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;
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);
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;
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')
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);
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);
}
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;
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;
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);
}
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;
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;
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;
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;
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 */
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;
}
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;
}
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;
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");
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;
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);
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);
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);
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;
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 */
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;
}
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;
}
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);
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)
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);
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;
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);
}
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;
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);
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;
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;
}
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;
}
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;
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;
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 */
};
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 */
};
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 */
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);
}
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;
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;
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);
}
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;