From: 최대우 (Daewoo Choi) Date: Thu, 1 Oct 2026 03:59:44 +0000 (+0900) Subject: HTTP/3: avoid unaligned stores in Huffman encoding X-Git-Tag: release-1.31.8~3 X-Git-Url: https://git.kaiwu.me/ngx_http_auth_basic_module.html?a=commitdiff_plain;h=b38c9d8068ab55504aa4311f729803b503579520;p=nginx.git HTTP/3: avoid unaligned stores in Huffman encoding The encoder wrote accumulated bits by casting the destination to uint64_t *, or uint32_t * on 32-bit platforms, and assigning through it, which requires the destination to be suitably aligned. In HTTP/2 the destination is a temporary buffer from ngx_palloc() and is always aligned. In HTTP/3 it points past a variable number of prefix integer bytes, so its alignment is arbitrary and the store is undefined behaviour. Byte order conversion is now separated from the store, which is done with ngx_memcpy(). --- diff --git a/src/http/ngx_http_huff_encode.c b/src/http/ngx_http_huff_encode.c index c03b153da..7fff5eb0e 100644 --- a/src/http/ngx_http_huff_encode.c +++ b/src/http/ngx_http_huff_encode.c @@ -158,32 +158,19 @@ static ngx_http_huff_encode_code_t ngx_http_huff_encode_table_lc[256] = #if (NGX_PTR_SIZE == 8) -#if (NGX_HAVE_LITTLE_ENDIAN) - -#if (NGX_HAVE_GCC_BSWAP64) -#define ngx_http_huff_encode_buf(dst, buf) \ - (*(uint64_t *) (dst) = __builtin_bswap64(buf)) +#if !(NGX_HAVE_LITTLE_ENDIAN) +#define ngx_http_huff_encode_hton(buf) (buf) +#elif (NGX_HAVE_GCC_BSWAP64) +#define ngx_http_huff_encode_hton(buf) __builtin_bswap64(buf) #else -#define ngx_http_huff_encode_buf(dst, buf) \ - ((dst)[0] = (u_char) ((buf) >> 56), \ - (dst)[1] = (u_char) ((buf) >> 48), \ - (dst)[2] = (u_char) ((buf) >> 40), \ - (dst)[3] = (u_char) ((buf) >> 32), \ - (dst)[4] = (u_char) ((buf) >> 24), \ - (dst)[5] = (u_char) ((buf) >> 16), \ - (dst)[6] = (u_char) ((buf) >> 8), \ - (dst)[7] = (u_char) (buf)) -#endif - -#else /* !NGX_HAVE_LITTLE_ENDIAN */ -#define ngx_http_huff_encode_buf(dst, buf) \ - (*(uint64_t *) (dst) = (buf)) +#define ngx_http_huff_encode_hton(buf) \ + ((uint64_t) htonl((uint32_t) (buf)) << 32 \ + | htonl((uint32_t) ((buf) >> 32))) #endif #else /* NGX_PTR_SIZE == 4 */ -#define ngx_http_huff_encode_buf(dst, buf) \ - (*(uint32_t *) (dst) = htonl(buf)) +#define ngx_http_huff_encode_hton(buf) htonl(buf) #endif @@ -224,7 +211,8 @@ ngx_http_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower) buf |= code >> pending; - ngx_http_huff_encode_buf(&dst[hlen], buf); + buf = ngx_http_huff_encode_hton(buf); + ngx_memcpy(&dst[hlen], &buf, sizeof(buf)); hlen += sizeof(buf);