mirror of
https://github.com/torvalds/linux.git
synced 2026-10-23 15:32:04 +02:00
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: 7cf3d73b43 ("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>
This commit is contained in:
parent
ff87968e4e
commit
dbe1ae2304
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
60
scripts/kconfig/tests/savedefconfig_range/Kconfig
Normal file
60
scripts/kconfig/tests/savedefconfig_range/Kconfig
Normal file
|
|
@ -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
|
||||
8
scripts/kconfig/tests/savedefconfig_range/__init__.py
Normal file
8
scripts/kconfig/tests/savedefconfig_range/__init__.py
Normal file
|
|
@ -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')
|
||||
7
scripts/kconfig/tests/savedefconfig_range/config
Normal file
7
scripts/kconfig/tests/savedefconfig_range/config
Normal file
|
|
@ -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
|
||||
Loading…
Reference in New Issue
Block a user