diff options
| author | Nicolas Schier <nsc@kernel.org> | 2026-02-20 19:55:19 +0100 |
|---|---|---|
| committer | Nicolas Schier <nsc@kernel.org> | 2026-02-27 09:26:58 +0100 |
| commit | 102d712ded3ef2ee5b38ee6afa686aff63afd444 (patch) | |
| tree | 016c78a6ab4eca91ada9f5666a9a08940c147314 | |
| parent | 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f (diff) | |
kconfig: Error out on duplicated kconfig inclusion
Let kconfig exit with error on duplicated Kconfig file inclusion.
Repeated inclusion of Kbuild files are considered bad-practise with
regard to maintenance; and Kconfig language is rich enough that there
should be no need for that.
If repeated inclusion of Kconfig files is detected, error out with
messages like:
Kconfig.inc1:4: error: repeated inclusion of Kconfig.inc3
Kconfig.inc2:3: note: location of first inclusion of Kconfig.inc3
While commit f094f8a1b273 ("kconfig: allow multiple inclusion of the
same file") introduced detection of recursive inclusions of Kconfig
files, it explicitly allowed repeated inclusions, unfortunately w/o
reasoning.
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Closes: https://lore.kernel.org/all/CAHk-=wj03hLzK2D=+OYmjgcmGM+XYymp8GyaEs=C0=rXG2nb7w@mail.gmail.com/
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Link: https://patch.msgid.link/20260220-kconfig-error-out-on-duplicated-inclusion-v1-1-be78aa241a53@kernel.org
Signed-off-by: Nicolas Schier <nsc@kernel.org>
| -rw-r--r-- | scripts/kconfig/lexer.l | 4 | ||||
| -rw-r--r-- | scripts/kconfig/lkc.h | 3 | ||||
| -rw-r--r-- | scripts/kconfig/tests/err_repeated_inc/Kconfig | 3 | ||||
| -rw-r--r-- | scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 | 4 | ||||
| -rw-r--r-- | scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 | 3 | ||||
| -rw-r--r-- | scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 | 1 | ||||
| -rw-r--r-- | scripts/kconfig/tests/err_repeated_inc/__init__.py | 10 | ||||
| -rw-r--r-- | scripts/kconfig/tests/err_repeated_inc/expected_stderr | 2 | ||||
| -rw-r--r-- | scripts/kconfig/util.c | 31 |
9 files changed, 55 insertions, 6 deletions
diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l index 6d2c92c6095d..a6155422b4a6 100644 --- a/scripts/kconfig/lexer.l +++ b/scripts/kconfig/lexer.l @@ -402,7 +402,7 @@ void zconf_initscan(const char *name) exit(1); } - cur_filename = file_lookup(name); + cur_filename = file_lookup(name, NULL, 0); yylineno = 1; } @@ -443,7 +443,7 @@ void zconf_nextfile(const char *name) } yylineno = 1; - cur_filename = file_lookup(name); + cur_filename = file_lookup(name, cur_filename, cur_lineno); } static void zconf_endfile(void) diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 798985961215..7e6f6ca299cf 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -51,7 +51,8 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) } /* util.c */ -const char *file_lookup(const char *name); +const char *file_lookup(const char *name, + const char *parent_name, int parent_lineno); /* lexer.l */ int yylex(void); diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig b/scripts/kconfig/tests/err_repeated_inc/Kconfig new file mode 100644 index 000000000000..09a88fd29cb5 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +source "Kconfig.inc1" diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 new file mode 100644 index 000000000000..495dc38314a1 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +source "Kconfig.inc2" +source "Kconfig.inc3" diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 new file mode 100644 index 000000000000..2b630eec2e99 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +source "Kconfig.inc3" diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 new file mode 100644 index 000000000000..a4e40e534e6a --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 @@ -0,0 +1 @@ +# SPDX-License-Identifier: GPL-2.0-only diff --git a/scripts/kconfig/tests/err_repeated_inc/__init__.py b/scripts/kconfig/tests/err_repeated_inc/__init__.py new file mode 100644 index 000000000000..129d740a874b --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/__init__.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Detect repeated inclusion error. + +If repeated inclusion is detected, it should fail with error message. +""" + +def test(conf): + assert conf.oldaskconfig() != 0 + assert conf.stderr_contains('expected_stderr') diff --git a/scripts/kconfig/tests/err_repeated_inc/expected_stderr b/scripts/kconfig/tests/err_repeated_inc/expected_stderr new file mode 100644 index 000000000000..95d90d6a93c5 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/expected_stderr @@ -0,0 +1,2 @@ +Kconfig.inc1:4: error: Repeated inclusion of Kconfig.inc3 +Kconfig.inc2:3: note: Location of first inclusion of Kconfig.inc3 diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index 5cdcee144b58..0809aa061b6a 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c @@ -18,25 +18,50 @@ static HASHTABLE_DEFINE(file_hashtable, 1U << 11); struct file { struct hlist_node node; + struct { + const char *name; + int lineno; + } parent; char name[]; }; +static void die_duplicated_include(struct file *file, + const char *parent, int lineno) +{ + fprintf(stderr, + "%s:%d: error: repeated inclusion of %s\n" + "%s:%d: note: location of first inclusion of %s\n", + parent, lineno, file->name, + file->parent.name, file->parent.lineno, file->name); + exit(1); +} + /* file already present in list? If not add it */ -const char *file_lookup(const char *name) +const char *file_lookup(const char *name, + const char *parent_name, int parent_lineno) { + const char *parent = NULL; struct file *file; size_t len; int hash = hash_str(name); + if (parent_name) + parent = file_lookup(parent_name, NULL, 0); + hash_for_each_possible(file_hashtable, file, node, hash) - if (!strcmp(name, file->name)) - return file->name; + if (!strcmp(name, file->name)) { + if (!parent_name) + return file->name; + die_duplicated_include(file, parent, parent_lineno); + } len = strlen(name); file = xmalloc(sizeof(*file) + len + 1); memset(file, 0, sizeof(*file)); memcpy(file->name, name, len); file->name[len] = '\0'; + file->parent.name = parent; + file->parent.lineno = parent_lineno; hash_add(file_hashtable, &file->node, hash); |
