summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorJulian Braha <julianbraha@gmail.com>2026-08-30 23:11:29 +0100
committerNathan Chancellor <nathan@kernel.org>2026-09-17 16:19:02 -0700
commitdbe1ae2304a3b02c3bf6ae82895ff232a29f3fee (patch)
treed55b306c8f610afc4f3bc9e1d78d377a0968c9db /scripts
parentff87968e4e564acb2fadce363b1b41e7fa3aad2f (diff)
downloadlinux-next-dbe1ae2304a3b02c3bf6ae82895ff232a29f3fee.tar.gz
linux-next-dbe1ae2304a3b02c3bf6ae82895ff232a29f3fee.zip
kconfig: fix extra output from savedefconfig on out-of-range defaults
The Kconfig interpreter currently allows defaults that are outside of the range bounds. In these cases, the 'sym_validate_range' function will adjust the default value to the nearest range bound. For example, see this example: config A int range 1 2 default 16 Here, since the default value of 16 is greater than the bounds, the effective default value gets adjusted down to the upper bound, 2. However, 'savedefconfig' writes non-default values, and without being aware of the automatic adjustment to the range bound, it would write: A=2 This limitation is also documented in a comment: "The following fails to handle the situation where a default value is further limited by the valid range." To resolve this, let's factor out the default-range adjustment logic from the existing 'sym_validate_range' function into its own 'sym_get_near_range_bound' function for 'savedefconfig' to use too, so that it compares against the effective value. Adds tests, accordingly. Fixes: 7cf3d73b4360 ("kconfig: add savedefconfig") Assisted-by: Codex:gpt-5.6-sol Reported-by: Geert Uytterhoeven <geert+renesas@glider.be> Closes: https://lore.kernel.org/lkml/CAMuHMdVyUAA3L4mUkSjmnuE3cvj-+N8z-Bhxsh1wa-FQWc=fjw@mail.gmail.com/ Signed-off-by: Julian Braha <julianbraha@gmail.com> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Nathan Chancellor <nathan@kernel.org> Link: https://patch.msgid.link/20260830221129.2668354-1-julianbraha@gmail.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/kconfig/symbol.c39
-rw-r--r--scripts/kconfig/tests/savedefconfig_range/Kconfig60
-rw-r--r--scripts/kconfig/tests/savedefconfig_range/__init__.py8
-rw-r--r--scripts/kconfig/tests/savedefconfig_range/config7
-rw-r--r--scripts/kconfig/tests/savedefconfig_range/expected_defconfig0
5 files changed, 102 insertions, 12 deletions
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index e82f330fb8ee..01aa58d92c3b 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -157,7 +157,12 @@ static long long sym_get_range_val(struct symbol *sym, int base)
return strtoll(sym->curr.val, NULL, base);
}
-static void sym_validate_range(struct symbol *sym)
+/*
+ * Return the nearest range bound for an out-of-range default value.
+ * Return NULL if the value is valid or the symbol has no active range.
+ */
+static struct symbol *sym_get_near_range_bound(struct symbol *sym,
+ const char *value)
{
struct property *prop;
struct symbol *range_sym;
@@ -172,21 +177,31 @@ static void sym_validate_range(struct symbol *sym)
base = 16;
break;
default:
- return;
+ return NULL;
}
prop = sym_get_range_prop(sym);
if (!prop)
- return;
- val = strtoll(sym->curr.val, NULL, base);
+ return NULL;
+ val = strtoll(value, NULL, base);
range_sym = prop->expr->left.sym;
val2 = sym_get_range_val(range_sym, base);
if (val >= val2) {
range_sym = prop->expr->right.sym;
val2 = sym_get_range_val(range_sym, base);
if (val <= val2)
- return;
+ return NULL;
}
- sym->curr.val = range_sym->curr.val;
+
+ return range_sym;
+}
+
+static void sym_validate_range(struct symbol *sym)
+{
+ struct symbol *range_sym;
+
+ range_sym = sym_get_near_range_bound(sym, sym->curr.val);
+ if (range_sym)
+ sym->curr.val = range_sym->curr.val;
}
static void sym_set_changed(struct symbol *sym)
@@ -812,7 +827,7 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
const char *sym_get_string_default(struct symbol *sym)
{
struct property *prop;
- struct symbol *ds;
+ struct symbol *ds, *range_sym;
const char *str = "";
tristate val;
@@ -830,11 +845,6 @@ const char *sym_get_string_default(struct symbol *sym)
val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
break;
default:
- /*
- * The following fails to handle the situation
- * where a default value is further limited by
- * the valid range.
- */
ds = prop_get_symbol(prop);
if (ds != NULL) {
sym_calc_value(ds);
@@ -878,6 +888,11 @@ const char *sym_get_string_default(struct symbol *sym)
default:
break;
}
+
+ range_sym = sym_get_near_range_bound(sym, str);
+ if (range_sym)
+ str = range_sym->curr.val;
+
return str;
}
diff --git a/scripts/kconfig/tests/savedefconfig_range/Kconfig b/scripts/kconfig/tests/savedefconfig_range/Kconfig
new file mode 100644
index 000000000000..fd59d9082ed5
--- /dev/null
+++ b/scripts/kconfig/tests/savedefconfig_range/Kconfig
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Static default and range values
+
+config INT_DEFAULT_ABOVE_RANGE
+ int
+ range 1 1
+ default 16
+
+config INT_DEFAULT_BELOW_RANGE
+ int
+ range 4 8
+ default 2
+
+# Default and range values determined by other options
+
+config RANGE_UPPER_BOUND
+ int
+ default 3
+
+config INT_DYNAMIC_RANGE
+ int
+ range 0 RANGE_UPPER_BOUND
+ default 4
+
+# Hex
+
+config HEX_DEFAULT_ABOVE_RANGE
+ hex
+ range 0x10 0x20
+ default 0x40
+
+# Implicit default value of 0
+
+config INT_IMPLICIT_DEFAULT_ZERO
+ int
+ range 1 4
+
+# Conditional range
+
+config USE_FIRST_RANGE
+ bool
+ default y
+
+config INT_CONDITIONAL_RANGE
+ int
+ range 1 2 if USE_FIRST_RANGE
+ range 3 4 if !USE_FIRST_RANGE
+ default 3
+
+# Conditional default
+
+config USE_DEFAULT
+ bool
+ default y
+
+config INT_CONDITIONAL_DEFAULT
+ int
+ range 1 2
+ default 3 if USE_DEFAULT
diff --git a/scripts/kconfig/tests/savedefconfig_range/__init__.py b/scripts/kconfig/tests/savedefconfig_range/__init__.py
new file mode 100644
index 000000000000..961454be732c
--- /dev/null
+++ b/scripts/kconfig/tests/savedefconfig_range/__init__.py
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+"""Test savedefconfig with numerical defaults outside of ranges."""
+
+
+def test(conf):
+ assert conf._run_conf('--savedefconfig=defconfig', dot_config='config',
+ out_file='defconfig') == 0
+ assert conf.config_matches('expected_defconfig')
diff --git a/scripts/kconfig/tests/savedefconfig_range/config b/scripts/kconfig/tests/savedefconfig_range/config
new file mode 100644
index 000000000000..d939cfe5fd34
--- /dev/null
+++ b/scripts/kconfig/tests/savedefconfig_range/config
@@ -0,0 +1,7 @@
+CONFIG_INT_DEFAULT_ABOVE_RANGE=1
+CONFIG_INT_DEFAULT_BELOW_RANGE=4
+CONFIG_INT_DYNAMIC_RANGE=3
+CONFIG_HEX_DEFAULT_ABOVE_RANGE=0x20
+CONFIG_INT_IMPLICIT_DEFAULT_ZERO=1
+CONFIG_INT_CONDITIONAL_RANGE=2
+CONFIG_INT_CONDITIONAL_DEFAULT=2
diff --git a/scripts/kconfig/tests/savedefconfig_range/expected_defconfig b/scripts/kconfig/tests/savedefconfig_range/expected_defconfig
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/scripts/kconfig/tests/savedefconfig_range/expected_defconfig