Skip to content

mprintf: use size_t width for the bare Windows %I modifier - #23030

Closed
bagder wants to merge 5 commits into
masterfrom
bagder/mprintf-I
Closed

bagder wants to merge 5 commits into
masterfrom
bagder/mprintf-I

Conversation

@bagder

@bagder bagder commented Sep 22, 2026

Copy link
Copy Markdown
Member

The bare "%I" length modifier (without an explicit "32" or "64" suffix) is Microsoft's non-standard way to size an integer conversion to the platform's native pointer/size_t width: 4 bytes on 32-bit Windows, 8 bytes on 64-bit Windows. parse_flags() instead based the choice on SIZEOF_CURL_OFF_T, which is 8 on both, so on 32-bit Windows a bare "%In"/"%Id"/"%Iu" was always treated as 8-byte wide. For "%n" this made the MTYPE_INTPTR sink write an 8-byte int64_t through a caller-supplied pointer to a 4-byte destination, corrupting adjacent memory; for "%Id"/"%Iu" it fetched 8 bytes from the argument list where the caller passed a 4-byte value.

Switch the bare "%I" case to SIZEOF_SIZE_T, matching the same pattern already used for "%z". Explicit "%I32"/"%I64" are unaffected. curl's own code does not use the bare "%I" modifier anywhere.

Added test 1451 for verification (Windows-only).

Reported-by: Joshua Rogers

The bare "%I" length modifier (without an explicit "32" or "64"
suffix) is Microsoft's non-standard way to size an integer conversion
to the platform's native pointer/size_t width: 4 bytes on 32-bit
Windows, 8 bytes on 64-bit Windows. parse_flags() instead based the
choice on SIZEOF_CURL_OFF_T, which is 8 on both, so on 32-bit Windows
a bare "%In"/"%Id"/"%Iu" was always treated as 8-byte wide. For "%n"
this made the MTYPE_INTPTR sink write an 8-byte int64_t through a
caller-supplied pointer to a 4-byte destination, corrupting adjacent
memory; for "%Id"/"%Iu" it fetched 8 bytes from the argument list
where the caller passed a 4-byte value.

Switch the bare "%I" case to SIZEOF_SIZE_T, matching the same pattern
already used for "%z". Explicit "%I32"/"%I64" are unaffected. curl's
own code does not use the bare "%I" modifier anywhere.

Added test 1451 for verification (Windows-only).

Reported-by: Joshua Rogers
@bagder bagder added the Windows Windows-specific label Sep 22, 2026
@github-actions github-actions Bot added the tests label Sep 22, 2026
@bagder
bagder marked this pull request as ready for review September 22, 2026 07:31
@bagder
bagder requested a balanced review from Copilot September 22, 2026 07:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Test 1451 does not select libtests, so the new regression test will not execute.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Corrects bare Windows %I handling to use native size_t width and adds regression coverage.

Changes:

  • Selects width using SIZEOF_SIZE_T.
  • Adds Windows tests for %In and %Iu.
  • Registers test 1451.
File Description
lib/​mprintf.c Corrects bare %I width selection.
tests/​libtest/​lib1451.c Adds formatting regression checks.
tests/​libtest/​Makefile.inc Registers the libtest source.
tests/​data/​test1451 Defines the Windows test case.
tests/​data/​Makefile.am Registers test 1451.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/data/test1451
@bagder bagder closed this in 424d247 Sep 22, 2026
@bagder
bagder deleted the bagder/mprintf-I branch September 22, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Windows Windows-specific

Development

Successfully merging this pull request may close these issues.

3 participants