From 9b8719973ee2c5ec23aab9b958e5c6fbdf352f90 Mon Sep 17 00:00:00 2001 From: Julian Braha Date: Tue, 15 Sep 2026 22:15:08 +0100 Subject: [PATCH] kconfig: use unsigned integers for hex range checks While 'hex' values should use the bounds of 64-bit unsigned integers, the range values are treated as signed (checks use strtoll). For example: config HEX_RANGE hex range 0 0xfffffffffffffffe default 0xffffffffffffffff the default value should adjust down to the upper bound of 0xfffffffffffffffe, but since the check incorrectly parses both as LLONG_MAX, the value stays at the out-of-range default of 0xffffffffffffffff. To fix this, let's use a union of signed and unsigned integers to represent both 'int' and 'hex' range values, then use both strtoll and strtoull where appropriate. Assisted-by: LLM Signed-off-by: Julian Braha Reviewed-by: Nicolas Schier Link: https://patch.msgid.link/20260915211508.291790-6-julianbraha@gmail.com Signed-off-by: Nathan Chancellor --- scripts/kconfig/symbol.c | 41 ++++++++++++++----- .../kconfig/tests/warn_changed_input/Kconfig | 5 +++ .../tests/warn_changed_input/expected_config | 1 + 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 8ccd9e7e2cf0..dcb4b45e674b 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -142,8 +142,15 @@ struct property *sym_get_range_prop(struct symbol *sym) return NULL; } -static long long sym_get_range_val(struct symbol *sym, int base) +union range_value { + long long s; + unsigned long long u; +}; + +static union range_value sym_get_range_val(struct symbol *sym, int base) { + union range_value val; + sym_calc_value(sym); switch (sym->type) { case S_INT: @@ -155,7 +162,12 @@ static long long sym_get_range_val(struct symbol *sym, int base) default: break; } - return strtoll(sym->curr.val, NULL, base); + if (base == 10) + val.s = strtoll(sym->curr.val, NULL, base); + else + /* HEX */ + val.u = strtoull(sym->curr.val, NULL, base); + return val; } /* @@ -168,7 +180,7 @@ static struct symbol *sym_get_near_range_bound(struct symbol *sym, struct property *prop; struct symbol *range_sym; int base; - long long val, val2; + union range_value val, val2; switch (sym->type) { case S_INT: @@ -183,13 +195,19 @@ static struct symbol *sym_get_near_range_bound(struct symbol *sym, prop = sym_get_range_prop(sym); if (!prop) return NULL; - val = strtoll(value, NULL, base); + val = sym_get_range_val(sym, base); range_sym = prop->expr->left.sym; val2 = sym_get_range_val(range_sym, base); - if (val >= val2) { + + if (base == 10 && val.s >= val2.s) { range_sym = prop->expr->right.sym; val2 = sym_get_range_val(range_sym, base); - if (val <= val2) + if (val.s <= val2.s) + return NULL; + } else if (base == 16 && val.u >= val2.u) { + range_sym = prop->expr->right.sym; + val2 = sym_get_range_val(range_sym, base); + if (val.u <= val2.u) return NULL; } @@ -746,6 +764,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str) { struct property *prop; long long val; + unsigned long long uval; switch (sym->type) { case S_STRING: @@ -759,8 +778,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str) if (!prop) return true; val = strtoll(str, NULL, 10); - return val >= sym_get_range_val(prop->expr->left.sym, 10) && - val <= sym_get_range_val(prop->expr->right.sym, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10).s && + val <= sym_get_range_val(prop->expr->right.sym, 10).s; case S_HEX: if (!sym_string_valid(sym, str)) return false; @@ -769,9 +788,9 @@ bool sym_string_within_range(struct symbol *sym, const char *str) prop = sym_get_range_prop(sym); if (!prop) return true; - val = strtoll(str, NULL, 16); - return val >= sym_get_range_val(prop->expr->left.sym, 16) && - val <= sym_get_range_val(prop->expr->right.sym, 16); + uval = strtoull(str, NULL, 16); + return uval >= sym_get_range_val(prop->expr->left.sym, 16).u && + uval <= sym_get_range_val(prop->expr->right.sym, 16).u; case S_BOOLEAN: case S_TRISTATE: switch (str[0]) { diff --git a/scripts/kconfig/tests/warn_changed_input/Kconfig b/scripts/kconfig/tests/warn_changed_input/Kconfig index 69845e2f3fb3..df4183a08420 100644 --- a/scripts/kconfig/tests/warn_changed_input/Kconfig +++ b/scripts/kconfig/tests/warn_changed_input/Kconfig @@ -26,6 +26,11 @@ config NUM Kconfig resolves it to the constrained in-range value. The warning should report that adjustment. +config HEX_RANGE + hex + range 0 0xfffffffffffffffe + default 0xffffffffffffffff + config DUP bool "DUP" depends on DEP diff --git a/scripts/kconfig/tests/warn_changed_input/expected_config b/scripts/kconfig/tests/warn_changed_input/expected_config index fe8bbec66c53..6a8d98a69b7e 100644 --- a/scripts/kconfig/tests/warn_changed_input/expected_config +++ b/scripts/kconfig/tests/warn_changed_input/expected_config @@ -4,3 +4,4 @@ # # CONFIG_DEP is not set CONFIG_NUM=20 +CONFIG_HEX_RANGE=0xfffffffffffffffe