@@ -1103,13 +1103,45 @@ size_t WinHttpConnection::GetResponseContentLength(_In_ WinHttpConnection* pRequ
11031103 }
11041104 }
11051105
1106- try
1107- {
1108- contentLength = std::stoi (responseHeader);
1109- }
1110- catch (const std::exception& e)
1111- {
1112- HC_TRACE_ERROR (HTTPCLIENT, " WinHttpConnection [%d] std::stoi error in callback_status_read_complete: %s" , E_FAIL, e.what ());
1106+ // If the Content-Length header is absent (e.g. for chunked transfer encoding) "result" will be FALSE
1107+ // with ERROR_WINHTTP_HEADER_NOT_FOUND. In that case (or any other failure) just return 0 which the
1108+ // caller treats as "unknown length" and progress reporting logic will skip total size tracking.
1109+ if (result && !responseHeader.empty ())
1110+ {
1111+ // WinHttp gives a null-terminated wide string. Validate it contains only digits before converting
1112+ // to avoid throwing exceptions on unexpected values (empty, whitespace, etc.).
1113+ const wchar_t * p = responseHeader.c_str ();
1114+ if (*p != L' \0 ' )
1115+ {
1116+ bool allDigits = true ;
1117+ for (; *p != L' \0 ' ; ++p)
1118+ {
1119+ if (*p < L' 0' || *p > L' 9' )
1120+ {
1121+ allDigits = false ;
1122+ break ;
1123+ }
1124+ }
1125+ if (allDigits)
1126+ {
1127+ // Use wcstoull for conversion without throwing
1128+ errno = 0 ;
1129+ wchar_t * endPtr = nullptr ;
1130+ unsigned long long value = wcstoull (responseHeader.c_str (), &endPtr, 10 );
1131+ if (errno == 0 && endPtr != responseHeader.c_str ())
1132+ {
1133+ contentLength = static_cast <size_t >(value);
1134+ }
1135+ else
1136+ {
1137+ HC_TRACE_WARNING (HTTPCLIENT, " WinHttpConnection: invalid Content-Length header value encountered (conversion failure). Treating as unknown." );
1138+ }
1139+ }
1140+ else
1141+ {
1142+ HC_TRACE_WARNING (HTTPCLIENT, " WinHttpConnection: non-numeric Content-Length header value encountered. Treating as unknown." );
1143+ }
1144+ }
11131145 }
11141146
11151147 return contentLength;
0 commit comments