Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kconfig: fix comparison to constant symbols, 'm', 'n'

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>

+4 -2
+4 -2
scripts/kconfig/symbol.c
··· 14 14 15 15 struct symbol symbol_yes = { 16 16 .name = "y", 17 + .type = S_TRISTATE, 17 18 .curr = { "y", yes }, 18 19 .menus = LIST_HEAD_INIT(symbol_yes.menus), 19 20 .flags = SYMBOL_CONST|SYMBOL_VALID, ··· 22 21 23 22 struct symbol symbol_mod = { 24 23 .name = "m", 24 + .type = S_TRISTATE, 25 25 .curr = { "m", mod }, 26 26 .menus = LIST_HEAD_INIT(symbol_mod.menus), 27 27 .flags = SYMBOL_CONST|SYMBOL_VALID, ··· 30 28 31 29 struct symbol symbol_no = { 32 30 .name = "n", 31 + .type = S_TRISTATE, 33 32 .curr = { "n", no }, 34 33 .menus = LIST_HEAD_INIT(symbol_no.menus), 35 34 .flags = SYMBOL_CONST|SYMBOL_VALID, ··· 823 820 case no: 824 821 return "n"; 825 822 case mod: 826 - sym_calc_value(modules_sym); 827 - return (modules_sym->curr.tri == no) ? "n" : "m"; 823 + return "m"; 828 824 case yes: 829 825 return "y"; 830 826 }