Linux kbuild/kconfig development
 help / color / mirror / Atom feed
* [PATCH 0/4] kconfig: improve input validation for numeric options
@ 2026-08-29 17:18 Julian Braha
  2026-08-29 17:18 ` [PATCH 1/4] kconfig: promote invalid numeric reference from warning to error Julian Braha
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Julian Braha @ 2026-08-29 17:18 UTC (permalink / raw)
  To: nathan, nsc
  Cc: nico, rdunlap, grahamr, kees, pengpeng, vegard.nossum,
	linux-kernel, linux-kbuild, Julian Braha

This series improves checks for invalid values of 'int' and 'hex' config
options in the Kconfig interpreter.

Tests are added for all new warnings and errors.

Patch 1/4 promotes an existing warning to an error, for attempting to use
a non-numeric option to set a numeric option's value. This warning did not
have a test, but one is added with the promotion to error.

Patch 2/4 adds a check that the constant values for numerics are within
the bounds of the type (64-bit signed integer for 'int', and 64-bit
unsigned integer for 'hex'). This prevents silent failures, for example in
comparisons.

Patch 3/4 adds a check that 'int' and 'hex' options aren't used to set
each other's values. Since the values are naively reused from their
internal string representations, this currently also leads to later silent
failures. 

Finally, patch 4/4 rejects out-of-bounds numeric values from the Kconfig
frontends and adds a warning upon reading in an existing .config file
with one of these values. In the future, this warning should be promoted
to an error.

Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
Julian Braha (4):
  kconfig: promote invalid numeric reference from warning to error
  kconfig: check for out-of-bounds numeric constants
  kconfig: check for hex and int mismatches
  kconfig: prevent out-of-bounds user input for numeric options

 scripts/kconfig/confdata.c                    |  6 ++
 scripts/kconfig/lkc.h                         |  2 +-
 scripts/kconfig/lkc_proto.h                   |  1 +
 scripts/kconfig/menu.c                        | 68 ++++++++++++----
 scripts/kconfig/parser.y                      |  2 +-
 scripts/kconfig/symbol.c                      | 20 +++++
 scripts/kconfig/tests/err_num_bounds/Kconfig  | 79 +++++++++++++++++++
 .../kconfig/tests/err_num_bounds/__init__.py  | 12 +++
 .../tests/err_num_bounds/expected_stderr      | 10 +++
 .../kconfig/tests/err_num_mismatch/Kconfig    | 38 +++++++++
 .../tests/err_num_mismatch/__init__.py        |  9 +++
 .../tests/err_num_mismatch/expected_stderr    |  4 +
 .../tests/err_num_non_numeric_ref/Kconfig     | 75 ++++++++++++++++++
 .../tests/err_num_non_numeric_ref/__init__.py |  9 +++
 .../err_num_non_numeric_ref/expected_stderr   | 16 ++++
 scripts/kconfig/tests/warn_num_bounds/Kconfig | 24 ++++++
 .../kconfig/tests/warn_num_bounds/__init__.py | 25 ++++++
 scripts/kconfig/tests/warn_num_bounds/config  |  7 ++
 .../tests/warn_num_bounds/expected_config     | 11 +++
 .../warn_num_bounds/expected_config_stderr    |  3 +
 .../warn_num_bounds/expected_frontend_config  | 11 +++
 .../warn_num_bounds/expected_frontend_stderr  |  0
 22 files changed, 413 insertions(+), 19 deletions(-)
 create mode 100644 scripts/kconfig/tests/err_num_bounds/Kconfig
 create mode 100644 scripts/kconfig/tests/err_num_bounds/__init__.py
 create mode 100644 scripts/kconfig/tests/err_num_bounds/expected_stderr
 create mode 100644 scripts/kconfig/tests/err_num_mismatch/Kconfig
 create mode 100644 scripts/kconfig/tests/err_num_mismatch/__init__.py
 create mode 100644 scripts/kconfig/tests/err_num_mismatch/expected_stderr
 create mode 100644 scripts/kconfig/tests/err_num_non_numeric_ref/Kconfig
 create mode 100644 scripts/kconfig/tests/err_num_non_numeric_ref/__init__.py
 create mode 100644 scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/Kconfig
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/__init__.py
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/config
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_config
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_config_stderr
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_frontend_config
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_frontend_stderr

-- 
2.55.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] kconfig: promote invalid numeric reference from warning to error
  2026-08-29 17:18 [PATCH 0/4] kconfig: improve input validation for numeric options Julian Braha
@ 2026-08-29 17:18 ` Julian Braha
  2026-08-29 17:19 ` [PATCH 2/4] kconfig: check for out-of-bounds numeric constants Julian Braha
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Julian Braha @ 2026-08-29 17:18 UTC (permalink / raw)
  To: nathan, nsc
  Cc: nico, rdunlap, grahamr, kees, pengpeng, vegard.nossum,
	linux-kernel, linux-kbuild, Julian Braha

The Kconfig interpreter already warns if a numeric option attempts to use
a non-numeric option (bool, tristate, or string) to set its value (for
example, with a 'default' or 'range').

Since there is nowhere in the tree that attempts this, we can safely
promote this check from warning to error.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
 scripts/kconfig/lkc.h                         |  2 +-
 scripts/kconfig/menu.c                        | 39 ++++++----
 scripts/kconfig/parser.y                      |  2 +-
 .../tests/err_num_non_numeric_ref/Kconfig     | 75 +++++++++++++++++++
 .../tests/err_num_non_numeric_ref/__init__.py |  9 +++
 .../err_num_non_numeric_ref/expected_stderr   | 14 ++++
 6 files changed, 126 insertions(+), 15 deletions(-)
 create mode 100644 scripts/kconfig/tests/err_num_non_numeric_ref/Kconfig
 create mode 100644 scripts/kconfig/tests/err_num_non_numeric_ref/__init__.py
 create mode 100644 scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr

diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 7e6f6ca299cf..bbc99f75b416 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -89,7 +89,7 @@ struct property *menu_add_prompt(enum prop_type type, const char *prompt,
 				 struct expr *dep);
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
-void menu_finalize(void);
+int menu_finalize(void);
 void menu_set_type(int type);
 
 extern struct menu rootmenu;
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 9c079e92a9ed..99a57ce0fdc9 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -240,11 +240,12 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
 	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
 }
 
-static void sym_check_prop(struct symbol *sym)
+static int sym_check_prop(struct symbol *sym)
 {
 	struct property *prop;
 	struct symbol *sym2;
 	char *use;
+	int errors = 0;
 
 	for (prop = sym->prop; prop; prop = prop->next) {
 		switch (prop->type) {
@@ -258,10 +259,13 @@ static void sym_check_prop(struct symbol *sym)
 				break;
 			sym2 = prop_get_symbol(prop);
 			if (sym->type == S_HEX || sym->type == S_INT) {
-				if (!menu_validate_number(sym, sym2))
-					prop_warn(prop,
-					    "'%s': number is invalid",
-					    sym->name);
+				if (!menu_validate_number(sym, sym2)) {
+					fprintf(stderr,
+						"%s:%d: error: '%s': number is invalid\n",
+						prop->filename, prop->lineno,
+						sym->name);
+					errors++;
+				}
 			}
 			if (sym_is_choice(sym)) {
 				struct menu *choice = sym_get_choice_menu(sym2);
@@ -293,21 +297,28 @@ static void sym_check_prop(struct symbol *sym)
 				prop_warn(prop, "range is only allowed "
 						"for int or hex symbols");
 			if (!menu_validate_number(sym, prop->expr->left.sym) ||
-			    !menu_validate_number(sym, prop->expr->right.sym))
-				prop_warn(prop, "range is invalid");
+			    !menu_validate_number(sym, prop->expr->right.sym)) {
+				fprintf(stderr,
+					"%s:%d: error: range is invalid\n",
+					prop->filename, prop->lineno);
+				errors++;
+			}
 			break;
 		default:
 			;
 		}
 	}
+
+	return errors;
 }
 
-static void _menu_finalize(struct menu *parent, bool inside_choice)
+static int _menu_finalize(struct menu *parent, bool inside_choice)
 {
 	struct menu *menu, *last_menu;
 	struct symbol *sym;
 	struct property *prop;
 	struct expr *basedep, *dep, *dep2;
+	int errors = 0;
 
 	sym = parent->sym;
 	if (parent->list) {
@@ -393,7 +404,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
 		 * moving on
 		 */
 		for (menu = parent->list; menu; menu = menu->next)
-			_menu_finalize(menu, sym && sym_is_choice(sym));
+			errors += _menu_finalize(menu, sym && sym_is_choice(sym));
 	} else if (!inside_choice && sym) {
 		/*
 		 * Automatic submenu creation. If sym is a symbol and A, B, C,
@@ -461,7 +472,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
 			}
 			/* Superset, put in submenu */
 		next:
-			_menu_finalize(menu, false);
+			errors += _menu_finalize(menu, false);
 			menu->parent = parent;
 			last_menu = menu;
 		}
@@ -519,14 +530,16 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
 			menu_warn(parent, "config symbol defined without type");
 
 		/* Check properties connected to this symbol */
-		sym_check_prop(sym);
+		errors += sym_check_prop(sym);
 		sym->flags |= SYMBOL_WARNED;
 	}
+
+	return errors;
 }
 
-void menu_finalize(void)
+int menu_finalize(void)
 {
-	_menu_finalize(&rootmenu, false);
+	return _menu_finalize(&rootmenu, false);
 }
 
 bool menu_has_prompt(const struct menu *menu)
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index 5fb6f07b6ad2..40ceb9908c6f 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -587,7 +587,7 @@ void conf_parse(const char *name)
 		menu_add_prompt(P_MENU, "Main menu", NULL);
 	}
 
-	menu_finalize();
+	yynerrs += menu_finalize();
 
 	menu_for_each_entry(menu) {
 		struct menu *child;
diff --git a/scripts/kconfig/tests/err_num_non_numeric_ref/Kconfig b/scripts/kconfig/tests/err_num_non_numeric_ref/Kconfig
new file mode 100644
index 000000000000..0ca7a4a460f6
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_non_numeric_ref/Kconfig
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test non-numeric symbol references from numeric symbols
+
+config BOOL_SOURCE
+	bool
+
+config TRISTATE_SOURCE
+	tristate
+
+config STRING_SOURCE
+	string
+
+# Invalid int defaults
+
+config INT_DEFAULT_BOOL
+	int
+	default BOOL_SOURCE
+
+config INT_DEFAULT_TRISTATE
+	int
+	default TRISTATE_SOURCE
+
+config INT_DEFAULT_STRING
+	int
+	default STRING_SOURCE
+
+# Invalid hex defaults
+
+config HEX_DEFAULT_BOOL
+	hex
+	default BOOL_SOURCE
+
+config HEX_DEFAULT_TRISTATE
+	hex
+	default TRISTATE_SOURCE
+
+config HEX_DEFAULT_STRING
+	hex
+	default STRING_SOURCE
+
+# Invalid int ranges
+
+config INT_RANGE_BOOL
+	int
+	range BOOL_SOURCE 1
+
+config INT_RANGE_TRISTATE
+	int
+	range TRISTATE_SOURCE 1
+
+config INT_RANGE_STRING
+	int
+	range STRING_SOURCE 1
+
+config INT_RANGE_MULTIPLE
+	int
+	range BOOL_SOURCE TRISTATE_SOURCE
+
+# Invalid hex ranges
+
+config HEX_RANGE_BOOL
+	hex
+	range BOOL_SOURCE 0x1
+
+config HEX_RANGE_TRISTATE
+	hex
+	range TRISTATE_SOURCE 0x1
+
+config HEX_RANGE_STRING
+	hex
+	range STRING_SOURCE 0x1
+
+config HEX_RANGE_MULTIPLE
+	hex
+	range BOOL_SOURCE TRISTATE_SOURCE
diff --git a/scripts/kconfig/tests/err_num_non_numeric_ref/__init__.py b/scripts/kconfig/tests/err_num_non_numeric_ref/__init__.py
new file mode 100644
index 000000000000..9632907abead
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_non_numeric_ref/__init__.py
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Reject nonnumeric symbol references from int and hex properties.
+"""
+
+
+def test(conf):
+    assert conf.olddefconfig() == 1
+    assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr b/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr
new file mode 100644
index 000000000000..4974ba2fcd9c
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr
@@ -0,0 +1,14 @@
+Kconfig:17: error: 'INT_DEFAULT_BOOL': number is invalid
+Kconfig:21: error: 'INT_DEFAULT_TRISTATE': number is invalid
+Kconfig:25: error: 'INT_DEFAULT_STRING': number is invalid
+Kconfig:31: error: 'HEX_DEFAULT_BOOL': number is invalid
+Kconfig:35: error: 'HEX_DEFAULT_TRISTATE': number is invalid
+Kconfig:39: error: 'HEX_DEFAULT_STRING': number is invalid
+Kconfig:45: error: range is invalid
+Kconfig:49: error: range is invalid
+Kconfig:53: error: range is invalid
+Kconfig:57: error: range is invalid
+Kconfig:63: error: range is invalid
+Kconfig:67: error: range is invalid
+Kconfig:71: error: range is invalid
+Kconfig:75: error: range is invalid
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] kconfig: check for out-of-bounds numeric constants
  2026-08-29 17:18 [PATCH 0/4] kconfig: improve input validation for numeric options Julian Braha
  2026-08-29 17:18 ` [PATCH 1/4] kconfig: promote invalid numeric reference from warning to error Julian Braha
@ 2026-08-29 17:19 ` Julian Braha
  2026-08-29 17:19 ` [PATCH 3/4] kconfig: check for hex and int mismatches Julian Braha
  2026-08-29 17:19 ` [PATCH 4/4] kconfig: prevent out-of-bounds user input for numeric options Julian Braha
  3 siblings, 0 replies; 6+ messages in thread
From: Julian Braha @ 2026-08-29 17:19 UTC (permalink / raw)
  To: nathan, nsc
  Cc: nico, rdunlap, grahamr, kees, pengpeng, vegard.nossum,
	linux-kernel, linux-kbuild, Julian Braha

The Kconfig interpreter internally represents constants as strings, then
attempts to parse them as 64-bit signed integers for 'int' options, and
64-bit unsigned integers for 'hex' options.

However, there is currently no check that the conversion succeeds, leading
to failures when the values are actually used. For example:

  config LARGE_INT
    int
    default 10000000000000000000

  config BUGGED_INT_COMPARISON
    bool
    default y if LARGE_INT < 2

Obviously 10000000000000000000 is larger than 2, but the Kconfig
interpreter will fallback to comparing the two values with strcmp() after
the numeric conversion fails, causing the first character, '1', to be
compared with '2', and giving the wrong result.

Since none of these out-of-bounds values are used as constants anywhere in
the tree, we can already make these error out.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
 scripts/kconfig/menu.c                        | 60 ++++++++++----
 scripts/kconfig/tests/err_num_bounds/Kconfig  | 79 +++++++++++++++++++
 .../kconfig/tests/err_num_bounds/__init__.py  | 12 +++
 .../tests/err_num_bounds/expected_stderr      | 10 +++
 .../err_num_non_numeric_ref/expected_stderr   | 30 +++----
 5 files changed, 160 insertions(+), 31 deletions(-)
 create mode 100644 scripts/kconfig/tests/err_num_bounds/Kconfig
 create mode 100644 scripts/kconfig/tests/err_num_bounds/__init__.py
 create mode 100644 scripts/kconfig/tests/err_num_bounds/expected_stderr

diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 99a57ce0fdc9..ede791a2fe1b 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -4,6 +4,7 @@
  */
 
 #include <ctype.h>
+#include <errno.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -234,10 +235,46 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
 	menu_add_prop(type, expr_alloc_symbol(sym), dep);
 }
 
-static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
+/* Validate the sym2 value for numeric sym. */
+static int menu_validate_number(struct symbol *sym, struct symbol *sym2,
+				const struct property *prop)
 {
-	return sym2->type == S_INT || sym2->type == S_HEX ||
-	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
+	const char *type_bounds;
+
+	if (sym->type != S_INT && sym->type != S_HEX)
+		return 0;
+
+	if (sym2->type == S_INT || sym2->type == S_HEX)
+		return 0;
+
+	if (sym2->type != S_UNKNOWN ||
+		!sym_string_valid(sym, sym2->name)) {
+		fprintf(stderr, "%s:%d: error: '%s' is an invalid value for '%s'\n",
+			prop->filename, prop->lineno, sym2->name,
+			sym_type_name(sym->type));
+		return 1;
+	}
+
+	errno = 0;
+	if (sym->type == S_INT) {
+		type_bounds = "64-bit signed integer";
+		strtoll(sym2->name, NULL, 10);
+	} else {
+		/* hex */
+		type_bounds = "64-bit unsigned integer";
+		strtoull(sym2->name, NULL, 16);
+	}
+
+	if (errno == ERANGE) {
+		fprintf(stderr,
+			"%s:%d: error: %s constant '%s' is outside the %s bounds\n",
+			prop->filename, prop->lineno, sym_type_name(sym->type),
+			sym2->name, type_bounds);
+
+		return 1;
+	}
+
+	return 0;
 }
 
 static int sym_check_prop(struct symbol *sym)
@@ -259,13 +296,7 @@ static int sym_check_prop(struct symbol *sym)
 				break;
 			sym2 = prop_get_symbol(prop);
 			if (sym->type == S_HEX || sym->type == S_INT) {
-				if (!menu_validate_number(sym, sym2)) {
-					fprintf(stderr,
-						"%s:%d: error: '%s': number is invalid\n",
-						prop->filename, prop->lineno,
-						sym->name);
-					errors++;
-				}
+				errors += menu_validate_number(sym, sym2, prop);
 			}
 			if (sym_is_choice(sym)) {
 				struct menu *choice = sym_get_choice_menu(sym2);
@@ -296,13 +327,8 @@ static int sym_check_prop(struct symbol *sym)
 			if (sym->type != S_INT && sym->type != S_HEX)
 				prop_warn(prop, "range is only allowed "
 						"for int or hex symbols");
-			if (!menu_validate_number(sym, prop->expr->left.sym) ||
-			    !menu_validate_number(sym, prop->expr->right.sym)) {
-				fprintf(stderr,
-					"%s:%d: error: range is invalid\n",
-					prop->filename, prop->lineno);
-				errors++;
-			}
+			errors += menu_validate_number(sym, prop->expr->left.sym, prop);
+			errors += menu_validate_number(sym, prop->expr->right.sym, prop);
 			break;
 		default:
 			;
diff --git a/scripts/kconfig/tests/err_num_bounds/Kconfig b/scripts/kconfig/tests/err_num_bounds/Kconfig
new file mode 100644
index 000000000000..c439366c03b6
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_bounds/Kconfig
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test bounds checks for 'int' and 'hex' constants
+
+config INT_SOURCE
+	int
+
+config HEX_SOURCE
+	hex
+
+config BOOL_SOURCE
+	bool
+
+# Valid values at the limits of the type
+
+config INT_MIN
+	int
+	default -9223372036854775808
+
+config INT_MAX
+	int
+	default 9223372036854775807
+
+config HEX_MIN
+	hex
+	default 0x0
+
+config HEX_MAX
+	hex
+	default 0xffffffffffffffff
+
+config INT_RANGE_LIMITS
+	int
+	range -9223372036854775808 9223372036854775807
+
+config HEX_RANGE_LIMITS
+	hex
+	range 0 0xffffffffffffffff
+
+config INT_FROM_INT
+	int
+	default INT_SOURCE
+
+config HEX_FROM_HEX
+	hex
+	default HEX_SOURCE
+
+# Constants outside the bounds
+
+config INT_DEFAULT_TOO_HIGH
+	int
+	default 10000000000000000000
+
+config INT_DEFAULT_TOO_LOW
+	int
+	default -9223372036854775809
+
+config INT_RANGE_TOO_HIGH
+	int
+	range 0 10000000000000000000
+
+config INT_RANGE_TOO_LOW
+	int
+	range -10000000000000000000 0
+
+config INT_RANGE_BOTH_OUTSIDE
+	int
+	range -9223372036854775809 10000000000000000000
+
+config HEX_DEFAULT_TOO_HIGH
+	hex
+	default 0x10000000000000000
+
+config HEX_RANGE_TOO_HIGH
+	hex
+	range 0 0x10000000000000000
+
+config HEX_RANGE_BOTH_TOO_HIGH
+	hex
+	range 0x10000000000000000 0x20000000000000000
diff --git a/scripts/kconfig/tests/err_num_bounds/__init__.py b/scripts/kconfig/tests/err_num_bounds/__init__.py
new file mode 100644
index 000000000000..72ac6aa24491
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_bounds/__init__.py
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Detect constants outside the 'int' and 'hex' bounds.
+
+An int constant must fit in a signed 64-bit integer, and a hex constant must
+fit in an unsigned 64-bit integer.
+"""
+
+
+def test(conf):
+    assert conf.olddefconfig() == 1
+    assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/err_num_bounds/expected_stderr b/scripts/kconfig/tests/err_num_bounds/expected_stderr
new file mode 100644
index 000000000000..3f06e13359ef
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_bounds/expected_stderr
@@ -0,0 +1,10 @@
+Kconfig:51: error: integer constant '10000000000000000000' is outside the 64-bit signed integer bounds
+Kconfig:55: error: integer constant '-9223372036854775809' is outside the 64-bit signed integer bounds
+Kconfig:59: error: integer constant '10000000000000000000' is outside the 64-bit signed integer bounds
+Kconfig:63: error: integer constant '-10000000000000000000' is outside the 64-bit signed integer bounds
+Kconfig:67: error: integer constant '-9223372036854775809' is outside the 64-bit signed integer bounds
+Kconfig:67: error: integer constant '10000000000000000000' is outside the 64-bit signed integer bounds
+Kconfig:71: error: hex constant '0x10000000000000000' is outside the 64-bit unsigned integer bounds
+Kconfig:75: error: hex constant '0x10000000000000000' is outside the 64-bit unsigned integer bounds
+Kconfig:79: error: hex constant '0x10000000000000000' is outside the 64-bit unsigned integer bounds
+Kconfig:79: error: hex constant '0x20000000000000000' is outside the 64-bit unsigned integer bounds
diff --git a/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr b/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr
index 4974ba2fcd9c..005f855ecbdd 100644
--- a/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr
+++ b/scripts/kconfig/tests/err_num_non_numeric_ref/expected_stderr
@@ -1,14 +1,16 @@
-Kconfig:17: error: 'INT_DEFAULT_BOOL': number is invalid
-Kconfig:21: error: 'INT_DEFAULT_TRISTATE': number is invalid
-Kconfig:25: error: 'INT_DEFAULT_STRING': number is invalid
-Kconfig:31: error: 'HEX_DEFAULT_BOOL': number is invalid
-Kconfig:35: error: 'HEX_DEFAULT_TRISTATE': number is invalid
-Kconfig:39: error: 'HEX_DEFAULT_STRING': number is invalid
-Kconfig:45: error: range is invalid
-Kconfig:49: error: range is invalid
-Kconfig:53: error: range is invalid
-Kconfig:57: error: range is invalid
-Kconfig:63: error: range is invalid
-Kconfig:67: error: range is invalid
-Kconfig:71: error: range is invalid
-Kconfig:75: error: range is invalid
+Kconfig:17: error: 'BOOL_SOURCE' is an invalid value for 'integer'
+Kconfig:21: error: 'TRISTATE_SOURCE' is an invalid value for 'integer'
+Kconfig:25: error: 'STRING_SOURCE' is an invalid value for 'integer'
+Kconfig:31: error: 'BOOL_SOURCE' is an invalid value for 'hex'
+Kconfig:35: error: 'TRISTATE_SOURCE' is an invalid value for 'hex'
+Kconfig:39: error: 'STRING_SOURCE' is an invalid value for 'hex'
+Kconfig:45: error: 'BOOL_SOURCE' is an invalid value for 'integer'
+Kconfig:49: error: 'TRISTATE_SOURCE' is an invalid value for 'integer'
+Kconfig:53: error: 'STRING_SOURCE' is an invalid value for 'integer'
+Kconfig:57: error: 'BOOL_SOURCE' is an invalid value for 'integer'
+Kconfig:57: error: 'TRISTATE_SOURCE' is an invalid value for 'integer'
+Kconfig:63: error: 'BOOL_SOURCE' is an invalid value for 'hex'
+Kconfig:67: error: 'TRISTATE_SOURCE' is an invalid value for 'hex'
+Kconfig:71: error: 'STRING_SOURCE' is an invalid value for 'hex'
+Kconfig:75: error: 'BOOL_SOURCE' is an invalid value for 'hex'
+Kconfig:75: error: 'TRISTATE_SOURCE' is an invalid value for 'hex'
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] kconfig: check for hex and int mismatches
  2026-08-29 17:18 [PATCH 0/4] kconfig: improve input validation for numeric options Julian Braha
  2026-08-29 17:18 ` [PATCH 1/4] kconfig: promote invalid numeric reference from warning to error Julian Braha
  2026-08-29 17:19 ` [PATCH 2/4] kconfig: check for out-of-bounds numeric constants Julian Braha
@ 2026-08-29 17:19 ` Julian Braha
  2026-08-29 17:19 ` [PATCH 4/4] kconfig: prevent out-of-bounds user input for numeric options Julian Braha
  3 siblings, 0 replies; 6+ messages in thread
From: Julian Braha @ 2026-08-29 17:19 UTC (permalink / raw)
  To: nathan, nsc
  Cc: nico, rdunlap, grahamr, kees, pengpeng, vegard.nossum,
	linux-kernel, linux-kbuild, Julian Braha

Using a numeric option of one type (e.g. 'int') to determine the value of
a different numeric type (e.g. 'hex') currently fails silently in various
ways if attempted, because the underlying string representation is naively
reused.

Example 1:

  config I
    int
    default -1

  config HEX_DEFAULT_INT
    hex
    default I

Here, HEX_DEFAULT_INT actually gets set to '0x-1', which is of course not
a valid hex value.

Example 2:

  config H
    hex
    default A

  config INT_DEFAULT_HEX
    int
    default H

Here, INT_DEFAULT_HEX actually gets set to 'A', without even converting
into the base-10 equivalent of 10. This value, 'A', is otherwise a
rejected int value if entered in the frontend, or read in from an existing
.config file.

These int-hex mismatches currently do not appear anywhere in the tree, so
it is already safe to make these error out.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
 scripts/kconfig/menu.c                        |  2 +-
 .../kconfig/tests/err_num_mismatch/Kconfig    | 38 +++++++++++++++++++
 .../tests/err_num_mismatch/__init__.py        |  9 +++++
 .../tests/err_num_mismatch/expected_stderr    |  4 ++
 4 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 scripts/kconfig/tests/err_num_mismatch/Kconfig
 create mode 100644 scripts/kconfig/tests/err_num_mismatch/__init__.py
 create mode 100644 scripts/kconfig/tests/err_num_mismatch/expected_stderr

diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index ede791a2fe1b..2d8b0c65ce1e 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -244,7 +244,7 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2,
 	if (sym->type != S_INT && sym->type != S_HEX)
 		return 0;
 
-	if (sym2->type == S_INT || sym2->type == S_HEX)
+	if (sym2->type == sym->type)
 		return 0;
 
 	if (sym2->type != S_UNKNOWN ||
diff --git a/scripts/kconfig/tests/err_num_mismatch/Kconfig b/scripts/kconfig/tests/err_num_mismatch/Kconfig
new file mode 100644
index 000000000000..8406f3bb6419
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_mismatch/Kconfig
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test 'int' and 'hex' symbols that reference each other
+
+config INT_SOURCE
+	int
+
+config HEX_SOURCE
+	hex
+
+# 'hex' reference from 'int'
+
+config INT_DEFAULT_HEX
+	int
+	default HEX_SOURCE
+
+config INT_RANGE_HEX
+	int
+	range HEX_SOURCE 1
+
+# A hex symbol must not reference an int symbol
+
+config HEX_DEFAULT_INT
+	hex
+	default INT_SOURCE
+
+config HEX_RANGE_INT
+	hex
+	range INT_SOURCE 0x1
+
+# Referencing the same type is valid
+
+config INT_FROM_INT
+	int
+	default INT_SOURCE
+
+config HEX_FROM_HEX
+	hex
+	range 0 HEX_SOURCE
diff --git a/scripts/kconfig/tests/err_num_mismatch/__init__.py b/scripts/kconfig/tests/err_num_mismatch/__init__.py
new file mode 100644
index 000000000000..275f2a6e9a5b
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_mismatch/__init__.py
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Reject direct references ('default' or 'range') between int and hex options.
+"""
+
+
+def test(conf):
+    assert conf.olddefconfig() == 1
+    assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/err_num_mismatch/expected_stderr b/scripts/kconfig/tests/err_num_mismatch/expected_stderr
new file mode 100644
index 000000000000..587c34467ae6
--- /dev/null
+++ b/scripts/kconfig/tests/err_num_mismatch/expected_stderr
@@ -0,0 +1,4 @@
+Kconfig:14: error: 'HEX_SOURCE' is an invalid value for 'integer'
+Kconfig:18: error: 'HEX_SOURCE' is an invalid value for 'integer'
+Kconfig:24: error: 'INT_SOURCE' is an invalid value for 'hex'
+Kconfig:28: error: 'INT_SOURCE' is an invalid value for 'hex'
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] kconfig: prevent out-of-bounds user input for numeric options
  2026-08-29 17:18 [PATCH 0/4] kconfig: improve input validation for numeric options Julian Braha
                   ` (2 preceding siblings ...)
  2026-08-29 17:19 ` [PATCH 3/4] kconfig: check for hex and int mismatches Julian Braha
@ 2026-08-29 17:19 ` Julian Braha
  2026-09-04 23:25   ` Nathan Chancellor
  3 siblings, 1 reply; 6+ messages in thread
From: Julian Braha @ 2026-08-29 17:19 UTC (permalink / raw)
  To: nathan, nsc
  Cc: nico, rdunlap, grahamr, kees, pengpeng, vegard.nossum,
	linux-kernel, linux-kbuild, Julian Braha

Currently, user input of out-of-bounds values for 'int' and 'hex' options
is possible, leading to later silent failures in Kconfig if that value is
used in a comparison, or a warning by GCC or error by Clang if used in the
C code.

Let's factor out the out-of-bounds check on constants, so that it can be
reused for checking user input.

The frontend will now reject an attempted user input of an out-of-bounds
numeric value, similarly to how a value outside the active 'range' already
does.

For migration of existing configurations, a .config file with an
out-of-bounds numeric value will be allowed for now, but will warn the
user when read in by confdata.c

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
 scripts/kconfig/confdata.c                    |  6 +++++
 scripts/kconfig/lkc_proto.h                   |  1 +
 scripts/kconfig/menu.c                        | 11 +++-----
 scripts/kconfig/symbol.c                      | 20 +++++++++++++++
 scripts/kconfig/tests/warn_num_bounds/Kconfig | 24 ++++++++++++++++++
 .../kconfig/tests/warn_num_bounds/__init__.py | 25 +++++++++++++++++++
 scripts/kconfig/tests/warn_num_bounds/config  |  7 ++++++
 .../tests/warn_num_bounds/expected_config     | 11 ++++++++
 .../warn_num_bounds/expected_config_stderr    |  3 +++
 .../warn_num_bounds/expected_frontend_config  | 11 ++++++++
 .../warn_num_bounds/expected_frontend_stderr  |  0
 11 files changed, 111 insertions(+), 8 deletions(-)
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/Kconfig
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/__init__.py
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/config
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_config
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_config_stderr
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_frontend_config
 create mode 100644 scripts/kconfig/tests/warn_num_bounds/expected_frontend_stderr

diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 4234a51d16fd..2227d89d6328 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -354,6 +354,12 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
 	case S_INT:
 	case S_HEX:
 		if (sym_string_valid(sym, p)) {
+			if (def != S_DEF_AUTO &&
+			    !sym_string_check_bounds(sym, p))
+				/* hex uses 64-bit unsigned integer */
+				conf_warning("value '%s' for %s is outside the 64-bit %s integer bounds",
+					     p, sym->name,
+					     sym->type == S_INT ? "signed" : "unsigned");
 			sym->def[def].val = xstrdup(p);
 			sym->flags |= def_flags;
 		} else {
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 8914b4e8f2a8..8b436c87ba4a 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -31,6 +31,7 @@ bool sym_set_tristate_value(struct symbol *sym,tristate tri);
 void choice_set_value(struct menu *choice, struct symbol *sym);
 tristate sym_toggle_tristate_value(struct symbol *sym);
 bool sym_string_valid(struct symbol *sym, const char *newval);
+bool sym_string_check_bounds(struct symbol *sym, const char *str);
 bool sym_string_within_range(struct symbol *sym, const char *str);
 bool sym_set_string_value(struct symbol *sym, const char *newval);
 bool sym_is_changeable(const struct symbol *sym);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 2d8b0c65ce1e..6f99216ee76d 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -4,7 +4,6 @@
  */
 
 #include <ctype.h>
-#include <errno.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -255,17 +254,13 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2,
 		return 1;
 	}
 
-	errno = 0;
-	if (sym->type == S_INT) {
+	if (sym->type == S_INT)
 		type_bounds = "64-bit signed integer";
-		strtoll(sym2->name, NULL, 10);
-	} else {
+	else
 		/* hex */
 		type_bounds = "64-bit unsigned integer";
-		strtoull(sym2->name, NULL, 16);
-	}
 
-	if (errno == ERANGE) {
+	if (!sym_string_check_bounds(sym, sym2->name)) {
 		fprintf(stderr,
 			"%s:%d: error: %s constant '%s' is outside the %s bounds\n",
 			prop->filename, prop->lineno, sym_type_name(sym->type),
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 7e81b3676ee9..2d1c021fa395 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -5,6 +5,7 @@
 
 #include <sys/types.h>
 #include <ctype.h>
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <regex.h>
@@ -711,6 +712,21 @@ bool sym_string_valid(struct symbol *sym, const char *str)
 	}
 }
 
+bool sym_string_check_bounds(struct symbol *sym, const char *str)
+{
+	errno = 0;
+
+	if (sym->type == S_INT)
+		strtoll(str, NULL, 10);
+	else if (sym->type == S_HEX)
+		strtoull(str, NULL, 16);
+	else
+		/* string */
+		return true;
+
+	return errno != ERANGE;
+}
+
 bool sym_string_within_range(struct symbol *sym, const char *str)
 {
 	struct property *prop;
@@ -722,6 +738,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
 	case S_INT:
 		if (!sym_string_valid(sym, str))
 			return false;
+		if (!sym_string_check_bounds(sym, str))
+			return false;
 		prop = sym_get_range_prop(sym);
 		if (!prop)
 			return true;
@@ -731,6 +749,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
 	case S_HEX:
 		if (!sym_string_valid(sym, str))
 			return false;
+		if (!sym_string_check_bounds(sym, str))
+			return false;
 		prop = sym_get_range_prop(sym);
 		if (!prop)
 			return true;
diff --git a/scripts/kconfig/tests/warn_num_bounds/Kconfig b/scripts/kconfig/tests/warn_num_bounds/Kconfig
new file mode 100644
index 000000000000..a810225a58a3
--- /dev/null
+++ b/scripts/kconfig/tests/warn_num_bounds/Kconfig
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0
+
+mainmenu "Numeric bounds test"
+
+config INT_TOO_LOW
+	int "Integer below its type bounds"
+
+config INT_TOO_HIGH
+	int "Integer above its type bounds"
+
+config HEX_TOO_HIGH
+	hex "Hex value above its type bounds"
+
+config INT_MIN
+	int "Minimum valid integer"
+
+config INT_MAX
+	int "Maximum valid integer"
+
+config HEX_MIN
+	hex "Minimum valid hex value"
+
+config HEX_MAX
+	hex "Maximum valid hex value"
diff --git a/scripts/kconfig/tests/warn_num_bounds/__init__.py b/scripts/kconfig/tests/warn_num_bounds/__init__.py
new file mode 100644
index 000000000000..db7518258217
--- /dev/null
+++ b/scripts/kconfig/tests/warn_num_bounds/__init__.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+"""Test user values outside the numeric type bounds."""
+
+
+def test(conf):
+    in_keys = (
+        '-9223372036854775809\n'
+        '-1\n'
+        '9223372036854775808\n'
+        '1\n'
+        '0x10000000000000000\n'
+        '0x1\n'
+        '-9223372036854775808\n'
+        '9223372036854775807\n'
+        '0x0\n'
+        '0xffffffffffffffff\n'
+    )
+
+    assert conf.oldaskconfig(in_keys=in_keys) == 0
+    assert conf.stderr_matches('expected_frontend_stderr')
+    assert conf.config_matches('expected_frontend_config')
+
+    assert conf.olddefconfig('config') == 0
+    assert conf.stderr_matches('expected_config_stderr')
+    assert conf.config_matches('expected_config')
diff --git a/scripts/kconfig/tests/warn_num_bounds/config b/scripts/kconfig/tests/warn_num_bounds/config
new file mode 100644
index 000000000000..74bf263f99bf
--- /dev/null
+++ b/scripts/kconfig/tests/warn_num_bounds/config
@@ -0,0 +1,7 @@
+CONFIG_INT_TOO_LOW=-9223372036854775809
+CONFIG_INT_TOO_HIGH=9223372036854775808
+CONFIG_HEX_TOO_HIGH=0x10000000000000000
+CONFIG_INT_MIN=-9223372036854775808
+CONFIG_INT_MAX=9223372036854775807
+CONFIG_HEX_MIN=0x0
+CONFIG_HEX_MAX=0xffffffffffffffff
diff --git a/scripts/kconfig/tests/warn_num_bounds/expected_config b/scripts/kconfig/tests/warn_num_bounds/expected_config
new file mode 100644
index 000000000000..8b1aef612bc6
--- /dev/null
+++ b/scripts/kconfig/tests/warn_num_bounds/expected_config
@@ -0,0 +1,11 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Numeric bounds test
+#
+CONFIG_INT_TOO_LOW=-9223372036854775809
+CONFIG_INT_TOO_HIGH=9223372036854775808
+CONFIG_HEX_TOO_HIGH=0x10000000000000000
+CONFIG_INT_MIN=-9223372036854775808
+CONFIG_INT_MAX=9223372036854775807
+CONFIG_HEX_MIN=0x0
+CONFIG_HEX_MAX=0xffffffffffffffff
diff --git a/scripts/kconfig/tests/warn_num_bounds/expected_config_stderr b/scripts/kconfig/tests/warn_num_bounds/expected_config_stderr
new file mode 100644
index 000000000000..be2ed7fbf648
--- /dev/null
+++ b/scripts/kconfig/tests/warn_num_bounds/expected_config_stderr
@@ -0,0 +1,3 @@
+.config:1:warning: value '-9223372036854775809' for INT_TOO_LOW is outside the 64-bit signed integer bounds
+.config:2:warning: value '9223372036854775808' for INT_TOO_HIGH is outside the 64-bit signed integer bounds
+.config:3:warning: value '0x10000000000000000' for HEX_TOO_HIGH is outside the 64-bit unsigned integer bounds
diff --git a/scripts/kconfig/tests/warn_num_bounds/expected_frontend_config b/scripts/kconfig/tests/warn_num_bounds/expected_frontend_config
new file mode 100644
index 000000000000..a7e842517026
--- /dev/null
+++ b/scripts/kconfig/tests/warn_num_bounds/expected_frontend_config
@@ -0,0 +1,11 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Numeric bounds test
+#
+CONFIG_INT_TOO_LOW=-1
+CONFIG_INT_TOO_HIGH=1
+CONFIG_HEX_TOO_HIGH=0x1
+CONFIG_INT_MIN=-9223372036854775808
+CONFIG_INT_MAX=9223372036854775807
+CONFIG_HEX_MIN=0x0
+CONFIG_HEX_MAX=0xffffffffffffffff
diff --git a/scripts/kconfig/tests/warn_num_bounds/expected_frontend_stderr b/scripts/kconfig/tests/warn_num_bounds/expected_frontend_stderr
new file mode 100644
index 000000000000..e69de29bb2d1
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 4/4] kconfig: prevent out-of-bounds user input for numeric options
  2026-08-29 17:19 ` [PATCH 4/4] kconfig: prevent out-of-bounds user input for numeric options Julian Braha
@ 2026-09-04 23:25   ` Nathan Chancellor
  0 siblings, 0 replies; 6+ messages in thread
From: Nathan Chancellor @ 2026-09-04 23:25 UTC (permalink / raw)
  To: Julian Braha
  Cc: nathan, nsc, nico, rdunlap, grahamr, kees, pengpeng,
	vegard.nossum, linux-kernel, linux-kbuild

> diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
> index 4234a51d16fd..2227d89d6328 100644
> --- a/scripts/kconfig/confdata.c
> +++ b/scripts/kconfig/confdata.c
> @@ -354,6 +354,12 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
>  	case S_INT:
>  	case S_HEX:
>  		if (sym_string_valid(sym, p)) {
> +			if (def != S_DEF_AUTO &&
> +			    !sym_string_check_bounds(sym, p))
> +				/* hex uses 64-bit unsigned integer */
> +				conf_warning("value '%s' for %s is outside the 64-bit %s integer bounds",
> +					     p, sym->name,
> +					     sym->type == S_INT ? "signed" : "unsigned");
>  			sym->def[def].val = xstrdup(p);
>  			sym->flags |= def_flags;
>  		} else {
...
> diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
> index 2d8b0c65ce1e..6f99216ee76d 100644
> --- a/scripts/kconfig/menu.c
> +++ b/scripts/kconfig/menu.c
> @@ -4,7 +4,6 @@
>   */
>  
>  #include <ctype.h>
> -#include <errno.h>
>  #include <stdarg.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -255,17 +254,13 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2,
>  		return 1;
>  	}
>  
> -	errno = 0;
> -	if (sym->type == S_INT) {
> +	if (sym->type == S_INT)
>  		type_bounds = "64-bit signed integer";
> -		strtoll(sym2->name, NULL, 10);
> -	} else {
> +	else
>  		/* hex */
>  		type_bounds = "64-bit unsigned integer";
> -		strtoull(sym2->name, NULL, 16);
> -	}
>  
> -	if (errno == ERANGE) {
> +	if (!sym_string_check_bounds(sym, sym2->name)) {
>  		fprintf(stderr,
>  			"%s:%d: error: %s constant '%s' is outside the %s bounds\n",
>  			prop->filename, prop->lineno, sym_type_name(sym->type),

With this, you could inline the type bounds string like you did above:

diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 6f99216ee76d..f4b5b11991b4 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -238,8 +238,6 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
 static int menu_validate_number(struct symbol *sym, struct symbol *sym2,
 				const struct property *prop)
 {
-	const char *type_bounds;
-
 	if (sym->type != S_INT && sym->type != S_HEX)
 		return 0;
 
@@ -254,17 +252,11 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2,
 		return 1;
 	}
 
-	if (sym->type == S_INT)
-		type_bounds = "64-bit signed integer";
-	else
-		/* hex */
-		type_bounds = "64-bit unsigned integer";
-
 	if (!sym_string_check_bounds(sym, sym2->name)) {
 		fprintf(stderr,
-			"%s:%d: error: %s constant '%s' is outside the %s bounds\n",
+			"%s:%d: error: %s constant '%s' is outside the 64-bit %s integer bounds\n",
 			prop->filename, prop->lineno, sym_type_name(sym->type),
-			sym2->name, type_bounds);
+			sym2->name, sym->type == S_INT ? "signed" : "unsigned");
 
 		return 1;
 	}

> diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
> index 7e81b3676ee9..2d1c021fa395 100644
> --- a/scripts/kconfig/symbol.c
> +++ b/scripts/kconfig/symbol.c
> @@ -5,6 +5,7 @@
>  
>  #include <sys/types.h>
>  #include <ctype.h>
> +#include <errno.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <regex.h>
> @@ -711,6 +712,21 @@ bool sym_string_valid(struct symbol *sym, const char *str)
>  	}
>  }
>  
> +bool sym_string_check_bounds(struct symbol *sym, const char *str)
> +{
> +	errno = 0;
> +
> +	if (sym->type == S_INT)
> +		strtoll(str, NULL, 10);
> +	else if (sym->type == S_HEX)
> +		strtoull(str, NULL, 16);
> +	else
> +		/* string */
> +		return true;
> +
> +	return errno != ERANGE;
> +}
> +
>  bool sym_string_within_range(struct symbol *sym, const char *str)
>  {
>  	struct property *prop;
> @@ -722,6 +738,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
>  	case S_INT:
>  		if (!sym_string_valid(sym, str))
>  			return false;
> +		if (!sym_string_check_bounds(sym, str))
> +			return false;
>  		prop = sym_get_range_prop(sym);
>  		if (!prop)
>  			return true;
> @@ -731,6 +749,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
>  	case S_HEX:
>  		if (!sym_string_valid(sym, str))
>  			return false;
> +		if (!sym_string_check_bounds(sym, str))
> +			return false;
>  		prop = sym_get_range_prop(sym);
>  		if (!prop)
>  			return true;

Sashiko has a comment that seems to be relevant here unless I
misunderstand what it is complaining about:

https://sashiko.dev/#/patchset/64934

Otherwise, I like the direction here.

-- 
Cheers,
Nathan


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-04 23:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-29 17:18 [PATCH 0/4] kconfig: improve input validation for numeric options Julian Braha
2026-08-29 17:18 ` [PATCH 1/4] kconfig: promote invalid numeric reference from warning to error Julian Braha
2026-08-29 17:19 ` [PATCH 2/4] kconfig: check for out-of-bounds numeric constants Julian Braha
2026-08-29 17:19 ` [PATCH 3/4] kconfig: check for hex and int mismatches Julian Braha
2026-08-29 17:19 ` [PATCH 4/4] kconfig: prevent out-of-bounds user input for numeric options Julian Braha
2026-09-04 23:25   ` Nathan Chancellor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox