Skip to content

fix(utility): keep tail-merged C strings in Go and Rust mode - #402

Merged
danielplohmann merged 3 commits into
danielplohmann:masterfrom
r0ny123:fix/tail-merged-strings
Oct 15, 2026
Merged

danielplohmann merged 3 commits into
danielplohmann:masterfrom
r0ny123:fix/tail-merged-strings

Conversation

@r0ny123

@r0ny123 r0ny123 commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Follow-up to the two non-blocking notes on #382.

url= on mirai_x64. This was not the Go-mode minimum. The compiler stores "=" as the tail of "url=", and mov esi, 0x40d673 references it on its own, so the unpaired read stopped at that reference and gave "url". The cap is now skipped when the next target is the string's last character, nothing else points into the string, and the string starts a run (the byte before it can't end a printable string). A target that starts a UTF-16 string, as in rust_pe_gnu's \cmd.exe, still cuts.

Results against master, compared per string:

  • mirai_x64 with a planted pclntab header or /rustc/ path keeps url= and Cookie: (3 refs longer).
  • rust_pe_gnu, unplanted mirai_x64, and my go1.24.7 amd64/386 and Rust builds are unchanged.
  • Chains of suffixes ("\r\n\r\n", "\r\n", "\n") are still cut, because the middle one doesn't start a run, and packed Rust literals look the same there.

go1.24.7 not reproducible. Adds tests/go_hello_amd64_xored (1 MB). It is a go1.24.7 linux/amd64 hello program built with -trimpath -ldflags="-s -w -buildid=", and its source is in the test docstring. The fixture tests check that Go mode reads smdaGoMarker and hello there at their length, with at most one string over 200 chars. Before #382 the same binary gave 54 refs and neither literal.

ruff, ty, the full suite and the fixture gate pass on Python 3.11.

An unpaired reference stopped at the next referenced address, which cut
"url=" at the reference to its "=" suffix. Skip the cut when the target
is the string's last character, nothing else points into the string, and
the string starts a run. Adds a go1.24.7 linux/amd64 fixture so Go mode
runs on a real pclntab.
@danielplohmann danielplohmann added this to the v4.11.0 milestone Oct 15, 2026

@danielplohmann danielplohmann left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved on 1cec0bc.

Checked on Python 3.11.16: ruff check and format clean, full suite 2397 passed, 2 skipped. Reproduced the mirai_x64 figure with the /rustc/ marker planted in padding, compared per (ins_addr, data_addr): 16 strings shortened against unplanted on master, 13 on this branch. url= (twice) and Cookie: come back, and the \r\n chain and the packed abcdefgh... / HWCLVGAJ tables stay cut, as described.

Two non-blocking notes, both handled on our side in the 4.11.0 release PR, so nothing to push here:

  • The last check in _tail_merged cannot fail. target is end - 1 by the time it runs, so the first reference past it is always at or past end. An instrumented run over both string test files made 860 calls and never reached it. The "only other reference" property is already guaranteed by next_target being the first reference after offset. Fine to drop it whenever the file is touched next.
  • The changelog bullet does not name its tree (rule 4). The release PR adds 1cec0bc3ee5594037a5f52e1e0eaeb8262747418 and the 16 -> 13 figure, and updates #382's cost sentence to match.

@danielplohmann
danielplohmann merged commit 5129aa3 into danielplohmann:master Oct 15, 2026
24 checks passed
@r0ny123
r0ny123 deleted the fix/tail-merged-strings branch October 18, 2026 14:04
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.

2 participants