Skip to content

netfilter-match-modules: fix shell-dependent snippet corruption - #152

Closed
ispyisail wants to merge 1 commit into
masterfrom
fix/netfilter-module-printf-format-string
Closed

netfilter-match-modules: fix shell-dependent snippet corruption#152
ispyisail wants to merge 1 commit into
masterfrom
fix/netfilter-module-printf-format-string

Conversation

@ispyisail

Copy link
Copy Markdown
Owner

Fixes a build-from-source failure reported on the forum (asammar, "Compile
from Source Error", https://www.gargoyle-router.com/phpbb/viewtopic.php?t=18408):
compiling mediatek.filogic (and any other target) fails with errors like

src/statement.c:620:38: error: 's' undeclared (first use in this function)
620 | nft_print(octx, "%s"%s"", inv ? "!= " : "", stmt->weburl.match);

src/statement.c is not a real source file in this repo -- it's spliced
together at build time by integrate_netfilter_modules.sh from per-module
snippet files (e.g. netfilter-match-modules/nftables/weburl/nftables/src_statement.c.1).
Those snippets deliberately double up literal %% (so it survives as a
single % once inserted into format strings like nft_print(octx, "%%s\\"%%s\\"", ...)).
The insertion helper, insert_lines_at(), did that collapse by handing the
snippet text to printf as the format string (printf "$lines\n") and
relying on printf's own %% handling.

That also hands the unrelated \\" already in the snippet to printf's
escape processing, and shells disagree on what an unrecognized \\"
escape does: dash's printf (Debian/Ubuntu's default /bin/sh) leaves it
alone, bash's builtin printf (the default /bin/sh on Arch, and other
systems/containers) silently drops the backslash. build.sh invokes this
script as sh $netfilter_patch_script, so the outcome depends entirely on
what /bin/sh happens to be -- exactly reproduced locally: same snippet
content through dash's printf comes out as valid C, through bash's comes
out byte-for-byte matching the forum's reported error.

Fix: do the %% -> % collapse explicitly with sed, and pass the
snippet text to printf as data (printf '%s\n' "$lines") rather than as
a format string. Same fix applied to two more printf "$var" call sites
further down the same script (kernel Makefile var extraction) that had the
identical latent issue, even though their content is less likely to
contain %%/\\.

Verified by extracting the real snippet files for all four affected
modules (weburl, webmon, timerange, bandwidth) and running both the
original and fixed insert_lines_at() under both bash and dash: the
original reproduces the exact reported compile error under bash; the fix
produces identical, gcc -fsyntax-only-clean C under both shells.

…t string

insert_lines_at() ran the module .c/.y/.l snippets through printf "$lines"
to collapse the snippets' escaped %% back to a single %. Shells disagree on
how printf handles the unrelated \" also present in those snippets (bash's
builtin drops the backslash, dash's doesn't), corrupting emitted files like
src/statement.c into invalid C on any system where /bin/sh is bash. Do the
%%->% collapse explicitly with sed instead, which is shell-independent.
@ispyisail

Copy link
Copy Markdown
Owner Author

Closing in favour of #154, which supersedes this.

This change is correct for the \" corruption it targets, but incomplete in a way that makes things worse rather than better. Emitting the snippet literally also stops printf collapsing \\ to \, and three of the inline config_lines this script builds for libnftnl's src/Makefile.in were written as \\ precisely to rely on that collapse — they produce the trailing backslash that forms a Makefile line continuation.

With this merged as-is those come out as a literal \\, which automake reads as an escaped backslash rather than a continuation, and libnftnl fails to build with:

Makefile:141: *** recipe commences before first target

That would break the build for everyone, including the dash users who are unaffected today — confirmed live by the reporter in the forum thread (viewtopic.php?t=18408), who hit exactly that error after applying this.

#154 carries both halves and has been verified in dash and bash: all 101 spliced files render byte-identically to current dash output, the three Makefile.in continuations are preserved, and a sweep confirms no other backslash-bearing argument reaches insert_lines_at.

@ispyisail ispyisail closed this Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant