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

kconfig: recursive checks drop file/lineno

This prevents segfault when getting filename and lineno in recursive
checks.

If the following snippet is found in Kconfig:

[Test code 1]

config FOO
bool
depends on BAR
select BAR

... without BAR defined; then there is a segfault.

Kconfig:34:error: recursive dependency detected!
Kconfig:34: symbol FOO depends on BAR
make[4]: *** [scripts/kconfig/Makefile:85: allnoconfig] Segmentation fault

This is because of the following. BAR is a fake entry created by
sym_lookup() with prop being NULL. In the recursive check, there is a
NULL check for prop to fall back to stack->sym->prop if stack->prop is
NULL. However, in this case, stack->sym points to the fake BAR entry
created by sym_lookup(), so prop is still NULL. prop was then referenced
without additional NULL checks, causing segfault.

As the previous email thread suggests, the file and lineno for select is
also wrong:

[Test code 2]

config FOO
bool

config BAR
bool

config FOO
bool "FOO"
depends on BAR
select BAR

$ make defconfig
*** Default configuration is based on 'x86_64_defconfig'
Kconfig:1:error: recursive dependency detected!
Kconfig:1: symbol FOO depends on BAR
Kconfig:4: symbol BAR is selected by FOO
[...]

Kconfig:4 should be Kconfig:10.

This patch deletes the wrong and segfault-prone filename/lineno
inference completely. With this patch, Test code 1 yields:

error: recursive dependency detected!
symbol FOO depends on BAR
symbol BAR is selected by FOO

Signed-off-by: HONG Yifan <elsk@google.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>

authored by

HONG Yifan and committed by
Masahiro Yamada
9d0d2660 301c1090

+29 -47
+11 -29
scripts/kconfig/symbol.c
··· 1074 1074 { 1075 1075 struct dep_stack *stack; 1076 1076 struct symbol *sym, *next_sym; 1077 - struct menu *menu = NULL; 1078 1077 struct menu *choice; 1079 - struct property *prop; 1080 1078 struct dep_stack cv_stack; 1079 + enum prop_type type; 1081 1080 1082 1081 choice = sym_get_choice_menu(last_sym); 1083 1082 if (choice) { ··· 1095 1096 for (; stack; stack = stack->next) { 1096 1097 sym = stack->sym; 1097 1098 next_sym = stack->next ? stack->next->sym : last_sym; 1098 - prop = stack->prop; 1099 - if (prop == NULL) 1100 - prop = stack->sym->prop; 1099 + type = stack->prop ? stack->prop->type : P_UNKNOWN; 1101 1100 1102 - /* for choice values find the menu entry (used below) */ 1103 - if (sym_is_choice(sym) || sym_is_choice_value(sym)) { 1104 - for (prop = sym->prop; prop; prop = prop->next) { 1105 - menu = prop->menu; 1106 - if (prop->menu) 1107 - break; 1108 - } 1109 - } 1110 1101 if (stack->sym == last_sym) 1111 - fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", 1112 - prop->filename, prop->lineno); 1102 + fprintf(stderr, "error: recursive dependency detected!\n"); 1113 1103 1114 1104 if (sym_is_choice(next_sym)) { 1115 1105 choice = list_first_entry(&next_sym->menus, struct menu, link); 1116 1106 1117 - fprintf(stderr, "%s:%d:\tsymbol %s is part of choice block at %s:%d\n", 1118 - menu->filename, menu->lineno, 1107 + fprintf(stderr, "\tsymbol %s is part of choice block at %s:%d\n", 1119 1108 sym->name ? sym->name : "<choice>", 1120 1109 choice->filename, choice->lineno); 1121 1110 } else if (stack->expr == &sym->dir_dep.expr) { 1122 - fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", 1123 - prop->filename, prop->lineno, 1111 + fprintf(stderr, "\tsymbol %s depends on %s\n", 1124 1112 sym->name ? sym->name : "<choice>", 1125 1113 next_sym->name); 1126 1114 } else if (stack->expr == &sym->rev_dep.expr) { 1127 - fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", 1128 - prop->filename, prop->lineno, 1115 + fprintf(stderr, "\tsymbol %s is selected by %s\n", 1129 1116 sym->name, next_sym->name); 1130 1117 } else if (stack->expr == &sym->implied.expr) { 1131 - fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n", 1132 - prop->filename, prop->lineno, 1118 + fprintf(stderr, "\tsymbol %s is implied by %s\n", 1133 1119 sym->name, next_sym->name); 1134 1120 } else if (stack->expr) { 1135 - fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", 1136 - prop->filename, prop->lineno, 1121 + fprintf(stderr, "\tsymbol %s %s value contains %s\n", 1137 1122 sym->name ? sym->name : "<choice>", 1138 - prop_get_type_name(prop->type), 1123 + prop_get_type_name(type), 1139 1124 next_sym->name); 1140 1125 } else { 1141 - fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n", 1142 - prop->filename, prop->lineno, 1126 + fprintf(stderr, "\tsymbol %s %s is visible depending on %s\n", 1143 1127 sym->name ? sym->name : "<choice>", 1144 - prop_get_type_name(prop->type), 1128 + prop_get_type_name(type), 1145 1129 next_sym->name); 1146 1130 } 1147 1131 }
+18 -18
scripts/kconfig/tests/err_recursive_dep/expected_stderr
··· 1 - Kconfig:5:error: recursive dependency detected! 2 - Kconfig:5: symbol A depends on A 1 + error: recursive dependency detected! 2 + symbol A depends on A 3 3 For a resolution refer to Documentation/kbuild/kconfig-language.rst 4 4 subsection "Kconfig recursive dependency limitations" 5 5 6 - Kconfig:11:error: recursive dependency detected! 7 - Kconfig:11: symbol B is selected by B 6 + error: recursive dependency detected! 7 + symbol B is selected by B 8 8 For a resolution refer to Documentation/kbuild/kconfig-language.rst 9 9 subsection "Kconfig recursive dependency limitations" 10 10 11 - Kconfig:17:error: recursive dependency detected! 12 - Kconfig:17: symbol C1 depends on C2 13 - Kconfig:21: symbol C2 depends on C1 11 + error: recursive dependency detected! 12 + symbol C1 depends on C2 13 + symbol C2 depends on C1 14 14 For a resolution refer to Documentation/kbuild/kconfig-language.rst 15 15 subsection "Kconfig recursive dependency limitations" 16 16 17 - Kconfig:27:error: recursive dependency detected! 18 - Kconfig:27: symbol D1 depends on D2 19 - Kconfig:32: symbol D2 is selected by D1 17 + error: recursive dependency detected! 18 + symbol D1 depends on D2 19 + symbol D2 is selected by D1 20 20 For a resolution refer to Documentation/kbuild/kconfig-language.rst 21 21 subsection "Kconfig recursive dependency limitations" 22 22 23 - Kconfig:37:error: recursive dependency detected! 24 - Kconfig:37: symbol E1 depends on E2 25 - Kconfig:42: symbol E2 is implied by E1 23 + error: recursive dependency detected! 24 + symbol E1 depends on E2 25 + symbol E2 is implied by E1 26 26 For a resolution refer to Documentation/kbuild/kconfig-language.rst 27 27 subsection "Kconfig recursive dependency limitations" 28 28 29 - Kconfig:49:error: recursive dependency detected! 30 - Kconfig:49: symbol F1 default value contains F2 31 - Kconfig:51: symbol F2 depends on F1 29 + error: recursive dependency detected! 30 + symbol F1 default value contains F2 31 + symbol F2 depends on F1 32 32 For a resolution refer to Documentation/kbuild/kconfig-language.rst 33 33 subsection "Kconfig recursive dependency limitations" 34 34 35 - Kconfig:60:error: recursive dependency detected! 36 - Kconfig:60: symbol G depends on G 35 + error: recursive dependency detected! 36 + symbol G depends on G 37 37 For a resolution refer to Documentation/kbuild/kconfig-language.rst 38 38 subsection "Kconfig recursive dependency limitations"