]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
kconfig: fix infinite loop in sym_calc_choice()
authorMasahiro Yamada <masahiroy@kernel.org>
Wed, 25 Sep 2024 11:25:31 +0000 (20:25 +0900)
committerMasahiro Yamada <masahiroy@kernel.org>
Mon, 30 Sep 2024 11:42:52 +0000 (20:42 +0900)
Since commit f79dc03fe68c ("kconfig: refactor choice value calculation"),
Kconfig for ARCH=powerpc may result in an infinite loop. This occurs
because there are two entries for POWERPC64_CPU in a choice block.

If the same symbol appears twice in a choice block, the ->choice_link
node is added twice to ->choice_members, resulting a corrupted linked
list.

A simple test case is:

    choice
            prompt "choice"

    config A
            bool "A"

    config B
            bool "B 1"

    config B
            bool "B 2"

    endchoice

Running 'make defconfig' results in an infinite loop.

One solution is to replace the current two entries:

    config POWERPC64_CPU
            bool "Generic (POWER5 and PowerPC 970 and above)"
            depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
            select PPC_64S_HASH_MMU

    config POWERPC64_CPU
            bool "Generic (POWER8 and above)"
            depends on PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
            select ARCH_HAS_FAST_MULTIPLIER
            select PPC_64S_HASH_MMU
            select PPC_HAS_LBARX_LHARX

with the following single entry:

    config POWERPC64_CPU
            bool "Generic 64 bit powerpc"
            depends on PPC_BOOK3S_64
            select ARCH_HAS_FAST_MULTIPLIER if CPU_LITTLE_ENDIAN
            select PPC_64S_HASH_MMU
            select PPC_HAS_LBARX_LHARX if CPU_LITTLE_ENDIAN

In my opinion, the latter looks cleaner, but PowerPC maintainers may
prefer to display different prompts depending on CPU_LITTLE_ENDIAN.

For now, this commit fixes the issue in Kconfig, restoring the original
behavior. I will reconsider whether such a use case is worth supporting.

Fixes: f79dc03fe68c ("kconfig: refactor choice value calculation")
Reported-by: Marco Bonelli <marco@mebeim.net>
Closes: https://lore.kernel.org/all/1763151587.3581913.1727224126288@privateemail.com/
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
scripts/kconfig/parser.y

index 1ad60f9e164e496c989f8d6ce6d37bc9b2ab62c9..bc43fb67c7c41e6db263a636ae165dbfa22e99d5 100644 (file)
@@ -159,8 +159,14 @@ config_stmt: config_entry_start config_option_list
                        yynerrs++;
                }
 
-               list_add_tail(&current_entry->sym->choice_link,
-                             &current_choice->choice_members);
+               /*
+                * If the same symbol appears twice in a choice block, the list
+                * node would be added twice, leading to a broken linked list.
+                * list_empty() ensures that this symbol has not yet added.
+                */
+               if (list_empty(&current_entry->sym->choice_link))
+                       list_add_tail(&current_entry->sym->choice_link,
+                                     &current_choice->choice_members);
        }
 
        printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);