Linux SPARSE checker discussions
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: linux-sparse@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Bart Van Assche <bvanassche@acm.org>
Subject: [PATCH 70/73] pre-process: Support long token and string expansions dynamically
Date: Mon,  9 Nov 2026 12:32:56 -0800	[thread overview]
Message-ID: <20261109203259.362845-71-bvanassche@acm.org> (raw)
In-Reply-To: <20261109203259.362845-1-bvanassche@acm.org>

Dynamically resize token and string buffers in show_token_sequence(),
tokenize.c, and get_string_constant() in char.c, check allocation and size
bounds, increase MAX_STRING in token.h to 65535, and round oversized slab
allocations up to chunk multiples in allocate.c.

Prevent "too long token expansion" errors, 64 KB string literal truncation,
die("alloc too big") aborts, and fixed-buffer overflows when formatting,
stringifying, or concatenating deeply nested macro expansions such as those
found in modern Linux kernel headers.

Add a regression test in validation/long-string-expansion.c.

Fixes: fbc8230fa8c4 ("Larger buffer size for token concatenation")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 allocate.c                         | 27 ++++++++---
 allocate.h                         |  1 +
 char.c                             | 46 +++++++++++-------
 pre-process.c                      | 58 ++++++++++++++++------
 token.h                            |  2 +-
 tokenize.c                         | 78 +++++++++++++++++++++---------
 validation/long-string-expansion.c | 30 ++++++++++++
 7 files changed, 179 insertions(+), 63 deletions(-)
 create mode 100644 validation/long-string-expansion.c

diff --git a/allocate.c b/allocate.c
index 2aca1815e5f2..75cd8f3befef 100644
--- a/allocate.c
+++ b/allocate.c
@@ -30,6 +30,7 @@
  * efficient: allocate larger "blobs", and give out individual
  * small bits and pieces of it with no maintenance overhead.
  */
+#include <limits.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -60,7 +61,7 @@ void drop_all_allocations(struct allocator_struct *desc)
 	desc->freelist = NULL;
 	while (blob) {
 		struct allocation_blob *next = blob->next;
-		blob_free(blob, desc->chunking);
+		blob_free(blob, blob->size);
 		blob = next;
 	}
 }
@@ -97,22 +98,32 @@ void *allocate(struct allocator_struct *desc, unsigned int size)
 	desc->useful_bytes += size;
 	size = (size + alignment - 1) & ~(alignment-1);
 	if (!blob || blob->left < size) {
-		unsigned int offset, chunking = desc->chunking;
+		unsigned long offset, chunking = desc->chunking;
 		struct allocation_blob *newblob;
 
 		offset = offsetof(struct allocation_blob, data);
 		offset = (offset + alignment - 1) & ~(alignment-1);
-		if (size > chunking - offset)
-			die("alloc too big");
+		if (size > chunking - offset) {
+			unsigned long need = (unsigned long)size + offset;
+			chunking = (need + chunking - 1) & ~(chunking - 1);
+			if (chunking < need || chunking - offset > UINT_MAX)
+				die("alloc too big");
+		}
 		newblob = blob_alloc(chunking);
 		if (!newblob)
 			die("out of memory");
 		desc->total_bytes += chunking;
-		newblob->next = blob;
+		newblob->size = chunking;
+		newblob->left = chunking - offset;
+		newblob->offset = offset - offsetof(struct allocation_blob, data);
+		if (blob && blob->left > newblob->left - size) {
+			newblob->next = blob->next;
+			blob->next = newblob;
+		} else {
+			newblob->next = blob;
+			desc->blobs = newblob;
+		}
 		blob = newblob;
-		desc->blobs = newblob;
-		blob->left = chunking - offset;
-		blob->offset = offset - offsetof(struct allocation_blob, data);
 	}
 	retval = blob->data + blob->offset;
 	blob->offset += size;
diff --git a/allocate.h b/allocate.h
index a6d305371c28..be99d1053608 100644
--- a/allocate.h
+++ b/allocate.h
@@ -5,6 +5,7 @@
 
 struct allocation_blob {
 	struct allocation_blob *next;
+	unsigned long size;
 	unsigned int left, offset;
 	unsigned char data[];
 };
diff --git a/char.c b/char.c
index a0776b560e29..5614a887f095 100644
--- a/char.c
+++ b/char.c
@@ -1,3 +1,6 @@
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #include "target.h"
 #include "lib.h"
@@ -171,6 +174,22 @@ void get_char_constant(struct token *token, unsigned long long *val)
 	*val = v;
 }
 
+static void append_string_byte(char **buf, size_t *cap, size_t *len, char ch)
+{
+	if (*len >= INT_MAX - sizeof(struct string))
+		die("string too large");
+	if (*len + 1 > *cap) {
+		size_t new_cap = *cap ? *cap * 2 : 4096;
+		if (new_cap < *len + 1)
+			new_cap = *len + 1;
+		*buf = realloc(*buf, new_cap);
+		if (!*buf)
+			die("out of memory");
+		*cap = new_cap;
+	}
+	(*buf)[(*len)++] = ch;
+}
+
 struct token *get_string_constant(struct token *token, struct expression *expr)
 {
 	struct string *string = token->string;
@@ -178,8 +197,9 @@ struct token *get_string_constant(struct token *token, struct expression *expr)
 	int stringtype = token_type(token);
 	int is_wide = stringtype == TOKEN_WIDE_STRING;
 	int is_utf8 = stringtype == TOKEN_UTF8_STRING;
-	static char buffer[MAX_STRING];
-	int len = 0;
+	static char *buffer;
+	static size_t buf_size;
+	size_t len = 0;
 	int bits;
 	int esc_count = 0;
 
@@ -219,29 +239,21 @@ struct token *get_string_constant(struct token *token, struct expression *expr)
 			if (is_ucn && !is_wide) {
 				char utf8[4];
 				int i, n = encode_utf8(v, utf8);
-				for (i = 0; i < n; i++) {
-					if (len < MAX_STRING)
-						buffer[len] = utf8[i];
-					len++;
-				}
+				for (i = 0; i < n; i++)
+					append_string_byte(&buffer, &buf_size, &len, utf8[i]);
 			} else {
-				if (len < MAX_STRING)
-					buffer[len] = v;
-				len++;
+				append_string_byte(&buffer, &buf_size, &len, v);
 			}
 		}
 		token = token->next;
 	}
-	if (len > MAX_STRING) {
-		warning(token->pos, "trying to concatenate %d-character string (%d bytes max)", len, MAX_STRING);
-		len = MAX_STRING;
-	}
 
 	if (esc_count || len >= string->length) {
 		if (string->immutable || len >= string->length)	/* can't cannibalize */
-			string = __alloc_string(len+1);
-		string->length = len+1;
-		memcpy(string->data, buffer, len);
+			string = __alloc_string(len + 1);
+		string->length = len + 1;
+		if (len)
+			memcpy(string->data, buffer, len);
 		string->data[len] = '\0';
 	}
 	expr->string = string;
diff --git a/pre-process.c b/pre-process.c
index 8eb70ca7a1a4..1ea6c71b9a7e 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -34,6 +34,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdint.h>
 #include <time.h>
 #include <errno.h>
 #include <sys/stat.h>
@@ -420,38 +421,65 @@ static struct token *dup_list(struct token *list)
 
 static const char *show_token_sequence(struct token *token, int quote)
 {
-	static char buffer[MAX_STRING];
-	char *ptr = buffer;
-	int whitespace = 0;
+	static char *buffer;
+	static size_t buf_size;
+	size_t offset = 0;
+	size_t whitespace = 0;
 
 	if (!token && !quote)
 		return "<none>";
 	while (!eof_token(token)) {
 		const char *val = quote ? quote_token(token) : show_token(token);
-		int len = strlen(val);
-
-		if (ptr + whitespace + len >= buffer + sizeof(buffer)) {
-			sparse_error(token->pos, "too long token expansion");
-			break;
+		size_t len = strlen(val);
+		size_t needed;
+
+		if (len > SIZE_MAX - offset - whitespace - 1)
+			die("out of memory");
+		needed = offset + whitespace + len + 1;
+
+		if (needed > buf_size) {
+			size_t new_size = buf_size ? buf_size : 65536;
+			while (new_size < needed) {
+				if (new_size > SIZE_MAX / 2) {
+					new_size = needed;
+					break;
+				}
+				new_size *= 2;
+			}
+			buffer = realloc(buffer, new_size);
+			if (!buffer)
+				die("out of memory");
+			buf_size = new_size;
 		}
 
 		if (whitespace)
-			*ptr++ = ' ';
-		memcpy(ptr, val, len);
-		ptr += len;
+			buffer[offset++] = ' ';
+		memcpy(buffer + offset, val, len);
+		offset += len;
 		token = token->next;
 		whitespace = token->pos.whitespace;
 	}
-	*ptr = 0;
+	if (!buffer) {
+		buf_size = 64;
+		buffer = malloc(buf_size);
+		if (!buffer)
+			die("out of memory");
+	}
+	buffer[offset] = 0;
 	return buffer;
 }
 
 static struct token *stringify(struct token *arg)
 {
 	const char *s = show_token_sequence(arg, 1);
-	int size = strlen(s)+1;
-	struct token *token = __alloc_token(0);
-	struct string *string = __alloc_string(size);
+	size_t size = strlen(s) + 1;
+	struct token *token;
+	struct string *string;
+
+	if (size > INT_MAX - sizeof(struct string))
+		die("string too large");
+	token = __alloc_token(0);
+	string = __alloc_string(size);
 
 	memcpy(string->data, s, size);
 	string->length = size;
diff --git a/token.h b/token.h
index 998d83a123c9..e8276757ca5f 100644
--- a/token.h
+++ b/token.h
@@ -206,7 +206,7 @@ struct token {
 	};
 };
 
-#define MAX_STRING 8191
+#define MAX_STRING 65535
 
 static inline struct token *containing_token(struct token **p)
 {
diff --git a/tokenize.c b/tokenize.c
index 775c54667af7..95dad56a8096 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
+#include <limits.h>
 #include <stdint.h>
 
 #include "lib.h"
@@ -110,6 +111,25 @@ const char *show_ident(const struct ident *ident)
 	return buffer;
 }
 
+static char *grow_buffer(char **buf, size_t *cap, size_t needed)
+{
+	if (needed > *cap) {
+		size_t new_cap = *cap ? *cap : 4096;
+		while (new_cap < needed) {
+			if (new_cap > SIZE_MAX / 2) {
+				new_cap = needed;
+				break;
+			}
+			new_cap *= 2;
+		}
+		*buf = realloc(*buf, new_cap);
+		if (!*buf)
+			die("out of memory");
+		*cap = new_cap;
+	}
+	return *buf;
+}
+
 static char *charstr(char *ptr, unsigned char c, unsigned char escape, unsigned char next)
 {
 	if (isprint(c)) {
@@ -135,13 +155,18 @@ static char *charstr(char *ptr, unsigned char c, unsigned char escape, unsigned
 
 const char *show_string(const struct string *string)
 {
-	static char buffer[4 * MAX_STRING + 3];
+	static char *buffer;
+	static size_t buf_size;
+	size_t len;
 	char *ptr;
 	int i;
 
 	if (!string || !string->length)
 		return "<bad_string>";
-	ptr = buffer;
+	len = string->length;
+	if (len > (SIZE_MAX - 3) / 4)
+		die("out of memory");
+	ptr = grow_buffer(&buffer, &buf_size, 4 * len + 3);
 	*ptr++ = '"';
 	for (i = 0; i < string->length-1; i++) {
 		const char *p = string->data + i;
@@ -155,10 +180,15 @@ const char *show_string(const struct string *string)
 static const char *show_char(const char *s, size_t len, const char *prefix,
 			     char delim)
 {
-	static char buffer[MAX_STRING + 8];
-	char *p = buffer;
-	if (prefix) {
-		size_t plen = strlen(prefix);
+	static char *buffer;
+	static size_t buf_size;
+	size_t plen = prefix ? strlen(prefix) : 0;
+	char *p;
+
+	if (len > SIZE_MAX - plen - 3)
+		die("out of memory");
+	p = grow_buffer(&buffer, &buf_size, plen + len + 3);
+	if (plen) {
 		memcpy(p, prefix, plen);
 		p += plen;
 	}
@@ -173,11 +203,16 @@ static const char *show_char(const char *s, size_t len, const char *prefix,
 static const char *quote_char(const char *s, size_t len, const char *prefix,
 			      char delim)
 {
-	static char buffer[2 * MAX_STRING + 8];
+	static char *buffer;
+	static size_t buf_size;
+	size_t plen = prefix ? strlen(prefix) : 0;
 	size_t i;
-	char *p = buffer;
-	if (prefix) {
-		size_t plen = strlen(prefix);
+	char *p;
+
+	if (len > (SIZE_MAX - plen - 6) / 2)
+		die("out of memory");
+	p = grow_buffer(&buffer, &buf_size, plen + 2 * len + 6);
+	if (plen) {
 		memcpy(p, prefix, plen);
 		p += plen;
 	}
@@ -661,18 +696,20 @@ static int get_one_number(int c, int next, stream_t *stream)
 
 static int eat_string(int next, stream_t *stream, enum token_type type)
 {
-	static char buffer[MAX_STRING];
+	static char *buffer;
+	static size_t buf_size;
 	struct string *string;
 	struct token *token = stream->token;
-	int len = 0;
+	size_t len = 0;
 	int escape;
 	int want_hex = 0;
 	char delim = type < TOKEN_STRING ? '\'' : '"';
 
 	for (escape = 0; escape || next != delim; next = nextchar(stream)) {
-		if (len < MAX_STRING)
-			buffer[len] = next;
-		len++;
+		if (len >= INT_MAX - sizeof(struct string))
+			die("string too large");
+		grow_buffer(&buffer, &buf_size, len + 4 < 64 ? 64 : len + 4);
+		buffer[len++] = next;
 		if (next == '\n') {
 			warning(stream_pos(stream),
 				"missing terminating %c character", delim);
@@ -698,20 +735,17 @@ static int eat_string(int next, stream_t *stream, enum token_type type)
 	if (want_hex)
 		warning(stream_pos(stream),
 			"\\x used with no following hex digits");
-	if (len > MAX_STRING) {
-		warning(stream_pos(stream), "string too long (%d bytes, %d bytes max)", len, MAX_STRING);
-		len = MAX_STRING;
-	}
 	if (delim == '\'' && len && len <= 4) {
 		token_type(token) = type + len;
 		memset(buffer + len, '\0', 4 - len);
 		memcpy(token->embedded, buffer, 4);
 	} else {
 		token_type(token) = type;
-		string = __alloc_string(len+1);
-		memcpy(string->data, buffer, len);
+		string = __alloc_string(len + 1);
+		if (len)
+			memcpy(string->data, buffer, len);
 		string->data[len] = '\0';
-		string->length = len+1;
+		string->length = len + 1;
 		token->string = string;
 	}
 
diff --git a/validation/long-string-expansion.c b/validation/long-string-expansion.c
new file mode 100644
index 000000000000..5523ae966c74
--- /dev/null
+++ b/validation/long-string-expansion.c
@@ -0,0 +1,30 @@
+#define S16 "0123456789abcdef"
+#define S64 S16 S16 S16 S16
+#define S256 S64 S64 S64 S64
+#define S1024 S256 S256 S256 S256
+#define S4096 S1024 S1024 S1024 S1024
+#define S16384 S4096 S4096 S4096 S4096
+#define S65536 S16384 S16384 S16384 S16384
+
+#define STR_INNER(x) #x
+#define STR(x) STR_INNER(x)
+
+#define T4 a+a+a+a
+#define T16 T4+T4+T4+T4
+#define T64 T16+T16+T16+T16
+#define T256 T64+T64+T64+T64
+#define T1024 T256+T256+T256+T256
+#define T4096 T1024+T1024+T1024+T1024
+#define T16384 T4096+T4096+T4096+T4096
+#define T65536 T16384+T16384+T16384+T16384
+
+/* Concatenated string literal > 65535 bytes */
+_Static_assert(sizeof(S65536 S16) == 65536 + 16 + 1, "concat > 64KB");
+
+/* Stringified macro expansion with escaped quotes > 65535 bytes */
+_Static_assert(sizeof(STR("q" T65536)) > 130000, "stringify > 64KB");
+
+/*
+ * check-name: long-string-expansion
+ * check-command: sparse $file
+ */

  parent reply	other threads:[~2026-11-09 20:33 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 20:31 Bart Van Assche
2026-11-09 20:31 ` [PATCH 01/73] Makefile: Pass '--' to rm in clean target to handle dash-prefixed files Bart Van Assche
2026-11-09 20:31 ` [PATCH 02/73] sparse-llvm: Use LLVMCreateBuilderForModule() with LLVM 24 and later Bart Van Assche
2026-11-09 20:31 ` [PATCH 03/73] typeof_unqual: Strip qualifiers and address space from types and arrays Bart Van Assche
2026-11-09 20:31 ` [PATCH 04/73] bitfield: Pack consecutive _Bool bitfields into byte containers Bart Van Assche
2026-11-09 20:31 ` [PATCH 05/73] allocate: Harden slab allocation bounds, zeroing, and mmap checks Bart Van Assche
2026-11-09 20:31 ` [PATCH 06/73] tokenize: Support 4096-byte identifiers and fix escape bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 07/73] pre-process: Fix macro expansion and include directive handling Bart Van Assche
2026-11-09 20:31 ` [PATCH 08/73] options, lib: Harden warning buffers and command-line option parsing Bart Van Assche
2026-11-09 20:31 ` [PATCH 09/73] builtin: Fix atomic builtin type checking and object_size bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 10/73] parse, show-parse: Fix attribute propagation, enum overflow, and bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 11/73] target-openrisc: Set target_openrisc.mach to MACH_OPENRISC Bart Van Assche
2026-11-09 20:31 ` [PATCH 12/73] evaluate: Fix pointer arithmetic, incomplete types, and qualifiers Bart Van Assche
2026-11-09 20:31 ` [PATCH 13/73] expand: Fix static initializer folding and floating-point casts Bart Van Assche
2026-11-09 20:32 ` [PATCH 14/73] inline: Copy union cast types and VLA bounds when inlining Bart Van Assche
2026-11-09 20:32 ` [PATCH 15/73] linearize, flow: Fix asm operands, switch case bounds, and DSE Bart Van Assche
2026-11-09 20:32 ` [PATCH 16/73] memops, ssa: Walk parent insns in reverse and skip mixed-size SSA Bart Van Assche
2026-11-09 20:32 ` [PATCH 17/73] simplify: Prevent overflow on LLONG_MIN negation and fix simplifications Bart Van Assche
2026-11-09 20:32 ` [PATCH 18/73] sparse: Gate context failure warning on Wcontext and catch underflow Bart Van Assche
2026-11-09 20:32 ` [PATCH 19/73] ast-model: Return AST_N_COLUMNS and inspect child nodes lazily Bart Van Assche
2026-11-09 20:32 ` [PATCH 20/73] c2xml: Guard against recursive symbols and free xmlGetProp() string Bart Van Assche
2026-11-09 20:32 ` [PATCH 21/73] compile-i386: Fix buffer bounds, unsigned '<=' codegen, and null checks Bart Van Assche
2026-11-09 20:32 ` [PATCH 22/73] ctags: Fix line comparison order and handle SYM_RESTRICT and SYM_LABEL Bart Van Assche
2026-11-09 20:32 ` [PATCH 23/73] dissect: Unwrap array element type via base_type() Bart Van Assche
2026-11-09 20:32 ` [PATCH 24/73] example: Fix show_op() rotating buffer dimensions Bart Van Assche
2026-11-09 20:32 ` [PATCH 25/73] graph: Check PSEUDO_SYM before dereferencing insn->func->sym Bart Van Assche
2026-11-09 20:32 ` [PATCH 26/73] scheck: Fix slice() upper bit index calculation Bart Van Assche
2026-11-09 20:32 ` [PATCH 27/73] sparse-llvm: Support arbitrary struct member counts and fix operand types Bart Van Assche
2026-11-09 20:32 ` [PATCH 28/73] inline: Duplicate generic expressions instead of evaluating them Bart Van Assche
2026-11-09 20:32 ` [PATCH 29/73] lib: Avoid mutating fmt before va_start() in warning() Bart Van Assche
2026-11-09 20:32 ` [PATCH 30/73] cse, canon: Cast pointers to uintptr_t before relational comparison Bart Van Assche
2026-11-09 20:32 ` [PATCH 31/73] context: Add "conditional context increment" model Bart Van Assche
2026-11-09 20:32 ` [PATCH 32/73] expand: Simplify signed constants early Bart Van Assche
2026-11-09 20:32 ` [PATCH 33/73] bitwise: Allow all-bits-set as a restricted value Bart Van Assche
2026-11-09 20:32 ` [PATCH 34/73] bitwise: Allow restricted ordered compares with unrestricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 35/73] bitwise: Keep unrestricted values unrestricted after a cast Bart Van Assche
2026-11-09 20:32 ` [PATCH 36/73] bitwise: Don't remove MOD_SPECIFIER from 'bitwise' types Bart Van Assche
2026-11-09 20:32 ` [PATCH 37/73] bitwise: Allow both regular casts and forced casts for restricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 38/73] clang-format: Add .clang-format configuration file Bart Van Assche
2026-11-09 20:32 ` [PATCH 39/73] options: Add support for -std=c23, -std=c2x and -std=gnu23 Bart Van Assche
2026-11-09 20:32 ` [PATCH 40/73] preprocessor: Add support for #elifdef and #elifndef Bart Van Assche
2026-11-09 20:32 ` [PATCH 41/73] preprocessor: Add support for __has_include and __has_include_next Bart Van Assche
2026-11-09 20:32 ` [PATCH 42/73] c23: Add support for static_assert, alignas, alignof, thread_local Bart Van Assche
2026-11-09 20:32 ` [PATCH 43/73] c23: Add support for bool, true, and false keywords Bart Van Assche
2026-11-09 20:32 ` [PATCH 44/73] c23: Add support for nullptr and nullptr_t Bart Van Assche
2026-11-09 20:32 ` [PATCH 45/73] c23: Add support for digit separators in numeric literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 46/73] c23: Support unnamed parameters in function definitions Bart Van Assche
2026-11-09 20:32 ` [PATCH 47/73] c23: Support variadic functions without named parameters Bart Van Assche
2026-11-09 20:32 ` [PATCH 48/73] c23: Support labels before declarations and at block ends Bart Van Assche
2026-11-09 20:32 ` [PATCH 49/73] c23: Support auto type inference Bart Van Assche
2026-11-09 20:32 ` [PATCH 50/73] c23: Support constexpr object specifier Bart Van Assche
2026-11-09 20:32 ` [PATCH 51/73] c23: Support enumerations with fixed underlying types Bart Van Assche
2026-11-09 20:32 ` [PATCH 52/73] c23: Support standard [[]] attribute syntax Bart Van Assche
2026-11-09 20:32 ` [PATCH 53/73] preprocessor: Add support for __has_c_attribute Bart Van Assche
2026-11-09 20:32 ` [PATCH 54/73] c23: Support empty initializer braces {} Bart Van Assche
2026-11-09 20:32 ` [PATCH 55/73] preprocessor: Add support for __has_embed Bart Van Assche
2026-11-09 20:32 ` [PATCH 56/73] preprocessor: Add support for #embed directive Bart Van Assche
2026-11-09 20:32 ` [PATCH 57/73] c23: Add support for u8 character constants and string literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 58/73] preprocessor: Add support for __VA_OPT__ Bart Van Assche
2026-11-09 20:32 ` [PATCH 59/73] c23: Treat empty parameter list () as (void) and reject K&R functions Bart Van Assche
2026-11-09 20:32 ` [PATCH 60/73] c23: Support storage-class specifiers in compound literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 61/73] c23: Add support for _BitInt(N) Bart Van Assche
2026-11-09 20:32 ` [PATCH 62/73] enum: Support machine mode attributes on enumeration types Bart Van Assche
2026-11-09 20:32 ` [PATCH 63/73] enum: Support __attribute__((packed)) " Bart Van Assche
2026-11-09 20:32 ` [PATCH 64/73] expand: Ignore top-level non-array address space in compare_types() Bart Van Assche
2026-11-09 20:32 ` [PATCH 65/73] builtin: Support __builtin_infer_alloc_token() as a size_t ICE Bart Van Assche
2026-11-09 20:32 ` [PATCH 66/73] builtin: Add support for Linux kernel compiler builtins Bart Van Assche
2026-11-09 20:32 ` [PATCH 67/73] builtin: Add support for __builtin_has_attribute() Bart Van Assche
2026-11-09 20:32 ` [PATCH 68/73] cleanup: Support __attribute__((cleanup(...))) in linearize and -Wcontext Bart Van Assche
2026-11-09 20:32 ` [PATCH 69/73] builtin: Do not evaluate __builtin_clz(0) and __builtin_ctz(0) Bart Van Assche
2026-11-09 20:32 ` Bart Van Assche [this message]
2026-11-09 20:32 ` [PATCH 71/73] x86: Undefine conflicting bitness macros when parsing -m flags Bart Van Assche
2026-11-09 20:32 ` [PATCH 72/73] evaluate: Accept conditional expressions with only one void side Bart Van Assche
2026-11-09 20:32 ` [PATCH 73/73] ci: Add Linux kernel GitHub Actions workflow and build script Bart Van Assche

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=20261109203259.362845-71-bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /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