Linux Hardening
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx@kernel.org>
To: Martin Uecker <uecker@tugraz.at>,
	 Christopher Bazley <chris.bazley.wg14@gmail.com>,
	Alex Celeste <alexg.nvfp@gmail.com>,
	 Joseph Myers <josmyers@redhat.com>,
	Aaron Ballman <aaron@aaronballman.com>
Cc: Douglas McIlroy <douglas.mcilroy@dartmouth.edu>,
	 Bruno Haible <bruno@clisp.org>, Paul Eggert <eggert@cs.ucla.edu>,
	 Florian Weimer <fweimer@redhat.com>,
	Jonathan Corbet <corbet@lwn.net>, Kees Cook <kees@kernel.org>,
	 Eric Biggers <ebiggers@kernel.org>,
	Ard Biesheuvel <ardb@kernel.org>,
	 Daniel Thompson <danielt@kernel.org>,
	Daniel Lundin <daniel.lundin.mail@gmail.com>,
	 "Valentin V. Bartenev" <vbartenev@gmail.com>,
	Andrew Clayton <andrew@digital-domain.net>,
	 "Brian W. Kernighan" <bwk@cs.princeton.edu>,
	"G. Branden Robinson" <branden@debian.org>,
	 "Basil L. Contovounesios" <basil@contovou.net>,
	"Jason A. Donenfeld" <jason@zx2c4.com>,
	 Linus Torvalds <torvalds@linux-foundation.org>,
	onf <onf@disroot.org>, Rich Felker <dalias@libc.org>,
	 linux-hardening@vger.kernel.org,
	Alejandro Colomar <alx@kernel.org>
Subject: [RFC v3 2/6] alx-0076r3 - incompatible array parameters
Date: Mon, 26 Jan 2026 13:48:35 +0100	[thread overview]
Message-ID: <aXdioPaMhmF3PyZo@devuan> (raw)
In-Reply-To: <aXdhh1r7ePA5SrIE@devuan>

[-- Attachment #1: Type: text/plain, Size: 7063 bytes --]

Name
	alx-0076r3 - incompatible array parameters

Principles
	-  Uphold the character of the language.
	-  Codify existing practice to address evident deficiencies.
	-  Avoid quiet changes.
	-  Enable secure programming.

	And from previous charters:

	C23:
	-  APIs should be self-documenting when possible.

Category
	Language; array parameters.

Authors
	Alejandro Colomar <alx@kernel.org>
	Martin Uecker <uecker@tugraz.at>

	Acked-by: Doug McIlroy
	Acked-by: Andrew Clayton <ac@sigsegv.uk>

History
	<https://www.alejandro-colomar.es/src/alx/alx/std/wg14/alx-0076.git/>

	r0 (2026-01-23):
	-  Initial draft.

	r1 (2026-01-24):
	-  Add a principle.
	-  Don't break parameters of function type (but see alx-0077).
	-  Document that this also applies to [static n].
	-  Remove superfluous line in diff.
	-  Clarify that the array type is incomplete.
	-  Add 'See also'.
	-  ffix

	r2 (2026-01-25):
	-  Take the two examples from N2906 (reordered).
	-  Add Martin as co-author.

	r3 (2026-01-26):
	-  Acked-by.
	-  tfix

Abstract
	The following two function prototypes violate a constraint:

		void f(int (*p)[2]);
		void f(int (*p)[2+1]);

	The following two function prototypes should be unacceptable,
	for consistency:

		void g(int a[2]);
		void g(int a[2+1]);

Discussion
	The prototypes above are obviously wrong.  If a program is
	compiled containing the above prototypes for g(), the programmer
	is clearly very confused, and there are high chances that the
	program will eventually overflow a buffer.

	Currently, a program containing

		void g(int a[2]);
		void g(int a[2+1]);

	is a valid program, because the array parameters are adjusted to
	pointers before checking for type compatibility.

	The standard (n3685) says in 6.7.7.4p3:

		Two function types are compatible
		if and only if all of the following hold:
			--  They specify compatible return types.
			--  The parameter type lists
			    agree in the number of parameters
			    and in whether the function is variadic or not.
			--  The corresponding parameters have compatible types.
		In the determination
		of type compatibility
		and of a composite type,
		each parameter declared with function or array type
		is taken as having
		the adjusted type
		and each parameter declared with qualified type
		is taken as having
		the unqualified version of its declared type.

	We could easily tweak that paragraph to say that the
	compatibility is tested before adjustment.  That would need a
	teak to make pointers compatible with arrays, though.  It would
	also need a tweak so that in function calls we still use the
	adjusted type.

    [static n]
	This change also makes the following be not compatible:

		void h(int a[static 2]);
		void h(int a[static 2+1]);

	This is intentional.  A future proposal will propose that
	a function declared with a parameter [static n] is not allowed
	to access more than n elements (and the current proposal already
	kind-of implies this).  Another future proposal will make
	[static n] and [n] equivalent, except for nullability of the
	pointer.

Prior art
	Both GCC and Clang already diagnose such code:

		alx@devuan:~/tmp$ cat ap.c 
		void g(int a[2]);
		void g(int a[2+1]);
		alx@devuan:~/tmp$ gcc -Wall -S ap.c 
		ap.c:2:12: warning: argument 1 of type ‘int[3]’ with mismatched bound [-Warray-parameter=]
		    2 | void g(int a[2+1]);
		      |        ~~~~^~~~~~
		ap.c:1:12: note: previously declared as ‘int[2]’
		    1 | void g(int a[2]);
		      |        ~~~~^~~~
		alx@devuan:~/tmp$ clang -Weverything -S ap.c 
		ap.c:2:12: warning: argument 'a' of type 'int[3]' with
		      mismatched bound [-Warray-parameter]
		    2 | void g(int a[2+1]);
		      |            ^
		ap.c:1:12: note: previously declared as 'int[2]' here
		    1 | void g(int a[2]);
		      |            ^
		1 warning generated.

See also
	N2906 (Uecker; "Consistency of Parameters Declared as Arrays (updates N2779)")
	That proposal is superseded by this one, which achieves the same
	goal with significantly less complexity.

	alx-0077r0 - function parameters of function type
	<https://www.alejandro-colomar.es/src/alx/alx/std/wg14/alx-0077.git/>

Comments
	On 2026-01-25T18:19:02-0500, Douglas McIlroy wrote:
	> All six proposals look eminently reasonable.  They simplify
	> the language and remove surprises.  I suspect these proposals
	> will invalidate very few existing programs.  In any event, the
	> required corrections will improve the legibility and
	> maintainability of such programs.
	>
	> Doug McIlroy

	---

	On 2026-01-26T02:01:16+0000, Alex Celeste wrote:
	> Like Martin - these all seem eminently reasonable to me.

Proposed wording
	Based on N3685.

    6.5.3.3  Function calls
	@@ Constraints, p2
	 The number of arguments
	 shall agree with
	 the number of parameters.
	 Each argument shall have a type such that
	 its value may be assigned to
	 an object with
	 the unqualified version of the type of
	-its corresponding parameter.
	+its corresponding adjusted parameter.

    6.7.7.4  Function declarators
	@@ Semantics, p15
	 Two function types are compatible
	 if and only if all of the following hold:
		--  They specify compatible return types.
		--  The parameter type lists
		    agree in the number of parameters
		    and in whether the function is variadic or not.
		--  The corresponding parameters have compatible types.
	 In the determination
	 of type compatibility
	 and of a composite type,
	-each parameter declared with function or array type
	+each parameter declared with array type
	 is taken as having
	-the adjusted type
	+the non-adjusted type,
	+each parameter declared with function type    ## \
	+is taken as having                            ## -} See below.
	+the adjusted type,                            ## /
	+each parameter declared with "pointer to object <i>type</i>"
	+is taken as having incomplete "array of <i>type</i>"
	+(the opposite of adjustment),
	 and each parameter declared with qualified type
	 is taken as having
	 the unqualified version of its declared type.

	## The three lines about function type are to not change
	## anything regarding function types in this proposal, as this
	## proposal intends to be mostly uncontroversial.  However, it
	## is cruft that shouldn't be there.  There's another proposal
	## for removing that: alx-0077.  If that other proposal is
	## accepted before this one (or at the same time), remove these
	## three lines here.

	@@ p21+1
	+EXAMPLE 6
	+The following are all compatible function prototype declarators:
	+	void g(int x[const 5]);
	+	void g(int x[5]);          // composite type
	+	void g(int *restrict x);
	+	void g(int x[*]);
	+	void g(int x[]);

	@@ p21+2
	+EXAMPLE 7
	+The following function prototype declarators
	+are not compatible:
	+	void g(int x[5]);
	+	void g(int x[3]);

-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  parent reply	other threads:[~2026-01-26 12:48 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <aXZM5O2mU2e3LJBJ@devuan>
2026-01-26 12:48 ` [RFC v3 0/6] Improve function parameters in ISO C2y Alejandro Colomar
2026-01-26 12:48   ` [RFC v3 1/6] alx-0077r3 - disallow function parameters of function type Alejandro Colomar
2026-01-26 12:48   ` Alejandro Colomar [this message]
2026-01-26 12:48   ` [RFC v3 3/6] alx-0078r2 - [static n] shouldn't access more than n elements Alejandro Colomar
2026-01-28  9:54     ` Daniel Thompson
2026-01-28 15:14       ` Alejandro Colomar
2026-01-26 12:49   ` [RFC v3 4/6] alx-0079r2 - [static n] == non-null [n] Alejandro Colomar
2026-01-26 12:49   ` [RFC v3 5/6] alx-0081r2 - array parameters of 0 elements Alejandro Colomar
2026-01-28 10:14     ` Daniel Thompson
2026-01-28 15:21       ` Alejandro Colomar
2026-01-26 12:49   ` [RFC v3 6/6] alx-0080r1 - [static] without array length expression Alejandro Colomar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aXdioPaMhmF3PyZo@devuan \
    --to=alx@kernel.org \
    --cc=aaron@aaronballman.com \
    --cc=alexg.nvfp@gmail.com \
    --cc=andrew@digital-domain.net \
    --cc=ardb@kernel.org \
    --cc=basil@contovou.net \
    --cc=branden@debian.org \
    --cc=bruno@clisp.org \
    --cc=bwk@cs.princeton.edu \
    --cc=chris.bazley.wg14@gmail.com \
    --cc=corbet@lwn.net \
    --cc=dalias@libc.org \
    --cc=daniel.lundin.mail@gmail.com \
    --cc=danielt@kernel.org \
    --cc=douglas.mcilroy@dartmouth.edu \
    --cc=ebiggers@kernel.org \
    --cc=eggert@cs.ucla.edu \
    --cc=fweimer@redhat.com \
    --cc=jason@zx2c4.com \
    --cc=josmyers@redhat.com \
    --cc=kees@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=onf@disroot.org \
    --cc=torvalds@linux-foundation.org \
    --cc=uecker@tugraz.at \
    --cc=vbartenev@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox