]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: add `void *ctx` to reader/writer instances
authorStefan Eissing <stefan@eissing.org>
Wed, 6 Mar 2024 08:52:43 +0000 (09:52 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 6 Mar 2024 13:38:12 +0000 (14:38 +0100)
- `struct Curl_cwriter` and `struct Curl_creader` now carry a
  `void *ctx` member that points to the instance as allocated.
- using `r->ctx` and `w->ctx` as pointer to the instance specific
  struct that has been allocated

Reported-by: Rudi Heitbaum
Fixes #13035
Closes #13059

lib/cw-out.c
lib/ftp.c
lib/http_chunks.c
lib/mime.c
lib/sendf.c
lib/sendf.h
lib/smtp.c
lib/ws.c

index b29b45665a86e347aaf7eca824f58c14515e2b79..25a27a68cd6a1aee731bb4bec2e9d600669a9a67 100644 (file)
@@ -123,7 +123,7 @@ struct Curl_cwtype Curl_cwt_out = {
 static CURLcode cw_out_init(struct Curl_easy *data,
                             struct Curl_cwriter *writer)
 {
-  struct cw_out_ctx *ctx = (struct cw_out_ctx *)writer;
+  struct cw_out_ctx *ctx = writer->ctx;
   (void)data;
   ctx->buf = NULL;
   return CURLE_OK;
@@ -151,7 +151,7 @@ static size_t cw_out_bufs_len(struct cw_out_ctx *ctx)
 
 static void cw_out_close(struct Curl_easy *data, struct Curl_cwriter *writer)
 {
-  struct cw_out_ctx *ctx = (struct cw_out_ctx *)writer;
+  struct cw_out_ctx *ctx = writer->ctx;
 
   (void)data;
   cw_out_bufs_free(ctx);
@@ -378,7 +378,7 @@ static CURLcode cw_out_write(struct Curl_easy *data,
                              struct Curl_cwriter *writer, int type,
                              const char *buf, size_t blen)
 {
-  struct cw_out_ctx *ctx = (struct cw_out_ctx *)writer;
+  struct cw_out_ctx *ctx = writer->ctx;
   CURLcode result;
   bool flush_all;
 
index 8881bd364a3202a5363b08b663575d6818415945..2511bd4b6110b62a3d65f4333550ccbc935b3bf0 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -273,7 +273,7 @@ static CURLcode ftp_cw_lc_write(struct Curl_easy *data,
                                 const char *buf, size_t blen)
 {
   static const char nl = '\n';
-  struct ftp_cw_lc_ctx *ctx = (struct ftp_cw_lc_ctx *)writer;
+  struct ftp_cw_lc_ctx *ctx = writer->ctx;
 
   if(!(type & CLIENTWRITE_BODY) ||
      data->conn->proto.ftpc.transfertype != 'A')
index f9cb0741ea23d2b1924a255d78a4132deb532a5a..cfbd40bc28662cae3c562900c3395d45d9aefc14 100644 (file)
@@ -394,7 +394,7 @@ struct chunked_writer {
 static CURLcode cw_chunked_init(struct Curl_easy *data,
                                 struct Curl_cwriter *writer)
 {
-  struct chunked_writer *ctx = (struct chunked_writer *)writer;
+  struct chunked_writer *ctx = writer->ctx;
 
   data->req.chunk = TRUE;      /* chunks coming our way. */
   Curl_httpchunk_init(data, &ctx->ch, FALSE);
@@ -404,7 +404,7 @@ static CURLcode cw_chunked_init(struct Curl_easy *data,
 static void cw_chunked_close(struct Curl_easy *data,
                              struct Curl_cwriter *writer)
 {
-  struct chunked_writer *ctx = (struct chunked_writer *)writer;
+  struct chunked_writer *ctx = writer->ctx;
   Curl_httpchunk_free(data, &ctx->ch);
 }
 
@@ -412,7 +412,7 @@ static CURLcode cw_chunked_write(struct Curl_easy *data,
                                  struct Curl_cwriter *writer, int type,
                                  const char *buf, size_t blen)
 {
-  struct chunked_writer *ctx = (struct chunked_writer *)writer;
+  struct chunked_writer *ctx = writer->ctx;
   CURLcode result;
   size_t consumed;
 
@@ -474,7 +474,7 @@ struct chunked_reader {
 static CURLcode cr_chunked_init(struct Curl_easy *data,
                                 struct Curl_creader *reader)
 {
-  struct chunked_reader *ctx = (struct chunked_reader *)reader;
+  struct chunked_reader *ctx = reader->ctx;
   (void)data;
   Curl_bufq_init2(&ctx->chunkbuf, CURL_CHUNKED_MAXLEN, 2, BUFQ_OPT_SOFT_LIMIT);
   return CURLE_OK;
@@ -483,7 +483,7 @@ static CURLcode cr_chunked_init(struct Curl_easy *data,
 static void cr_chunked_close(struct Curl_easy *data,
                              struct Curl_creader *reader)
 {
-  struct chunked_reader *ctx = (struct chunked_reader *)reader;
+  struct chunked_reader *ctx = reader->ctx;
   (void)data;
   Curl_bufq_free(&ctx->chunkbuf);
 }
@@ -491,7 +491,7 @@ static void cr_chunked_close(struct Curl_easy *data,
 static CURLcode add_last_chunk(struct Curl_easy *data,
                                struct Curl_creader *reader)
 {
-  struct chunked_reader *ctx = (struct chunked_reader *)reader;
+  struct chunked_reader *ctx = reader->ctx;
   struct curl_slist *trailers = NULL, *tr;
   CURLcode result;
   size_t n;
@@ -542,7 +542,7 @@ static CURLcode add_chunk(struct Curl_easy *data,
                           struct Curl_creader *reader,
                           char *buf, size_t blen)
 {
-  struct chunked_reader *ctx = (struct chunked_reader *)reader;
+  struct chunked_reader *ctx = reader->ctx;
   CURLcode result;
   char tmp[CURL_CHUNKED_MINLEN];
   size_t nread;
@@ -595,7 +595,7 @@ static CURLcode cr_chunked_read(struct Curl_easy *data,
                                 char *buf, size_t blen,
                                 size_t *pnread, bool *peos)
 {
-  struct chunked_reader *ctx = (struct chunked_reader *)reader;
+  struct chunked_reader *ctx = reader->ctx;
   CURLcode result = CURLE_READ_ERROR;
 
   *pnread = 0;
index cccf46f897578979d4fc440b2a2b4eb9f6cc8a85..48a1ad87c7a18968fe255e594f33d4658393c5f1 100644 (file)
@@ -1928,7 +1928,7 @@ struct cr_mime_ctx {
 static CURLcode cr_mime_init(struct Curl_easy *data,
                              struct Curl_creader *reader)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
   (void)data;
   ctx->total_len = -1;
   ctx->read_len = 0;
@@ -1941,7 +1941,7 @@ static CURLcode cr_mime_read(struct Curl_easy *data,
                              char *buf, size_t blen,
                              size_t *pnread, bool *peos)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
   size_t nread;
 
   /* Once we have errored, we will return the same error forever */
@@ -2022,7 +2022,7 @@ static CURLcode cr_mime_read(struct Curl_easy *data,
 static bool cr_mime_needs_rewind(struct Curl_easy *data,
                                  struct Curl_creader *reader)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
   (void)data;
   return ctx->read_len > 0;
 }
@@ -2030,7 +2030,7 @@ static bool cr_mime_needs_rewind(struct Curl_easy *data,
 static curl_off_t cr_mime_total_length(struct Curl_easy *data,
                                        struct Curl_creader *reader)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
   (void)data;
   return ctx->total_len;
 }
@@ -2039,7 +2039,7 @@ static CURLcode cr_mime_resume_from(struct Curl_easy *data,
                                     struct Curl_creader *reader,
                                     curl_off_t offset)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
 
   if(offset > 0) {
     curl_off_t passed = 0;
@@ -2080,7 +2080,7 @@ static CURLcode cr_mime_resume_from(struct Curl_easy *data,
 static CURLcode cr_mime_rewind(struct Curl_easy *data,
                                struct Curl_creader *reader)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
   CURLcode result = mime_rewind(ctx->part);
   if(result)
     failf(data, "Cannot rewind mime/post data");
@@ -2090,7 +2090,7 @@ static CURLcode cr_mime_rewind(struct Curl_easy *data,
 static CURLcode cr_mime_unpause(struct Curl_easy *data,
                                 struct Curl_creader *reader)
 {
-  struct cr_mime_ctx *ctx = (struct cr_mime_ctx *)reader;
+  struct cr_mime_ctx *ctx = reader->ctx;
   (void)data;
   mime_unpause(ctx->part);
   return CURLE_OK;
@@ -2118,7 +2118,7 @@ CURLcode Curl_creader_set_mime(struct Curl_easy *data, curl_mimepart *part)
   result = Curl_creader_create(&r, data, &cr_mime, CURL_CR_CLIENT);
   if(result)
     return result;
-  ctx = (struct cr_mime_ctx *)r;
+  ctx = r->ctx;
   ctx->part = part;
   /* Make sure we will read the entire mime structure. */
   result = mime_rewind(ctx->part);
index 81f2deabdc0b3b4a475d9d1ef59cd138044a4723..ce9b2b07576ff24799d13902ff8629aa69e03e10 100644 (file)
@@ -236,7 +236,7 @@ static CURLcode cw_download_write(struct Curl_easy *data,
                                   struct Curl_cwriter *writer, int type,
                                   const char *buf, size_t nbytes)
 {
-  struct cw_download_ctx *ctx = (struct cw_download_ctx *)writer;
+  struct cw_download_ctx *ctx = writer->ctx;
   CURLcode result;
   size_t nwrite, excess_len = 0;
   bool is_connect = !!(type & CLIENTWRITE_CONNECT);
@@ -368,15 +368,18 @@ CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
                                    const struct Curl_cwtype *cwt,
                                    Curl_cwriter_phase phase)
 {
-  struct Curl_cwriter *writer;
+  struct Curl_cwriter *writer = NULL;
   CURLcode result = CURLE_OUT_OF_MEMORY;
+  void *p;
 
   DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
-  writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size);
-  if(!writer)
+  p = calloc(1, cwt->cwriter_size);
+  if(!p)
     goto out;
 
+  writer = (struct Curl_cwriter *)p;
   writer->cwt = cwt;
+  writer->ctx = p;
   writer->phase = phase;
   result = cwt->do_init(data, writer);
 
@@ -575,7 +578,7 @@ struct cr_in_ctx {
 
 static CURLcode cr_in_init(struct Curl_easy *data, struct Curl_creader *reader)
 {
-  struct cr_in_ctx *ctx = (struct cr_in_ctx *)reader;
+  struct cr_in_ctx *ctx = reader->ctx;
   (void)data;
   ctx->read_cb = data->state.fread_func;
   ctx->cb_user_data = data->state.in;
@@ -590,7 +593,7 @@ static CURLcode cr_in_read(struct Curl_easy *data,
                            char *buf, size_t blen,
                            size_t *pnread, bool *peos)
 {
-  struct cr_in_ctx *ctx = (struct cr_in_ctx *)reader;
+  struct cr_in_ctx *ctx = reader->ctx;
   size_t nread;
 
   /* Once we have errored, we will return the same error forever */
@@ -681,7 +684,7 @@ static CURLcode cr_in_read(struct Curl_easy *data,
 static bool cr_in_needs_rewind(struct Curl_easy *data,
                                struct Curl_creader *reader)
 {
-  struct cr_in_ctx *ctx = (struct cr_in_ctx *)reader;
+  struct cr_in_ctx *ctx = reader->ctx;
   (void)data;
   return ctx->has_used_cb;
 }
@@ -689,7 +692,7 @@ static bool cr_in_needs_rewind(struct Curl_easy *data,
 static curl_off_t cr_in_total_length(struct Curl_easy *data,
                                      struct Curl_creader *reader)
 {
-  struct cr_in_ctx *ctx = (struct cr_in_ctx *)reader;
+  struct cr_in_ctx *ctx = reader->ctx;
   (void)data;
   return ctx->total_len;
 }
@@ -698,7 +701,7 @@ static CURLcode cr_in_resume_from(struct Curl_easy *data,
                                   struct Curl_creader *reader,
                                   curl_off_t offset)
 {
-  struct cr_in_ctx *ctx = (struct cr_in_ctx *)reader;
+  struct cr_in_ctx *ctx = reader->ctx;
   int seekerr = CURL_SEEKFUNC_CANTSEEK;
 
   DEBUGASSERT(data->conn);
@@ -760,7 +763,7 @@ static CURLcode cr_in_resume_from(struct Curl_easy *data,
 static CURLcode cr_in_rewind(struct Curl_easy *data,
                              struct Curl_creader *reader)
 {
-  struct cr_in_ctx *ctx = (struct cr_in_ctx *)reader;
+  struct cr_in_ctx *ctx = reader->ctx;
 
   /* If we never invoked the callback, there is noting to rewind */
   if(!ctx->has_used_cb)
@@ -830,15 +833,18 @@ CURLcode Curl_creader_create(struct Curl_creader **preader,
                              const struct Curl_crtype *crt,
                              Curl_creader_phase phase)
 {
-  struct Curl_creader *reader;
+  struct Curl_creader *reader = NULL;
   CURLcode result = CURLE_OUT_OF_MEMORY;
+  void *p;
 
   DEBUGASSERT(crt->creader_size >= sizeof(struct Curl_creader));
-  reader = (struct Curl_creader *) calloc(1, crt->creader_size);
-  if(!reader)
+  p = calloc(1, crt->creader_size);
+  if(!p)
     goto out;
 
+  reader = (struct Curl_creader *)p;
   reader->crt = crt;
+  reader->ctx = p;
   reader->phase = phase;
   result = crt->do_init(data, reader);
 
@@ -866,7 +872,7 @@ struct cr_lc_ctx {
 
 static CURLcode cr_lc_init(struct Curl_easy *data, struct Curl_creader *reader)
 {
-  struct cr_lc_ctx *ctx = (struct cr_lc_ctx *)reader;
+  struct cr_lc_ctx *ctx = reader->ctx;
   (void)data;
   Curl_bufq_init2(&ctx->buf, (16 * 1024), 1, BUFQ_OPT_SOFT_LIMIT);
   return CURLE_OK;
@@ -874,7 +880,7 @@ static CURLcode cr_lc_init(struct Curl_easy *data, struct Curl_creader *reader)
 
 static void cr_lc_close(struct Curl_easy *data, struct Curl_creader *reader)
 {
-  struct cr_lc_ctx *ctx = (struct cr_lc_ctx *)reader;
+  struct cr_lc_ctx *ctx = reader->ctx;
   (void)data;
   Curl_bufq_free(&ctx->buf);
 }
@@ -885,7 +891,7 @@ static CURLcode cr_lc_read(struct Curl_easy *data,
                            char *buf, size_t blen,
                            size_t *pnread, bool *peos)
 {
-  struct cr_lc_ctx *ctx = (struct cr_lc_ctx *)reader;
+  struct cr_lc_ctx *ctx = reader->ctx;
   CURLcode result;
   size_t nread, i, start, n;
   bool eos;
@@ -1024,7 +1030,7 @@ CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len)
   result = Curl_creader_create(&r, data, &cr_in, CURL_CR_CLIENT);
   if(result)
     return result;
-  ctx = (struct cr_in_ctx *)r;
+  ctx = r->ctx;
   ctx->total_len = len;
 
   cl_reset_reader(data);
@@ -1161,7 +1167,7 @@ static CURLcode cr_buf_read(struct Curl_easy *data,
                             char *buf, size_t blen,
                             size_t *pnread, bool *peos)
 {
-  struct cr_buf_ctx *ctx = (struct cr_buf_ctx *)reader;
+  struct cr_buf_ctx *ctx = reader->ctx;
   size_t nread = ctx->blen - ctx->index;
 
   (void)data;
@@ -1183,7 +1189,7 @@ static CURLcode cr_buf_read(struct Curl_easy *data,
 static bool cr_buf_needs_rewind(struct Curl_easy *data,
                                 struct Curl_creader *reader)
 {
-  struct cr_buf_ctx *ctx = (struct cr_buf_ctx *)reader;
+  struct cr_buf_ctx *ctx = reader->ctx;
   (void)data;
   return ctx->index > 0;
 }
@@ -1191,7 +1197,7 @@ static bool cr_buf_needs_rewind(struct Curl_easy *data,
 static curl_off_t cr_buf_total_length(struct Curl_easy *data,
                                       struct Curl_creader *reader)
 {
-  struct cr_buf_ctx *ctx = (struct cr_buf_ctx *)reader;
+  struct cr_buf_ctx *ctx = reader->ctx;
   (void)data;
   return (curl_off_t)ctx->blen;
 }
@@ -1200,7 +1206,7 @@ static CURLcode cr_buf_resume_from(struct Curl_easy *data,
                                    struct Curl_creader *reader,
                                    curl_off_t offset)
 {
-  struct cr_buf_ctx *ctx = (struct cr_buf_ctx *)reader;
+  struct cr_buf_ctx *ctx = reader->ctx;
   size_t boffset;
 
   (void)data;
@@ -1242,7 +1248,7 @@ CURLcode Curl_creader_set_buf(struct Curl_easy *data,
   result = Curl_creader_create(&r, data, &cr_buf, CURL_CR_CLIENT);
   if(result)
     return result;
-  ctx = (struct cr_buf_ctx *)r;
+  ctx = r->ctx;
   ctx->buf = buf;
   ctx->blen = blen;
   ctx->index = 0;
index 2c5bc362086a1c84bc71a8047c2e2b9be3964e73..a62cfe8c6873de7d7752348ee4f4cb7ebc26dd9b 100644 (file)
@@ -117,10 +117,16 @@ struct Curl_cwtype {
   size_t cwriter_size;  /* sizeof() allocated struct Curl_cwriter */
 };
 
-/* Client writer instance */
+/* Client writer instance, allocated on creation.
+ * `void *ctx` is the pointer from the allocation of
+ * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
+ * by the writers implementation. See https://github.com/curl/curl/pull/13054
+ * for the alignment problems that arise otherwise.
+ */
 struct Curl_cwriter {
   const struct Curl_cwtype *cwt;  /* type implementation */
   struct Curl_cwriter *next;  /* Downstream writer. */
+  void *ctx;                  /* allocated instance pointer */
   Curl_cwriter_phase phase; /* phase at which it operates */
 };
 
@@ -214,10 +220,16 @@ typedef enum {
   CURL_CR_CLIENT  /* data read from client */
 } Curl_creader_phase;
 
-/* Client reader instance */
+/* Client reader instance, allocated on creation.
+ * `void *ctx` is the pointer from the allocation of
+ * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
+ * by the writers implementation. See https://github.com/curl/curl/pull/13054
+ * for the alignment problems that arise otherwise.
+ */
 struct Curl_creader {
   const struct Curl_crtype *crt;  /* type implementation */
   struct Curl_creader *next;  /* Downstream reader. */
+  void *ctx;
   Curl_creader_phase phase; /* phase at which it operates */
 };
 
index 2d8536008316ea907793ed12eaad31ba25533e45..b32ef36e4b3d42340db401b08ddf8568dcad6dd9 100644 (file)
@@ -1786,7 +1786,7 @@ struct cr_eob_ctx {
 static CURLcode cr_eob_init(struct Curl_easy *data,
                             struct Curl_creader *reader)
 {
-  struct cr_eob_ctx *ctx = (struct cr_eob_ctx *)reader;
+  struct cr_eob_ctx *ctx = reader->ctx;
   (void)data;
   /* The first char we read is the first on a line, as if we had
    * read CRLF just before */
@@ -1797,7 +1797,7 @@ static CURLcode cr_eob_init(struct Curl_easy *data,
 
 static void cr_eob_close(struct Curl_easy *data, struct Curl_creader *reader)
 {
-  struct cr_eob_ctx *ctx = (struct cr_eob_ctx *)reader;
+  struct cr_eob_ctx *ctx = reader->ctx;
   (void)data;
   Curl_bufq_free(&ctx->buf);
 }
@@ -1812,7 +1812,7 @@ static CURLcode cr_eob_read(struct Curl_easy *data,
                             char *buf, size_t blen,
                             size_t *pnread, bool *peos)
 {
-  struct cr_eob_ctx *ctx = (struct cr_eob_ctx *)reader;
+  struct cr_eob_ctx *ctx = reader->ctx;
   CURLcode result = CURLE_OK;
   size_t nread, i, start, n;
   bool eos;
index 37108946d41156665aed114d63f2fe42b675076e..263299761f8dbf3070534f6e74903280bb37e484 100644 (file)
--- a/lib/ws.c
+++ b/lib/ws.c
@@ -363,7 +363,7 @@ struct ws_cw_ctx {
 static CURLcode ws_cw_init(struct Curl_easy *data,
                            struct Curl_cwriter *writer)
 {
-  struct ws_cw_ctx *ctx = (struct ws_cw_ctx *)writer;
+  struct ws_cw_ctx *ctx = writer->ctx;
   (void)data;
   Curl_bufq_init2(&ctx->buf, WS_CHUNK_SIZE, 1, BUFQ_OPT_SOFT_LIMIT);
   return CURLE_OK;
@@ -371,7 +371,7 @@ static CURLcode ws_cw_init(struct Curl_easy *data,
 
 static void ws_cw_close(struct Curl_easy *data, struct Curl_cwriter *writer)
 {
-  struct ws_cw_ctx *ctx = (struct ws_cw_ctx *)writer;
+  struct ws_cw_ctx *ctx = writer->ctx;
   (void) data;
   Curl_bufq_free(&ctx->buf);
 }
@@ -423,7 +423,7 @@ static CURLcode ws_cw_write(struct Curl_easy *data,
                             struct Curl_cwriter *writer, int type,
                             const char *buf, size_t nbytes)
 {
-  struct ws_cw_ctx *ctx = (struct ws_cw_ctx *)writer;
+  struct ws_cw_ctx *ctx = writer->ctx;
   struct websocket *ws;
   CURLcode result;