IIS: Content-Length header corrupted/truncated for large responses (wrong printf format + off-by-one buffer size)
Author: A13501350Created Aug 27, 2026Updated Sep 15, 2026
LabelsPlatform - IIS2.x
Summary
In iis/mymodule.cpp, StringCchPrintfA is used to build the Content-Length header value, but it has two defects that corrupt the header for large responses:
- Wrong format specifier for 64-bit value. At the response path,
ulTotalLengthis aULONGLONG, but it is printed with"%d"(which expects a 32-bitint).printfonly reads the low 32 bits, so the resultingContent-Lengthis wrong whenever the response body exceeds ~2 GiB. The other two call sites format anunsigned intlengthwith"%d"as well (should be%u). - Off-by-one destination size.
StringCchPrintfA'scchDestargument is passed assizeof(szLength)/sizeof(CHAR) - 1(= 20). Since this argument must include the null terminator, the buffer can only hold 19 digits. A 64-bit value can be 20 decimal digits (e.g.18446744073709551615), so it is silently truncated / the call fails.
Impact
When ModSecurity for IIS must synthesize the Content-Length header (the only-response, non-chunked case), a wrong value causes clients to hang or error because the body length does not match the advertised header.
Affected locations (v2/master)
iis/mymodule.cpp:642—ulTotalLength(ULONGLONG) ->"%llu"iis/mymodule.cpp:1140—length(unsigned int) ->"%u"iis/mymodule.cpp:1228—length(unsigned int) ->"%u"
All three should also pass the full buffer size sizeof(szLength)/sizeof(CHAR) (21) instead of ... - 1.
Suggested fix
CHAR szLength[21]; // Max length for a 64-bit int is 20 digits + null
ZeroMemory(szLength, sizeof(szLength));
HRESULT hr = StringCchPrintfA(
szLength,
sizeof(szLength) / sizeof(CHAR), // includes null terminator
"%llu", // ULONGLONG
ulTotalLength);Source: owasp-modsecurity/ModSecurity