winhttp: Fix a couple of corner cases in header processing.

This commit is contained in:
Hans Leidekker 2015-06-24 14:16:59 +02:00 committed by Alexandre Julliard
parent 49b6b60e23
commit 2516fb7807
2 changed files with 103 additions and 56 deletions

View File

@ -327,12 +327,8 @@ static header_t *parse_header( LPCWSTR string )
q++; /* skip past colon */
while (*q == ' ') q++;
if (!*q)
{
WARN("no value in line %s\n", debugstr_w(string));
return header;
}
len = strlenW( q );
if (!(header->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
{
free_header( header );
@ -404,76 +400,65 @@ static BOOL delete_header( request_t *request, DWORD index )
static BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only )
{
int index;
header_t *header;
header_t hdr;
TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags);
/* replace wins out over add */
if (flags & WINHTTP_ADDREQ_FLAG_REPLACE) flags &= ~WINHTTP_ADDREQ_FLAG_ADD;
if (flags & WINHTTP_ADDREQ_FLAG_ADD) index = -1;
else
index = get_header_index( request, field, 0, request_only );
if (index >= 0)
if ((index = get_header_index( request, field, 0, request_only )) >= 0)
{
if (flags & WINHTTP_ADDREQ_FLAG_ADD_IF_NEW) return FALSE;
header = &request->headers[index];
}
else if (value)
if (flags & WINHTTP_ADDREQ_FLAG_REPLACE)
{
header_t hdr;
if (index >= 0)
{
delete_header( request, index );
if (!value || !value[0]) return TRUE;
}
else if (!(flags & WINHTTP_ADDREQ_FLAG_ADD))
{
set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
return FALSE;
}
hdr.field = (LPWSTR)field;
hdr.value = (LPWSTR)value;
hdr.is_request = request_only;
return insert_header( request, &hdr );
}
/* no value to delete */
else return TRUE;
if (flags & WINHTTP_ADDREQ_FLAG_REPLACE)
else if (value)
{
delete_header( request, index );
if (value)
if ((flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)) &&
index >= 0)
{
header_t hdr;
WCHAR *tmp;
int len, len_orig, len_value;
header_t *header = &request->headers[index];
hdr.field = (LPWSTR)field;
hdr.value = (LPWSTR)value;
hdr.is_request = request_only;
len_orig = strlenW( header->value );
len_value = strlenW( value );
return insert_header( request, &hdr );
}
return TRUE;
}
else if (flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
{
WCHAR sep, *tmp;
int len, orig_len, value_len;
orig_len = strlenW( header->value );
value_len = strlenW( value );
if (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) sep = ',';
else sep = ';';
len = orig_len + value_len + 2;
if ((tmp = heap_realloc( header->value, (len + 1) * sizeof(WCHAR) )))
{
len = len_orig + len_value + 2;
if (!(tmp = heap_realloc( header->value, (len + 1) * sizeof(WCHAR) ))) return FALSE;
header->value = tmp;
header->value[len_orig++] = (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) ? ',' : ';';
header->value[len_orig++] = ' ';
header->value[orig_len] = sep;
orig_len++;
header->value[orig_len] = ' ';
orig_len++;
memcpy( &header->value[orig_len], value, value_len * sizeof(WCHAR) );
memcpy( &header->value[len_orig], value, len_value * sizeof(WCHAR) );
header->value[len] = 0;
return TRUE;
}
else
{
hdr.field = (LPWSTR)field;
hdr.value = (LPWSTR)value;
hdr.is_request = request_only;
return insert_header( request, &hdr );
}
}
return TRUE;
}
@ -2128,7 +2113,9 @@ static BOOL read_reply( request_t *request )
/* we rely on the fact that the protocol is ascii */
MultiByteToWideChar( CP_ACP, 0, status_code, len, status_codeW, len );
status_codeW[len] = 0;
if (!(process_header( request, attr_status, status_codeW, WINHTTP_ADDREQ_FLAG_REPLACE, FALSE ))) return FALSE;
if (!(process_header( request, attr_status, status_codeW,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE, FALSE )))
return FALSE;
len = status_code - buffer;
if (!(versionW = heap_alloc( len * sizeof(WCHAR) ))) return FALSE;
@ -2358,7 +2345,7 @@ static BOOL handle_redirect( request_t *request, DWORD status )
}
else heap_free( hostname );
if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
if (!(ret = open_connection( request ))) goto end;
heap_free( request->path );
@ -3227,7 +3214,8 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader(
goto done;
}
sprintfW( str, fmtW, header, value ? value : emptyW );
if (!WinHttpAddRequestHeaders( request->hrequest, str, len, WINHTTP_ADDREQ_FLAG_REPLACE ))
if (!WinHttpAddRequestHeaders( request->hrequest, str, len,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))
{
err = get_last_error();
}

View File

@ -420,6 +420,8 @@ static void test_WinHttpAddHeaders(void)
{'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0','/','p','o','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
static const WCHAR test_header_name2[] = {'n','a','m','e',0};
static const WCHAR test_header_name3[] = {'a',0};
static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
@ -438,6 +440,7 @@ static void test_WinHttpAddHeaders(void)
static const WCHAR field[] = {'f','i','e','l','d',0};
static const WCHAR value[] = {'v','a','l','u','e',' ',0};
static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
static const WCHAR empty[] = {0};
static const WCHAR test_headers[][14] =
{
@ -454,7 +457,9 @@ static void test_WinHttpAddHeaders(void)
{':','b',0},
{'c','d',0},
{' ','e',' ',':','f',0},
{'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0}
{'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
{'n','a','m','e',':',' ','v','a','l','u','e',0},
{'n','a','m','e',':',0}
};
static const WCHAR test_indices[][6] =
{
@ -763,6 +768,14 @@ static void test_WinHttpAddHeaders(void)
ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
ok(ret, "WinHttpAddRequestHeaders failed\n");
index = 0;
memset(buffer, 0xff, sizeof(buffer));
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name3, buffer, &len, &index);
ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
ok(!ret, "WinHttpAddRequestHeaders failed\n");
@ -803,6 +816,52 @@ static void test_WinHttpAddHeaders(void)
ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
ok(index == 1, "wrong index %u\n", index);
index = 0;
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
ok(!ret, "unexpected success\n");
SetLastError(0xdeadbeef);
ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
err = GetLastError();
ok(!ret, "unexpected success\n");
ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
ok(ret, "got %u\n", GetLastError());
index = 0;
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
ok(ret, "got %u\n", GetLastError());
ok(index == 1, "wrong index %u\n", index);
ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
ok(ret, "got %u\n", GetLastError());
index = 0;
len = sizeof(buffer);
SetLastError(0xdeadbeef);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
err = GetLastError();
ok(!ret, "unexpected success\n");
ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
ok(ret, "got %u\n", GetLastError());
index = 0;
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
ok(ret, "got %u\n", GetLastError());
ok(index == 1, "wrong index %u\n", index);
ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
ret = WinHttpCloseHandle(request);
ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
done: