diff options
author | Masahiro Yamada <masahiroy@kernel.org> | 2024-05-19 18:22:27 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-06-12 11:12:58 +0200 |
commit | 2b6e818fc609b50902b60caf8ab315c64523ceef (patch) | |
tree | bcfbee53019c965e2ba05137f9c4bc1b98ce3a54 /scripts | |
parent | b939d1e04a90248b4cdf417b0969c270ceb992b2 (diff) | |
download | linux-2b6e818fc609b50902b60caf8ab315c64523ceef.tar.gz linux-2b6e818fc609b50902b60caf8ab315c64523ceef.tar.bz2 linux-2b6e818fc609b50902b60caf8ab315c64523ceef.zip |
kconfig: fix comparison to constant symbols, 'm', 'n'
[ Upstream commit aabdc960a283ba78086b0bf66ee74326f49e218e ]
Currently, comparisons to 'm' or 'n' result in incorrect output.
[Test Code]
config MODULES
def_bool y
modules
config A
def_tristate m
config B
def_bool A > n
CONFIG_B is unset, while CONFIG_B=y is expected.
The reason for the issue is because Kconfig compares the tristate values
as strings.
Currently, the .type fields in the constant symbol definitions,
symbol_{yes,mod,no} are unspecified, i.e., S_UNKNOWN.
When expr_calc_value() evaluates 'A > n', it checks the types of 'A' and
'n' to determine how to compare them.
The left-hand side, 'A', is a tristate symbol with a value of 'm', which
corresponds to a numeric value of 1. (Internally, 'y', 'm', and 'n' are
represented as 2, 1, and 0, respectively.)
The right-hand side, 'n', has an unknown type, so it is treated as the
string "n" during the comparison.
expr_calc_value() compares two values numerically only when both can
have numeric values. Otherwise, they are compared as strings.
symbol numeric value ASCII code
-------------------------------------
y 2 0x79
m 1 0x6d
n 0 0x6e
'm' is greater than 'n' if compared numerically (since 1 is greater
than 0), but smaller than 'n' if compared as strings (since the ASCII
code 0x6d is smaller than 0x6e).
Specifying .type=S_TRISTATE for symbol_{yes,mod,no} fixes the above
test code.
Doing so, however, would cause a regression to the following test code.
[Test Code 2]
config MODULES
def_bool n
modules
config A
def_tristate n
config B
def_bool A = m
You would get CONFIG_B=y, while CONFIG_B should not be set.
The reason is because sym_get_string_value() turns 'm' into 'n' when the
module feature is disabled. Consequently, expr_calc_value() evaluates
'A = n' instead of 'A = m'. This oddity has been hidden because the type
of 'm' was previously S_UNKNOWN instead of S_TRISTATE.
sym_get_string_value() should not tweak the string because the tristate
value has already been correctly calculated. There is no reason to
return the string "n" where its tristate value is mod.
Fixes: 31847b67bec0 ("kconfig: allow use of relations other than (in)equality")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/kconfig/symbol.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index a76925b46ce6..7b1df55b0176 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -13,18 +13,21 @@ struct symbol symbol_yes = { .name = "y", + .type = S_TRISTATE, .curr = { "y", yes }, .flags = SYMBOL_CONST|SYMBOL_VALID, }; struct symbol symbol_mod = { .name = "m", + .type = S_TRISTATE, .curr = { "m", mod }, .flags = SYMBOL_CONST|SYMBOL_VALID, }; struct symbol symbol_no = { .name = "n", + .type = S_TRISTATE, .curr = { "n", no }, .flags = SYMBOL_CONST|SYMBOL_VALID, }; @@ -775,8 +778,7 @@ const char *sym_get_string_value(struct symbol *sym) case no: return "n"; case mod: - sym_calc_value(modules_sym); - return (modules_sym->curr.tri == no) ? "n" : "m"; + return "m"; case yes: return "y"; } |