diff mbox series

kconfig: Prevent segfault when getting filename

Message ID 20240618185609.4096399-1-elsk@google.com (mailing list archive)
State New
Headers show
Series kconfig: Prevent segfault when getting filename | expand

Commit Message

HONG Yifan June 18, 2024, 6:56 p.m. UTC
... 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.

Signed-off-by: Yifan Hong <elsk@google.com>
---
 scripts/kconfig/symbol.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

Comments

Masahiro Yamada June 19, 2024, 1:36 a.m. UTC | #1
On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@google.com> 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@google.com>
> ---
>  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
HONG Yifan June 20, 2024, 7:46 p.m. UTC | #2
On Tue, Jun 18, 2024 at 6:37 PM Masahiro Yamada <masahiroy@kernel.org> wrote:
>
> On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@google.com> 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@google.com>
> > ---
> >  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@kernel.org> wrote:
>
> On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@google.com> 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@google.com>
> > ---
> >  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
diff mbox series

Patch

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>");