base64: avoid repeated input loads when encoding
No binary (build failed)
—
(log yok)
| @@ -207,10 +207,15 @@ static CURLcode base64_encode(const char *table64, | |
| return CURLE_OUT_OF_MEMORY; | |
| while(insize >= 3) { | |
| - | *output++ = table64[in[0] >> 2]; |
| - | *output++ = table64[((in[0] & 0x03) << 4) | (in[1] >> 4)]; |
| - | *output++ = table64[((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6)]; |
| - | *output++ = table64[in[2] & 0x3F]; |
| + | /* Load all three input bytes before storing output, avoiding reloads when |
| + | the compiler cannot rule out aliasing. Extract four 6-bit indices from |
| + | the packed value; byte-wise loads avoid alignment and endian issues. */ |
| + | uint32_t bits = ((uint32_t)in[0] << 16) | |
| + | ((uint32_t)in[1] << 8) | in[2]; |
| + | *output++ = table64[bits >> 18]; |
| + | *output++ = table64[(bits >> 12) & 0x3F]; |
| + | *output++ = table64[(bits >> 6) & 0x3F]; |
| + | *output++ = table64[bits & 0x3F]; |
| insize -= 3; | |
| in += 3; | |
| } | |
| @@ -162,6 +162,30 @@ static CURLcode test_unit1302(const char *arg) | |
| curlx_safefree(decoded); | |
| } | |
| + | { |
| + | unsigned char binary[256]; |
| + | size_t length; |
| + | for(i = 0; i < sizeof(binary); i++) |
| + | binary[i] = (unsigned char)i; |
| + | for(length = 1; length <= sizeof(binary); length++) { |
| + | char *encoded; |
| + | unsigned char *decoded; |
| + | size_t enclen; |
| + | size_t declen; |
| + | result = curlx_base64_encode(binary, length, &encoded, &enclen); |
| + | abort_unless(result == CURLE_OK, "binary encoding failed"); |
| + | fail_unless(enclen == (length + 2) / 3 * 4, "wrong encoded size"); |
| + | fail_unless(!encoded[enclen], "encoded data is not terminated"); |
| + | result = curlx_base64_decode(encoded, &decoded, &declen); |
| + | curlx_free(encoded); |
| + | abort_unless(result == CURLE_OK, "binary decoding failed"); |
| + | fail_unless(declen == length, "wrong decoded size"); |
| + | fail_unless(!memcmp(decoded, binary, length), "wrong decoded data"); |
| + | fail_unless(!decoded[declen], "decoded data is not terminated"); |
| + | curlx_free(decoded); |
| + | } |
| + | } |
| + | |
| for(i = 0; i < CURL_ARRAYSIZE(url); i++) { | |
| const struct etest *e = &url[i]; | |
| char *out; | |