Skip to content

netfilter-match-modules: don't use inserted code as a printf format - #154

Open
ispyisail wants to merge 2 commits into
masterfrom
fix/netfilter-integrate-printf-format
Open

netfilter-match-modules: don't use inserted code as a printf format#154
ispyisail wants to merge 2 commits into
masterfrom
fix/netfilter-integrate-printf-format

Conversation

@ispyisail

Copy link
Copy Markdown
Owner

Fixes the "compile from source" failure reported on the forum (t=18408), where make mediatek.filogic dies with:

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

Root cause

insert_lines_at() in integrate_netfilter_modules.sh spliced snippet files into the real nftables sources with:

printf "$lines\n" >>.tmp.tmp

That passes the snippet as printf's format string, so the generated C depends on the shell's printf implementation. Two things get processed:

  • %%% — which is why the snippets were written with %%s to produce %s.
  • \"undefined in POSIX printf format processing, so implementations differ. dash and busybox ash preserve the backslash; bash and coreutils printf drop it.

So "%%s\"%%s\"" becomes "%s\"%s\"" (valid) under dash, but "%s"%s"" (broken) under bash — a string "%s", a bare %s token, then "". Hence 's' undeclared.

This is why it reproduces for some people and not others: it depends entirely on what /bin/sh is. Debian/Ubuntu point it at dash, so it builds; on a distro where /bin/sh is bash it fails. Nothing is wrong with the reporter's setup.

The blast radius matches the reported errors exactly — the only 4 spliced files containing \" are weburl (1 line), webmon (1), timerange (3), bandwidth (1), which is precisely the set of failing functions in the log, including timerange's three separate error lines.

The fix

  • insert_lines_at() now uses printf '%s\n' "$lines", emitting the snippet literally instead of interpreting it.
  • The snippets consequently drop the %% escaping they only carried to survive the old behaviour, so they now contain plain, valid C. \" stays as-is — it was always correct C, it was just being mangled in transit.

Only files spliced via action=insert were touched. Files handled by action=copy are unchanged, since a %% there is a genuine C printf escape.

Verification

Every one of the 101 spliced files was rendered through the old pipeline on a working (dash) system and through the new pipeline under both dash and bash, and compared:

files checked: 101 (each under dash AND bash)
RESULT: byte-identical to current dash output, in BOTH shells

So the generated sources are unchanged for everyone whose build works today, and now identical — rather than broken — for everyone whose /bin/sh is bash. The escape survey behind that claim: across all spliced files the only backslash sequence in use is \" (12 occurrences) and there are no lone %, so %% and \" were the complete set of printf-format dependencies.

ispyisail added 2 commits August 1, 2026 15:06
insert_lines_at() passed snippet contents as printf's format string, so
the generated C depended on the shell's printf. Where \" is undefined
(bash, coreutils printf) the backslash is dropped and "%s\"%s\""
becomes "%s"%s"", failing to compile. Emit the text literally and
drop the %%-escaping the snippets carried for the old behaviour.
The three libnftnl src/Makefile.in inserts wrote '\\' because the old
printf-as-format collapsed it to a single backslash. With the text now
emitted literally they must carry the single backslash they want, or the
generated Makefile gets an escaped backslash instead of a line
continuation and automake fails with 'recipe commences before first
target'.
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