On Tue, Jun 18, 2024 at 6:37 PM Masahiro Yamada <masahiroy@xxxxxxxxxx> wrote: > > On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@xxxxxxxxxx> wrote: > > > > ... and lineno in recursive checks. > > > > If the following snippet is found in Kconfig: > > > > config FOO > > tristate > > depends on BAR > > select BAR > > help > > foo > > > > ... without BAR defined; then if one runs > > `make tinyconfig`, 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. > > > > Similarly, menu is also accessed without NULL > > checks. However, sym_lookup() creates entry > > that is not a choice, so technically it shouldn't > > fall into the state where menu is NULL for > > choices. But I mechnically apply the NULL check > > anyways for completeness. > > > > This mechnical patch avoids the segfault. The > > above snippet produces the following error with > > this patch: > > > > Kconfig:34:error: recursive dependency detected! > > Kconfig:34: symbol FOO depends on BAR > > ???:-1: symbol BAR is selected by FOO > > > > That being said, I am not sure if it is the right > > fix conceptually and in functionality. > > > > "???:-1: symbol BAR is selected by FOO" > > is weird, as there is no property > like "selected by". > > It should print the file and lineno of > "select BAR". > > > > > > The existing code is already wrong. > > In the past, I was thinking of fixing it to reference > the relevant menu entry. > > > Currently, it points to an unrelated location. > > > > [Test Code] > > > 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 > For a resolution refer to Documentation/kbuild/kconfig-language.rst > subsection "Kconfig recursive dependency limitations" > > > > > "Kconfig:1: symbol FOO depends on BAR" > points to the other unrelated definition > because "depends on BAR" appears the second > entry starting line 7. > > > > > So, I am not keen on applying another cheap fix > to already-wrong code. > > If you want to fix it now, please remove all > file/lineno logs from this function. Thanks for your reply, Masahiro! Do you mean to delete the file/lineno for "selected by" only, or for the whole sym_check_print_recursive function? It appears to me that some file/lineno information (Like `Kconfig:1: symbol FOO` above) is still useful. I agree that the `Kconfig:4` is wrong, though. I think a segfault indicates that the program is not robust against bad user input. In my opinion, it should fail gracefully with some information to tell the user. I wish I can fix this properly; but unfortunately I am not too familiar with this code. That was why I only provided a mechanical fix. I am happy to remove the file/lineno's; I just want to confirm which to remove. > > Then, somebody may rewrite the code some day. > > > > > > > > > > > > > > Signed-off-by: Yifan Hong <elsk@xxxxxxxxxx> > > --- > > scripts/kconfig/symbol.c | 29 +++++++++++++++++++++-------- > > 1 file changed, 21 insertions(+), 8 deletions(-) > > > > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c > > index 8df0a75f40b9..72ab4f274289 100644 > > --- a/scripts/kconfig/symbol.c > > +++ b/scripts/kconfig/symbol.c > > @@ -1045,6 +1045,8 @@ static void sym_check_print_recursive(struct symbol *last_sym) > > struct menu *menu = NULL; > > struct property *prop; > > struct dep_stack cv_stack; > > + const char *filename = NULL; > > + int lineno = 0; > > > > if (sym_is_choice_value(last_sym)) { > > dep_stack_insert(&cv_stack, last_sym); > > @@ -1060,6 +1062,10 @@ static void sym_check_print_recursive(struct symbol *last_sym) > > } > > > > for (; stack; stack = stack->next) { > > + filename = "???"; > > + lineno = 0; > > + menu = NULL; > > + > > sym = stack->sym; > > next_sym = stack->next ? stack->next->sym : last_sym; > > prop = stack->prop; > > @@ -1073,45 +1079,52 @@ static void sym_check_print_recursive(struct symbol *last_sym) > > if (prop->menu) > > break; > > } > > + if (menu) { > > + filename = menu->filename; > > + lineno = menu->lineno; > > + } > > + } else if (prop) { > > + filename = prop->filename; > > + lineno = prop->lineno; > > } > > if (stack->sym == last_sym) > > fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", > > - prop->filename, prop->lineno); > > + filename, lineno); > > > > if (sym_is_choice(sym)) { > > fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", > > - menu->filename, menu->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (sym_is_choice_value(sym)) { > > fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", > > - menu->filename, menu->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr == &sym->dir_dep.expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr == &sym->rev_dep.expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr == &sym->implied.expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > prop_get_type_name(prop->type), > > next_sym->name ? next_sym->name : "<choice>"); > > } else { > > fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > prop_get_type_name(prop->type), > > next_sym->name ? next_sym->name : "<choice>"); > > -- > > 2.45.2.627.g7a2c4fd464-goog > > > > > > > -- > Best Regards > Masahiro Yamada On Tue, Jun 18, 2024 at 6:37 PM Masahiro Yamada <masahiroy@xxxxxxxxxx> wrote: > > On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@xxxxxxxxxx> wrote: > > > > ... and lineno in recursive checks. > > > > If the following snippet is found in Kconfig: > > > > config FOO > > tristate > > depends on BAR > > select BAR > > help > > foo > > > > ... without BAR defined; then if one runs > > `make tinyconfig`, 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. > > > > Similarly, menu is also accessed without NULL > > checks. However, sym_lookup() creates entry > > that is not a choice, so technically it shouldn't > > fall into the state where menu is NULL for > > choices. But I mechnically apply the NULL check > > anyways for completeness. > > > > This mechnical patch avoids the segfault. The > > above snippet produces the following error with > > this patch: > > > > Kconfig:34:error: recursive dependency detected! > > Kconfig:34: symbol FOO depends on BAR > > ???:-1: symbol BAR is selected by FOO > > > > That being said, I am not sure if it is the right > > fix conceptually and in functionality. > > > > "???:-1: symbol BAR is selected by FOO" > > is weird, as there is no property > like "selected by". > > It should print the file and lineno of > "select BAR". > > > > > > The existing code is already wrong. > > In the past, I was thinking of fixing it to reference > the relevant menu entry. > > > Currently, it points to an unrelated location. > > > > [Test Code] > > > 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 > For a resolution refer to Documentation/kbuild/kconfig-language.rst > subsection "Kconfig recursive dependency limitations" > > > > > "Kconfig:1: symbol FOO depends on BAR" > points to the other unrelated definition > because "depends on BAR" appears the second > entry starting line 7. > > > > > So, I am not keen on applying another cheap fix > to already-wrong code. > > If you want to fix it now, please remove all > file/lineno logs from this function. > > Then, somebody may rewrite the code some day. > > > > > > > > > > > > > > Signed-off-by: Yifan Hong <elsk@xxxxxxxxxx> > > --- > > scripts/kconfig/symbol.c | 29 +++++++++++++++++++++-------- > > 1 file changed, 21 insertions(+), 8 deletions(-) > > > > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c > > index 8df0a75f40b9..72ab4f274289 100644 > > --- a/scripts/kconfig/symbol.c > > +++ b/scripts/kconfig/symbol.c > > @@ -1045,6 +1045,8 @@ static void sym_check_print_recursive(struct symbol *last_sym) > > struct menu *menu = NULL; > > struct property *prop; > > struct dep_stack cv_stack; > > + const char *filename = NULL; > > + int lineno = 0; > > > > if (sym_is_choice_value(last_sym)) { > > dep_stack_insert(&cv_stack, last_sym); > > @@ -1060,6 +1062,10 @@ static void sym_check_print_recursive(struct symbol *last_sym) > > } > > > > for (; stack; stack = stack->next) { > > + filename = "???"; > > + lineno = 0; > > + menu = NULL; > > + > > sym = stack->sym; > > next_sym = stack->next ? stack->next->sym : last_sym; > > prop = stack->prop; > > @@ -1073,45 +1079,52 @@ static void sym_check_print_recursive(struct symbol *last_sym) > > if (prop->menu) > > break; > > } > > + if (menu) { > > + filename = menu->filename; > > + lineno = menu->lineno; > > + } > > + } else if (prop) { > > + filename = prop->filename; > > + lineno = prop->lineno; > > } > > if (stack->sym == last_sym) > > fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", > > - prop->filename, prop->lineno); > > + filename, lineno); > > > > if (sym_is_choice(sym)) { > > fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", > > - menu->filename, menu->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (sym_is_choice_value(sym)) { > > fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", > > - menu->filename, menu->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr == &sym->dir_dep.expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr == &sym->rev_dep.expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr == &sym->implied.expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > next_sym->name ? next_sym->name : "<choice>"); > > } else if (stack->expr) { > > fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > prop_get_type_name(prop->type), > > next_sym->name ? next_sym->name : "<choice>"); > > } else { > > fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n", > > - prop->filename, prop->lineno, > > + filename, lineno, > > sym->name ? sym->name : "<choice>", > > prop_get_type_name(prop->type), > > next_sym->name ? next_sym->name : "<choice>"); > > -- > > 2.45.2.627.g7a2c4fd464-goog > > > > > > > -- > Best Regards > Masahiro Yamada