From: Daniel Stenberg Date: Wed, 25 Jun 2025 06:14:58 +0000 (+0200) Subject: urlapi: use uppercase hex encoding X-Git-Tag: curl-8_15_0~154 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b5593a6fe06db9541b6a6221085d9f959a8b0c54;p=thirdparty%2Fcurl.git urlapi: use uppercase hex encoding For consistency. RFC 3986 section 2.1 says: "URI producers and normalizers should use uppercase hexadecimal digits for all percent-encodings." Reported-by: Jeroen Ooms Fixes #17685 Closes #17739 --- diff --git a/lib/escape.c b/lib/escape.c index 3cd906dc6c..a292ba3b62 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -85,7 +85,7 @@ char *curl_easy_escape(CURL *data, const char *string, else { /* encode it */ unsigned char out[3]={'%'}; - Curl_hexbyte(&out[1], in, FALSE); + Curl_hexbyte(&out[1], in); if(curlx_dyn_addn(&d, out, 3)) return NULL; } @@ -212,7 +212,8 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */ DEBUGASSERT(src && len && (olen >= 3)); if(src && len && (olen >= 3)) { while(len-- && (olen >= 3)) { - Curl_hexbyte(out, *src, TRUE); + out[0] = Curl_ldigits[*src >> 4]; + out[1] = Curl_ldigits[*src & 0x0F]; ++src; out += 2; olen -= 2; @@ -225,14 +226,11 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */ /* Curl_hexbyte * - * Output a single unsigned char as a two-digit hex number, lowercase or - * uppercase + * Output a single unsigned char as a two-digit UPPERCASE hex number. */ void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */ - unsigned char val, - bool lowercase) + unsigned char val) { - const unsigned char *t = lowercase ? Curl_ldigits : Curl_udigits; - dest[0] = t[val >> 4]; - dest[1] = t[val & 0x0F]; + dest[0] = Curl_udigits[val >> 4]; + dest[1] = Curl_udigits[val & 0x0F]; } diff --git a/lib/escape.h b/lib/escape.h index 1f2bac8fac..a43fc38ed3 100644 --- a/lib/escape.h +++ b/lib/escape.h @@ -42,7 +42,6 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */ unsigned char *out, size_t olen); /* output buffer size */ void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */ - unsigned char val, - bool lowercase); + unsigned char val); #endif /* HEADER_CURL_ESCAPE_H */ diff --git a/lib/urlapi.c b/lib/urlapi.c index 1a1700adb8..87636941b7 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -164,7 +164,7 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url, } else if((*iptr < ' ') || (*iptr >= 0x7f)) { unsigned char out[3]={'%'}; - Curl_hexbyte(&out[1], *iptr, TRUE); + Curl_hexbyte(&out[1], *iptr); result = curlx_dyn_addn(o, out, 3); } else { @@ -1861,7 +1861,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, } else { unsigned char out[3]={'%'}; - Curl_hexbyte(&out[1], *i, TRUE); + Curl_hexbyte(&out[1], *i); result = curlx_dyn_addn(&enc, out, 3); if(result) return cc2cu(result); diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c index 8487d43e8c..2fd25089d9 100644 --- a/lib/vtls/keylog.c +++ b/lib/vtls/keylog.c @@ -134,14 +134,14 @@ Curl_tls_keylog_write(const char *label, /* Client Random */ for(i = 0; i < CLIENT_RANDOM_SIZE; i++) { - Curl_hexbyte(&line[pos], client_random[i], FALSE); + Curl_hexbyte(&line[pos], client_random[i]); pos += 2; } line[pos++] = ' '; /* Secret */ for(i = 0; i < secretlen; i++) { - Curl_hexbyte(&line[pos], secret[i], FALSE); + Curl_hexbyte(&line[pos], secret[i]); pos += 2; } line[pos++] = '\n'; diff --git a/tests/data/test1138 b/tests/data/test1138 index 1f125f5844..ec7048c4ad 100644 --- a/tests/data/test1138 +++ b/tests/data/test1138 @@ -62,7 +62,7 @@ Host: %HOSTIP:%HTTPPORT User-Agent: curl/%VERSION Accept: */* -GET /we/are/all/moo.html/?name=%d8%a2%d8%ba%d8%a7%d8%b2-%d8%b3%d9%85-%d8%b2%d8%af%d8%a7%db%8c%db%8c-%d8%a7%d8%b2-%d8%a8%d8%a7%d8%b2%d8%a7%d8%b1-%d9%be%d9%88%d9%84&testcase=/%TESTNUMBER0002 HTTP/1.1 +GET /we/are/all/moo.html/?name=%D8%A2%D8%BA%D8%A7%D8%B2-%D8%B3%D9%85-%D8%B2%D8%AF%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%A8%D8%A7%D8%B2%D8%A7%D8%B1-%D9%BE%D9%88%D9%84&testcase=/%TESTNUMBER0002 HTTP/1.1 Host: %HOSTIP:%HTTPPORT User-Agent: curl/%VERSION Accept: */* diff --git a/tests/data/test472 b/tests/data/test472 index 3b4cf74764..d624760040 100644 --- a/tests/data/test472 +++ b/tests/data/test472 @@ -48,9 +48,9 @@ aws-sigv4 with query # Verify data after the test has been "shot" -GET /472/a=%e3%81%82 HTTP/1.1 +GET /472/a=%E3%81%82 HTTP/1.1 Host: fake.fake.fake:8000 -Authorization: AWS4-HMAC-SHA256 Credential=user/19700101/us-east-2/es/aws4_request, SignedHeaders=host;x-amz-date, Signature=d2f4797c813fc51d729ac555a23ac682be908fdbfae2042ba98d214c9298201b +Authorization: AWS4-HMAC-SHA256 Credential=user/19700101/us-east-2/es/aws4_request, SignedHeaders=host;x-amz-date, Signature=b8783c8387a5249b084642126fe1f8e07e12a2847820fd5b6cd64b2047149da4 X-Amz-Date: 19700101T000000Z User-Agent: curl/%VERSION Accept: */* diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c index fb8633058d..d1fc04359e 100644 --- a/tests/libtest/lib1560.c +++ b/tests/libtest/lib1560.c @@ -242,14 +242,14 @@ static const struct testcase get_parts_list[] ={ {"https://" "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4", "https | [11] | [12] | [13] | " - "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4 " + "%E2%84%82%E1%B5%A4%E2%93%87%E2%84%92%E3%80%82%F0%9D%90%92%F0%9F%84%B4 " "| [15] | / | [16] | [17]", 0, CURLU_URLENCODE, CURLUE_OK}, {"https://" "\xe2\x84\x82\xe1\xb5\xa4\xe2\x93\x87\xe2\x84\x92" "\xe3\x80\x82\xf0\x9d\x90\x92\xf0\x9f\x84\xb4", "https | [11] | [12] | [13] | " - "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4 " + "%E2%84%82%E1%B5%A4%E2%93%87%E2%84%92%E3%80%82%F0%9D%90%92%F0%9F%84%B4 " "| [15] | / | [16] | [17]", 0, CURLU_URLENCODE, CURLUE_OK}, {"https://user@example.net?he l lo", @@ -651,7 +651,7 @@ static const struct urltestcase get_url_list[] = { {"http://example.com%2F127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME}, {"https://%41", "https://A/", 0, 0, CURLUE_OK}, {"https://%20", "", 0, 0, CURLUE_BAD_HOSTNAME}, - {"https://%41%0d", "", 0, 0, CURLUE_BAD_HOSTNAME}, + {"https://%41%0D", "", 0, 0, CURLUE_BAD_HOSTNAME}, {"https://%25", "", 0, 0, CURLUE_BAD_HOSTNAME}, {"https://_%c0_", "https://_\xC0_/", 0, 0, CURLUE_OK}, {"https://_%c0_", "https://_%C0_/", 0, CURLU_URLENCODE, CURLUE_OK}, @@ -913,11 +913,11 @@ static const struct setcase set_parts_list[] = { 0, 0, CURLUE_OK, CURLUE_OK}, {"https://example.com/", "path=one\ntwo,", - "https://example.com/one%0atwo", + "https://example.com/one%0Atwo", 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK}, {"https://example.com/", "path=one\rtwo,", - "https://example.com/one%0dtwo", + "https://example.com/one%0Dtwo", 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK}, {"https://example.com/", "host=%43url.se,", @@ -1001,7 +1001,7 @@ static const struct setcase set_parts_list[] = { {"https://example.com/", "query=Al2cO3tDkcDZ3EWE5Lh+LX8TPHs,", /* contains '+' */ - "https://example.com/?Al2cO3tDkcDZ3EWE5Lh%2bLX8TPHs", + "https://example.com/?Al2cO3tDkcDZ3EWE5Lh%2BLX8TPHs", CURLU_URLDECODE, /* decode on get */ CURLU_URLENCODE, /* encode on set */ CURLUE_OK, CURLUE_OK}, @@ -1063,7 +1063,7 @@ static const struct setcase set_parts_list[] = { 0, 0, CURLUE_OK, CURLUE_OK}, {NULL, "scheme=https,user= @:,host=foobar,", - "https://%20%20%20%40%3a@foobar/", + "https://%20%20%20%40%3A@foobar/", 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK}, /* Setting a host name with spaces is not OK: */ {NULL, @@ -1076,7 +1076,7 @@ static const struct setcase set_parts_list[] = { 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK}, {NULL, "scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,", - "https://foobar/%c3%a4%c3%b6%c3%bc", + "https://foobar/%C3%A4%C3%B6%C3%BC", 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK}, {"imap://user:secret;opt@host/", "options=updated,scheme=imaps,password=p4ssw0rd,", @@ -1598,7 +1598,7 @@ static int get_parts(void) static const struct querycase append_list[] = { {"HTTP://test/?s", "name=joe\x02", "http://test/?s&name=joe%02", 0, CURLU_URLENCODE, CURLUE_OK}, - {"HTTP://test/?size=2#f", "name=joe=", "http://test/?size=2&name=joe%3d#f", + {"HTTP://test/?size=2#f", "name=joe=", "http://test/?size=2&name=joe%3D#f", 0, CURLU_URLENCODE, CURLUE_OK}, {"HTTP://test/?size=2#f", "name=joe doe", "http://test/?size=2&name=joe+doe#f",