From: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
To: bitbake-devel@lists.openembedded.org
Cc: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
Subject: [PATCH v2] parse: warn on trailing whitespace in parsed lines
Date: Thu, 6 Aug 2026 13:24:35 +0200 [thread overview]
Message-ID: <20260806112435.25128-1-jaipaul.cheernam@est.tech> (raw)
In-Reply-To: <20260804090834.99906-1-jaipaul.cheernam@est.tech>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 5487 bytes --]
rstrip() silently strips trailing whitespace before processing. This
hides invisible spaces or tabs that end up in patch context and cause
patches to fail to apply across branches.
Warn on any line with trailing whitespace so developers can fix it early.
Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
---
Changes since v1:
- Broadened from just backslash continuation to any trailing whitespace,
as suggested by Richard.
Real example from oe-core master (libssh2_1.11.1.bb, line 18):
file://CVE-2025-15661-3.patch \<TAB>
This caused CVE patches to fail to apply on wrynose where the trailing
tab was absent — invisible context mismatch.
Full parse (bitbake -p) across oe-core + meta-openembedded (2970 recipes):
- 228 unique trailing whitespace instances (verified, 0 false positives)
- 82 files affected (53 .bb, 19 .bbclass, 8 .inc, 2 .conf)
- 92 in oe-core, 136 in meta-openembedded
bbclass files like useradd.bbclass, sanity.bbclass, buildstats.bbclass
account for most of the warning noise since they are re-parsed for every
recipe that inherits them.
Tested with bitbake-selftest:
$ PYTHONPATH=lib python3 -m unittest lib.bb.tests.parse.ParseTest -v
3 new tests pass, no regressions.
A separate cleanup series will follow to fix the affected files.
lib/bb/parse/parse_py/BBHandler.py | 5 ++++-
lib/bb/parse/parse_py/ConfHandler.py | 10 ++++++++--
lib/bb/tests/parse.py | 28 ++++++++++++++++++++++++++++
3 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/lib/bb/parse/parse_py/BBHandler.py b/lib/bb/parse/parse_py/BBHandler.py
index 008fec230..3ac694e20 100644
--- a/lib/bb/parse/parse_py/BBHandler.py
+++ b/lib/bb/parse/parse_py/BBHandler.py
@@ -104,7 +104,10 @@ def get_statements(filename, absolute_filename, base_name):
lineno = lineno + 1
s = f.readline()
if not s: break
- s = s.rstrip()
+ raw = s.rstrip('\n').rstrip('\r')
+ s = raw.rstrip()
+ if s and raw != s:
+ bb.warn("Trailing whitespace in %s, line %s" % (filename, lineno))
feeder(lineno, s, filename, base_name, statements)
if __inpython__:
diff --git a/lib/bb/parse/parse_py/ConfHandler.py b/lib/bb/parse/parse_py/ConfHandler.py
index 9ddbae123..e4306d035 100644
--- a/lib/bb/parse/parse_py/ConfHandler.py
+++ b/lib/bb/parse/parse_py/ConfHandler.py
@@ -134,12 +134,18 @@ def handle(fn, data, include, baseconfig=False):
# skip empty lines
if not w:
continue
- s = s.rstrip()
+ raw = s.rstrip('\n').rstrip('\r')
+ s = raw.rstrip()
+ if s and raw != s:
+ bb.warn("Trailing whitespace in %s, line %s" % (fn, lineno))
while s[-1] == '\\':
line = f.readline()
origline += line
- s2 = line.rstrip()
+ raw2 = line.rstrip('\n').rstrip('\r')
+ s2 = raw2.rstrip()
lineno = lineno + 1
+ if s2 and raw2 != s2:
+ bb.warn("Trailing whitespace in %s, line %s" % (fn, lineno))
if (not s2 or s2 and s2[0] != "#") and s[0] == "#" :
bb.fatal("There is a confusing multiline, partially commented expression starting on line %s of file %s:\n%s\nPlease clarify whether this is all a comment or should be parsed." % (origlineno, fn, origline))
diff --git a/lib/bb/tests/parse.py b/lib/bb/tests/parse.py
index 6ac2137e0..5ccc6e93a 100644
--- a/lib/bb/tests/parse.py
+++ b/lib/bb/tests/parse.py
@@ -638,3 +638,31 @@ EXTRA_OECONF:append = " foobar"
output = run_bitbake(["bitbake", "-e", "recipe-file1"], builddir, extraenv).splitlines()
self.assertIn('BBCLASS_FILE="recipe-file.inc"', output)
self.assertIn(f'BBCLASS_RECIPE_FILE="recipe-file1.bb"', output)
+
+ trailing_whitespace_continuation = "A = \"1 \\\t \n2\"\n"
+
+ def test_parse_trailing_whitespace_continuation(self):
+ """Test that trailing whitespace after backslash continuation emits a warning"""
+ with self.parsehelper(self.trailing_whitespace_continuation) as f:
+ with self.assertLogs('BitBake', level='WARNING') as cm:
+ d = bb.parse.handle(f.name, self.d)['']
+ self.assertTrue(any("Trailing whitespace" in msg for msg in cm.output))
+ self.assertEqual(d.getVar("A"), "1 2")
+
+ trailing_whitespace_after_value = 'A = "1" \n'
+
+ def test_parse_trailing_whitespace_after_value(self):
+ """Test that trailing whitespace after a normal value emits a warning"""
+ with self.parsehelper(self.trailing_whitespace_after_value) as f:
+ with self.assertLogs('BitBake', level='WARNING') as cm:
+ d = bb.parse.handle(f.name, self.d)['']
+ self.assertTrue(any("Trailing whitespace" in msg for msg in cm.output))
+ self.assertEqual(d.getVar("A"), "1")
+
+ clean_continuation = "A = \"1 \\\n2\"\n"
+
+ def test_parse_clean_continuation_no_warning(self):
+ """Test that clean backslash continuation does not warn"""
+ with self.parsehelper(self.clean_continuation) as f:
+ d = bb.parse.handle(f.name, self.d)['']
+ self.assertEqual(d.getVar("A"), "1 2")
next prev parent reply other threads:[~2026-08-06 11:24 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 9:08 [PATCH] parse: warn on trailing whitespace after line continuation backslash Jaipaul Cheernam
2026-08-04 10:27 ` [bitbake-devel] " Richard Purdie
2026-08-04 10:37 ` Jaipaul Cheernam
2026-08-04 11:37 ` Richard Purdie
2026-08-04 12:15 ` Jaipaul Cheernam
2026-08-06 10:44 ` [PATCH v2] parse: warn on trailing whitespace in parsed lines Jaipaul Cheernam
2026-08-06 11:24 ` Jaipaul Cheernam [this message]
2026-08-13 15:07 ` [bitbake-devel] " Mathieu Dubois-Briand
2026-08-13 16:54 ` Jaipaul Cheernam
2026-08-20 10:31 ` Jaipaul Cheernam
2026-08-23 8:14 ` [bitbake-devel] " Mathieu Dubois-Briand
2026-08-25 16:13 ` Jaipaul Cheernam
2026-08-26 14:34 ` Richard Purdie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260806112435.25128-1-jaipaul.cheernam@est.tech \
--to=jaipaul.cheernam@est.tech \
--cc=bitbake-devel@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.