mirror of
https://github.com/curl/curl.git
synced 2025-01-18 14:04:30 +08:00
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
This commit is contained in:
parent
ae4d1437f1
commit
4399b0303a
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user