mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] kconfig: preserve the final answer when input has no newline
@ 2026-09-07 10:37 Erkan Erdem
  2026-09-09 22:43 ` Julian Braha
  0 siblings, 1 reply; 2+ messages in thread
From: Erkan Erdem @ 2026-09-07 10:37 UTC (permalink / raw)
  To: Nathan Chancellor, Nicolas Schier
  Cc: Erkan Erdem, Julian Braha, linux-kbuild, linux-kernel,
	Nick Desaulniers, Bill Wendling, Justin Stitt, llvm

conf_string() unconditionally removes the last character returned by
fgets(), assuming that it is a newline. When redirected input ends
without a newline, the last character is part of the answer instead.
For example, feeding 42 to an integer prompt stores 4, and feeding
0xff to a hexadecimal prompt stores 0xf. Both commands succeed despite
silently changing the supplied value.

Strip the newline with strcspn() so that a complete answer at EOF is
preserved. Keep the existing handling of newline-terminated and empty
answers unchanged.

Add regression tests for string, int and hex answers, with and without
a final newline, in oldaskconfig and oldconfig.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: LLM
Signed-off-by: Erkan Erdem <hexvalid@gmail.com>
---

Changes in v2, addressing Julian Braha's review:
- Add an in-tree regression test under scripts/kconfig/tests for string,
  int and hex answers, with and without a final newline, in oldconfig
  and oldaskconfig. The shared test harness is unchanged.
- Submit this fix independently of the checkkconfigsymbols.py change.
- Refresh Cc from scripts/get_maintainer.pl, including the LLVM contacts.

v1: https://lore.kernel.org/all/20260905123237.40670-1-hexvalid@gmail.com/

An AI coding assistant found the issue, prepared the fix and changelog,
and ran the original verification. The assistant also prepared the new
regression test and this v2 revision.

Validation:
- Built original and fixed conf with Clang on macOS and GCC in an
  x86_64 Linux container, using -Wall -Wmissing-prototypes
  -Wstrict-prototypes -Werror.
- On both platforms, the original conf fails all six unterminated-input
  cases and passes all six newline-terminated controls.
- The fixed conf passes the complete 33-test Kconfig suite on both
  platforms, including all 12 new cases.
- This tests the host configuration tool; a complete kernel was not built.

 scripts/kconfig/conf.c                        |  2 +-
 .../kconfig/tests/conf_no_newline/__init__.py | 32 +++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 scripts/kconfig/tests/conf_no_newline/__init__.py

diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index fe8ba09b0..46c9ca646 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -343,7 +343,7 @@ static int conf_string(struct menu *menu)
 			}
 			/* fall through */
 		default:
-			line[strlen(line)-1] = 0;
+			line[strcspn(line, "\n")] = 0;
 			def = line;
 		}
 		if (def && sym_set_string_value(sym, def))
diff --git a/scripts/kconfig/tests/conf_no_newline/__init__.py b/scripts/kconfig/tests/conf_no_newline/__init__.py
new file mode 100644
index 000000000..0fca696d2
--- /dev/null
+++ b/scripts/kconfig/tests/conf_no_newline/__init__.py
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Preserve complete string, int and hex answers at end of input.
+"""
+
+import subprocess
+
+import pytest
+
+from conftest import CONF_PATH
+
+
+@pytest.mark.parametrize('mode', ['--oldaskconfig', '--oldconfig'])
+@pytest.mark.parametrize('newline', ['', '\n'], ids=['eof', 'newline'])
+@pytest.mark.parametrize('symbol_type, value, expected', [
+    ('string', 'abcdef', '"abcdef"'),
+    ('int', '42', '42'),
+    ('hex', '0xff', '0xff'),
+])
+def test(mode, newline, symbol_type, value, expected, tmp_path, monkeypatch):
+    (tmp_path / 'Kconfig').write_text(
+        'config TEST\n\t{} "Test value"\n'.format(symbol_type))
+    monkeypatch.setenv('srctree', str(tmp_path))
+    monkeypatch.setenv('KCONFIG_DEFCONFIG_LIST', '')
+
+    result = subprocess.run([CONF_PATH, mode, 'Kconfig'],
+                            input=value + newline, text=True,
+                            stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                            cwd=tmp_path, timeout=10)
+
+    assert result.returncode == 0, result.stderr
+    assert 'CONFIG_TEST={}\n'.format(expected) in (tmp_path / '.config').read_text()

base-commit: 4d7d9486c04d917265f64c55bd23b2cc4fe7749c
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] kconfig: preserve the final answer when input has no newline
  2026-09-07 10:37 [PATCH v2] kconfig: preserve the final answer when input has no newline Erkan Erdem
@ 2026-09-09 22:43 ` Julian Braha
  0 siblings, 0 replies; 2+ messages in thread
From: Julian Braha @ 2026-09-09 22:43 UTC (permalink / raw)
  To: Erkan Erdem, Nathan Chancellor, Nicolas Schier
  Cc: linux-kbuild, linux-kernel, Nick Desaulniers, Bill Wendling,
	Justin Stitt, llvm

Hi Erkan,

On 9/7/26 11:37, Erkan Erdem wrote:
> conf_string() unconditionally removes the last character returned by
> fgets(), assuming that it is a newline. When redirected input ends
> without a newline, the last character is part of the answer instead.
> For example, feeding 42 to an integer prompt stores 4, and feeding
> 0xff to a hexadecimal prompt stores 0xf. Both commands succeed despite
> silently changing the supplied value.
> 
> Strip the newline with strcspn() so that a complete answer at EOF is
> preserved. Keep the existing handling of newline-terminated and empty
> answers unchanged.
> 
> Add regression tests for string, int and hex answers, with and without
> a final newline, in oldaskconfig and oldconfig.
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Assisted-by: LLM
> Signed-off-by: Erkan Erdem <hexvalid@gmail.com>
> ---
> 
> Changes in v2, addressing Julian Braha's review:
> - Add an in-tree regression test under scripts/kconfig/tests for string,
>   int and hex answers, with and without a final newline, in oldconfig
>   and oldaskconfig. The shared test harness is unchanged.
> - Submit this fix independently of the checkkconfigsymbols.py change.
> - Refresh Cc from scripts/get_maintainer.pl, including the LLVM contacts.
> 
> v1: https://lore.kernel.org/all/20260905123237.40670-1-hexvalid@gmail.com/
> 
> An AI coding assistant found the issue, prepared the fix and changelog,
> and ran the original verification. The assistant also prepared the new
> regression test and this v2 revision.
> 
> Validation:
> - Built original and fixed conf with Clang on macOS and GCC in an
>   x86_64 Linux container, using -Wall -Wmissing-prototypes
>   -Wstrict-prototypes -Werror.
> - On both platforms, the original conf fails all six unterminated-input
>   cases and passes all six newline-terminated controls.
> - The fixed conf passes the complete 33-test Kconfig suite on both
>   platforms, including all 12 new cases.
> - This tests the host configuration tool; a complete kernel was not built.
> 
>  scripts/kconfig/conf.c                        |  2 +-
>  .../kconfig/tests/conf_no_newline/__init__.py | 32 +++++++++++++++++++
>  2 files changed, 33 insertions(+), 1 deletion(-)
>  create mode 100644 scripts/kconfig/tests/conf_no_newline/__init__.py
> 
> diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
> index fe8ba09b0..46c9ca646 100644
> --- a/scripts/kconfig/conf.c
> +++ b/scripts/kconfig/conf.c
> @@ -343,7 +343,7 @@ static int conf_string(struct menu *menu)
>  			}
>  			/* fall through */
>  		default:
> -			line[strlen(line)-1] = 0;
> +			line[strcspn(line, "\n")] = 0;
>  			def = line;
>  		}
>  		if (def && sym_set_string_value(sym, def))
> diff --git a/scripts/kconfig/tests/conf_no_newline/__init__.py b/scripts/kconfig/tests/conf_no_newline/__init__.py
> new file mode 100644
> index 000000000..0fca696d2
> --- /dev/null
> +++ b/scripts/kconfig/tests/conf_no_newline/__init__.py
> @@ -0,0 +1,32 @@
> +# SPDX-License-Identifier: GPL-2.0
> +"""
> +Preserve complete string, int and hex answers at end of input.
> +"""
> +
> +import subprocess
> +
> +import pytest
> +
> +from conftest import CONF_PATH
> +
> +
> +@pytest.mark.parametrize('mode', ['--oldaskconfig', '--oldconfig'])
> +@pytest.mark.parametrize('newline', ['', '\n'], ids=['eof', 'newline'])
> +@pytest.mark.parametrize('symbol_type, value, expected', [
> +    ('string', 'abcdef', '"abcdef"'),
> +    ('int', '42', '42'),
> +    ('hex', '0xff', '0xff'),
> +])
> +def test(mode, newline, symbol_type, value, expected, tmp_path, monkeypatch):

Please follow the style of the existing Kconfig tests.

For example, the function signature should look like 'def test(conf):'

> +    (tmp_path / 'Kconfig').write_text(
> +        'config TEST\n\t{} "Test value"\n'.format(symbol_type))

And you should keep a minimal Kconfig file in the directory, instead of
having the test create a temporary file each time it runs.

> +    monkeypatch.setenv('srctree', str(tmp_path))
> +    monkeypatch.setenv('KCONFIG_DEFCONFIG_LIST', '')
> +
> +    result = subprocess.run([CONF_PATH, mode, 'Kconfig'],
> +                            input=value + newline, text=True,
> +                            stdout=subprocess.PIPE, stderr=subprocess.PIPE,
> +                            cwd=tmp_path, timeout=10)
> +
> +    assert result.returncode == 0, result.stderr
> +    assert 'CONFIG_TEST={}\n'.format(expected) in (tmp_path / '.config').read_text()
> 
> base-commit: 4d7d9486c04d917265f64c55bd23b2cc4fe7749c

- Julian Braha

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-09 22:43 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-07 10:37 [PATCH v2] kconfig: preserve the final answer when input has no newline Erkan Erdem
2026-09-09 22:43 ` Julian Braha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®