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,
ulTotalLength is a ULONGLONG, but it is printed with "%d" (which expects a 32-bit int). printf only reads the low 32 bits, so the resulting Content-Length is wrong whenever the response body exceeds ~2 GiB. The other two call sites format an unsigned int length with "%d" as well (should be %u).
- Off-by-one destination size.
StringCchPrintfA's cchDest argument is passed as sizeof(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);
Summary
In
iis/mymodule.cpp,StringCchPrintfAis used to build theContent-Lengthheader value, but it has two defects that corrupt the header for large responses: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).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-Lengthheader (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