From: Patrick Monnerat Date: Fri, 9 Sep 2022 11:25:02 +0000 (+0200) Subject: content_encoding: use writer struct subclasses for different encodings X-Git-Tag: curl-7_86_0~261 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4399b0303a332552c7bf11b1399cf9107cd4b294;p=thirdparty%2Fcurl.git content_encoding: use writer struct subclasses for different encodings The variable-sized encoding-specific storage of a struct contenc_writer currently relies on void * alignment that may be insufficient with regards to the specific storage fields, although having not caused any problems yet. In addition, gcc 11.3 issues a warning on access to fields of partially allocated structures that can occur when the specific storage size is 0: content_encoding.c: In function ‘Curl_build_unencoding_stack’: content_encoding.c:980:21: warning: array subscript ‘struct contenc_writer[0]’ is partly outside array bounds of ‘unsigned char[16]’ [-Warray-bounds] 980 | writer->handler = handler; | ~~~~~~~~~~~~~~~~^~~~~~~~~ In file included from content_encoding.c:49: memdebug.h:115:29: note: referencing an object of size 16 allocated by ‘curl_dbg_calloc’ 115 | #define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ content_encoding.c:977:60: note: in expansion of macro ‘calloc’ 977 | struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz); To solve both these problems, the current commit replaces the contenc_writer/params structure pairs by "subclasses" of struct contenc_writer. These are structures that contain a contenc_writer at offset 0. Proper field alignment is therefore handled by the compiler and full structure allocation is performed, silencing the warnings. Closes #9455 --- diff --git a/lib/content_encoding.c b/lib/content_encoding.c index 8e8f4df7c6..79ff8363cb 100644 --- a/lib/content_encoding.c +++ b/lib/content_encoding.c @@ -82,8 +82,9 @@ typedef enum { ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ } zlibInitState; -/* Writer parameters. */ -struct zlib_params { +/* Deflate and gzip writer. */ +struct zlib_writer { + struct contenc_writer super; zlibInitState zlib_init; /* zlib init state */ uInt trailerlen; /* Remaining trailer byte count. */ z_stream z; /* State structure for zlib. */ @@ -135,7 +136,7 @@ exit_zlib(struct Curl_easy *data, } static CURLcode process_trailer(struct Curl_easy *data, - struct zlib_params *zp) + struct zlib_writer *zp) { z_stream *z = &zp->z; CURLcode result = CURLE_OK; @@ -162,7 +163,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, struct contenc_writer *writer, zlibInitState started) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ uInt nread = z->avail_in; Bytef *orig_in = z->next_in; @@ -265,7 +266,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, static CURLcode deflate_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ if(!writer->downstream) @@ -285,7 +286,7 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ /* Set the compressed input when this function is called */ @@ -302,7 +303,7 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data, static void deflate_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ exit_zlib(data, z, &zp->zlib_init, CURLE_OK); @@ -314,7 +315,7 @@ static const struct content_encoding deflate_encoding = { deflate_init_writer, deflate_unencode_write, deflate_close_writer, - sizeof(struct zlib_params) + sizeof(struct zlib_writer) }; @@ -322,7 +323,7 @@ static const struct content_encoding deflate_encoding = { static CURLcode gzip_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ if(!writer->downstream) @@ -439,7 +440,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ if(zp->zlib_init == ZLIB_INIT_GZIP) { @@ -566,7 +567,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, static void gzip_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct zlib_params *zp = (struct zlib_params *) &writer->params; + struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ exit_zlib(data, z, &zp->zlib_init, CURLE_OK); @@ -578,15 +579,16 @@ static const struct content_encoding gzip_encoding = { gzip_init_writer, gzip_unencode_write, gzip_close_writer, - sizeof(struct zlib_params) + sizeof(struct zlib_writer) }; #endif /* HAVE_LIBZ */ #ifdef HAVE_BROTLI -/* Writer parameters. */ -struct brotli_params { +/* Brotli writer. */ +struct brotli_writer { + struct contenc_writer super; BrotliDecoderState *br; /* State structure for brotli. */ }; @@ -631,7 +633,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) static CURLcode brotli_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct brotli_params *bp = (struct brotli_params *) &writer->params; + struct brotli_writer *bp = (struct brotli_writer *) writer; (void) data; if(!writer->downstream) @@ -645,7 +647,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) { - struct brotli_params *bp = (struct brotli_params *) &writer->params; + struct brotli_writer *bp = (struct brotli_writer *) writer; const uint8_t *src = (const uint8_t *) buf; char *decomp; uint8_t *dst; @@ -692,7 +694,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data, static void brotli_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct brotli_params *bp = (struct brotli_params *) &writer->params; + struct brotli_writer *bp = (struct brotli_writer *) writer; + (void) data; if(bp->br) { @@ -707,14 +710,15 @@ static const struct content_encoding brotli_encoding = { brotli_init_writer, brotli_unencode_write, brotli_close_writer, - sizeof(struct brotli_params) + sizeof(struct brotli_writer) }; #endif #ifdef HAVE_ZSTD -/* Writer parameters. */ -struct zstd_params { +/* Zstd writer. */ +struct zstd_writer { + struct contenc_writer super; ZSTD_DStream *zds; /* State structure for zstd. */ void *decomp; }; @@ -722,7 +726,8 @@ struct zstd_params { static CURLcode zstd_init_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct zstd_params *zp = (struct zstd_params *)&writer->params; + struct zstd_writer *zp = (struct zstd_writer *) writer; + (void)data; if(!writer->downstream) @@ -738,7 +743,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data, const char *buf, size_t nbytes) { CURLcode result = CURLE_OK; - struct zstd_params *zp = (struct zstd_params *)&writer->params; + struct zstd_writer *zp = (struct zstd_writer *) writer; ZSTD_inBuffer in; ZSTD_outBuffer out; size_t errorCode; @@ -777,7 +782,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data, static void zstd_close_writer(struct Curl_easy *data, struct contenc_writer *writer) { - struct zstd_params *zp = (struct zstd_params *)&writer->params; + struct zstd_writer *zp = (struct zstd_writer *) writer; + (void)data; if(zp->decomp) { @@ -796,7 +802,7 @@ static const struct content_encoding zstd_encoding = { zstd_init_writer, zstd_unencode_write, zstd_close_writer, - sizeof(struct zstd_params) + sizeof(struct zstd_writer) }; #endif @@ -829,7 +835,7 @@ static const struct content_encoding identity_encoding = { identity_init_writer, identity_unencode_write, identity_close_writer, - 0 + sizeof(struct contenc_writer) }; @@ -921,7 +927,7 @@ static const struct content_encoding client_encoding = { client_init_writer, client_unencode_write, client_close_writer, - 0 + sizeof(struct contenc_writer) }; @@ -964,7 +970,7 @@ static const struct content_encoding error_encoding = { error_init_writer, error_unencode_write, error_close_writer, - 0 + sizeof(struct contenc_writer) }; /* Create an unencoding writer stage using the given handler. */ @@ -973,8 +979,10 @@ new_unencoding_writer(struct Curl_easy *data, const struct content_encoding *handler, struct contenc_writer *downstream) { - size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize; - struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz); + struct contenc_writer *writer; + + DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer)); + writer = (struct contenc_writer *) calloc(1, handler->writersize); if(writer) { writer->handler = handler; diff --git a/lib/content_encoding.h b/lib/content_encoding.h index 81bddd1be1..3c278cf727 100644 --- a/lib/content_encoding.h +++ b/lib/content_encoding.h @@ -28,7 +28,6 @@ struct contenc_writer { const struct content_encoding *handler; /* Encoding handler. */ struct contenc_writer *downstream; /* Downstream writer. */ - void *params; /* Encoding-specific storage (variable length). */ }; /* Content encoding writer. */ @@ -42,7 +41,7 @@ struct content_encoding { const char *buf, size_t nbytes); void (*close_writer)(struct Curl_easy *data, struct contenc_writer *writer); - size_t paramsize; + size_t writersize; };