1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-24 00:58:48 -05:00

http: made Curl_add_buffer functions take a pointer-pointer

... so that they can clear the original pointer on failure, which makes
the error-paths and their cleanups easier.

Closes #2992
This commit is contained in:
Daniel Stenberg 2018-09-14 11:48:53 +02:00
parent 130c53b632
commit 55dbcb061d
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 141 additions and 105 deletions

View File

@ -1094,11 +1094,13 @@ Curl_send_buffer *Curl_add_buffer_init(void)
/* /*
* Curl_add_buffer_free() frees all associated resources. * Curl_add_buffer_free() frees all associated resources.
*/ */
void Curl_add_buffer_free(Curl_send_buffer *buff) void Curl_add_buffer_free(Curl_send_buffer **inp)
{ {
if(buff) /* deal with NULL input */ Curl_send_buffer *in = *inp;
free(buff->buffer); if(in) /* deal with NULL input */
free(buff); free(in->buffer);
free(in);
*inp = NULL;
} }
/* /*
@ -1107,7 +1109,7 @@ void Curl_add_buffer_free(Curl_send_buffer *buff)
* *
* Returns CURLcode * Returns CURLcode
*/ */
CURLcode Curl_add_buffer_send(Curl_send_buffer *in, CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
struct connectdata *conn, struct connectdata *conn,
/* add the number of sent bytes to this /* add the number of sent bytes to this
@ -1128,6 +1130,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
size_t sendsize; size_t sendsize;
curl_socket_t sockfd; curl_socket_t sockfd;
size_t headersize; size_t headersize;
Curl_send_buffer *in = *inp;
DEBUGASSERT(socketindex <= SECONDARYSOCKET); DEBUGASSERT(socketindex <= SECONDARYSOCKET);
@ -1148,7 +1151,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
/* Curl_convert_to_network calls failf if unsuccessful */ /* Curl_convert_to_network calls failf if unsuccessful */
if(result) { if(result) {
/* conversion failed, free memory and return to the caller */ /* conversion failed, free memory and return to the caller */
Curl_add_buffer_free(in); Curl_add_buffer_free(inp);
return result; return result;
} }
@ -1172,7 +1175,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
result = Curl_get_upload_buffer(data); result = Curl_get_upload_buffer(data);
if(result) { if(result) {
/* malloc failed, free memory and return to the caller */ /* malloc failed, free memory and return to the caller */
Curl_add_buffer_free(in); Curl_add_buffer_free(&in);
return result; return result;
} }
memcpy(data->state.ulbuf, ptr, sendsize); memcpy(data->state.ulbuf, ptr, sendsize);
@ -1256,7 +1259,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
Curl_pipeline_leave_write(conn); Curl_pipeline_leave_write(conn);
} }
} }
Curl_add_buffer_free(in); Curl_add_buffer_free(&in);
return result; return result;
} }
@ -1265,31 +1268,35 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
/* /*
* add_bufferf() add the formatted input to the buffer. * add_bufferf() add the formatted input to the buffer.
*/ */
CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...) CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
{ {
char *s; char *s;
va_list ap; va_list ap;
Curl_send_buffer *in = *inp;
va_start(ap, fmt); va_start(ap, fmt);
s = vaprintf(fmt, ap); /* this allocs a new string to append */ s = vaprintf(fmt, ap); /* this allocs a new string to append */
va_end(ap); va_end(ap);
if(s) { if(s) {
CURLcode result = Curl_add_buffer(in, s, strlen(s)); CURLcode result = Curl_add_buffer(inp, s, strlen(s));
free(s); free(s);
return result; return result;
} }
/* If we failed, we cleanup the whole buffer and return error */ /* If we failed, we cleanup the whole buffer and return error */
free(in->buffer); free(in->buffer);
free(in); free(in);
*inp = NULL;
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
/* /*
* add_buffer() appends a memory chunk to the existing buffer * Curl_add_buffer() appends a memory chunk to the existing buffer
*/ */
CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
size_t size)
{ {
char *new_rb; char *new_rb;
Curl_send_buffer *in = *inp;
if(~size < in->size_used) { if(~size < in->size_used) {
/* If resulting used size of send buffer would wrap size_t, cleanup /* If resulting used size of send buffer would wrap size_t, cleanup
@ -1297,6 +1304,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
size will fit into a single allocatable memory chunk */ size will fit into a single allocatable memory chunk */
Curl_safefree(in->buffer); Curl_safefree(in->buffer);
free(in); free(in);
*inp = NULL;
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -1323,6 +1331,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
if(!new_rb) { if(!new_rb) {
/* If we failed, we cleanup the whole buffer and return error */ /* If we failed, we cleanup the whole buffer and return error */
free(in); free(in);
*inp = NULL;
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -1484,11 +1493,11 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
if(!req_buffer) if(!req_buffer)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
result = Curl_add_bufferf(req_buffer, proxy_header); result = Curl_add_bufferf(&req_buffer, proxy_header);
if(result) if(result)
return result; return result;
result = Curl_add_buffer_send(req_buffer, result = Curl_add_buffer_send(&req_buffer,
conn, conn,
&conn->data->info.request_size, &conn->data->info.request_size,
0, 0,
@ -1561,8 +1570,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
if(http->send_buffer) { if(http->send_buffer) {
Curl_add_buffer_free(http->send_buffer); Curl_add_buffer_free(&http->send_buffer);
http->send_buffer = NULL; /* clear the pointer */
} }
Curl_http2_done(conn, premature); Curl_http2_done(conn, premature);
@ -1653,8 +1661,8 @@ static CURLcode expect100(struct Curl_easy *data,
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");
} }
else { else {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Expect: 100-continue\r\n"); "Expect: 100-continue\r\n");
if(!result) if(!result)
data->state.expect100header = TRUE; data->state.expect100header = TRUE;
} }
@ -1785,7 +1793,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name))) !strcasecompare(data->state.first_host, conn->host.name)))
; ;
else { else {
result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data); result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data);
} }
if(semicolonp) if(semicolonp)
*semicolonp = ';'; /* put back the semicolon */ *semicolonp = ';'; /* put back the semicolon */
@ -1854,7 +1862,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
tm->tm_min, tm->tm_min,
tm->tm_sec); tm->tm_sec);
result = Curl_add_buffer(req_buffer, datestr, strlen(datestr)); result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
return result; return result;
} }
@ -2419,7 +2427,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* add the main request stuff */ /* add the main request stuff */
/* GET/HEAD/POST/PUT */ /* GET/HEAD/POST/PUT */
result = Curl_add_bufferf(req_buffer, "%s ", request); result = Curl_add_bufferf(&req_buffer, "%s ", request);
if(result) if(result)
return result; return result;
@ -2428,16 +2436,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* url */ /* url */
if(paste_ftp_userpwd) if(paste_ftp_userpwd)
result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s",
conn->user, conn->passwd, conn->user, conn->passwd,
ppath + sizeof("ftp://") - 1); ppath + sizeof("ftp://") - 1);
else else
result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); result = Curl_add_buffer(&req_buffer, ppath, strlen(ppath));
if(result) if(result)
return result; return result;
result = result =
Curl_add_bufferf(req_buffer, Curl_add_bufferf(&req_buffer,
"%s" /* ftp typecode (;type=x) */ "%s" /* ftp typecode (;type=x) */
" HTTP/%s\r\n" /* HTTP version */ " HTTP/%s\r\n" /* HTTP version */
"%s" /* host */ "%s" /* host */
@ -2518,11 +2526,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
while(co) { while(co) {
if(co->value) { if(co->value) {
if(0 == count) { if(0 == count) {
result = Curl_add_bufferf(req_buffer, "Cookie: "); result = Curl_add_bufferf(&req_buffer, "Cookie: ");
if(result) if(result)
break; break;
} }
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"%s%s=%s", count?"; ":"", "%s%s=%s", count?"; ":"",
co->name, co->value); co->name, co->value);
if(result) if(result)
@ -2535,15 +2543,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
if(addcookies && !result) { if(addcookies && !result) {
if(!count) if(!count)
result = Curl_add_bufferf(req_buffer, "Cookie: "); result = Curl_add_bufferf(&req_buffer, "Cookie: ");
if(!result) { if(!result) {
result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"", result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"",
addcookies); addcookies);
count++; count++;
} }
} }
if(count && !result) if(count && !result)
result = Curl_add_buffer(req_buffer, "\r\n", 2); result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result) if(result)
return result; return result;
@ -2577,7 +2585,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if((postsize != -1) && !data->req.upload_chunky && if((postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */ /* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize); "\r\n", postsize);
if(result) if(result)
@ -2590,7 +2598,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result; return result;
} }
result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */
if(result) if(result)
return result; return result;
@ -2598,7 +2606,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_pgrsSetUploadSize(data, postsize); Curl_pgrsSetUploadSize(data, postsize);
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
result = Curl_add_buffer_send(req_buffer, conn, result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET); &data->info.request_size, 0, FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending PUT request"); failf(data, "Failed sending PUT request");
@ -2616,11 +2624,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* This is form posting using mime data. */ /* This is form posting using mime data. */
if(conn->bits.authneg) { if(conn->bits.authneg) {
/* nothing to post! */ /* nothing to post! */
result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); result = Curl_add_bufferf(&req_buffer, "Content-Length: 0\r\n\r\n");
if(result) if(result)
return result; return result;
result = Curl_add_buffer_send(req_buffer, conn, result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET); &data->info.request_size, 0, FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending POST request"); failf(data, "Failed sending POST request");
@ -2640,7 +2648,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation, /* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */ although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize); "\r\n", postsize);
if(result) if(result)
@ -2652,7 +2660,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
struct curl_slist *hdr; struct curl_slist *hdr;
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) { for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
result = Curl_add_bufferf(req_buffer, "%s\r\n", hdr->data); result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data);
if(result) if(result)
return result; return result;
} }
@ -2676,7 +2684,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->state.expect100header = FALSE; data->state.expect100header = FALSE;
/* make the request end in a true CRLF */ /* make the request end in a true CRLF */
result = Curl_add_buffer(req_buffer, "\r\n", 2); result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result) if(result)
return result; return result;
@ -2689,7 +2697,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->sending = HTTPSEND_BODY; http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
result = Curl_add_buffer_send(req_buffer, conn, result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET); &data->info.request_size, 0, FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending POST request"); failf(data, "Failed sending POST request");
@ -2719,7 +2727,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) { (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation, /* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */ although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize); "\r\n", postsize);
if(result) if(result)
@ -2727,7 +2735,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
if(!Curl_checkheaders(conn, "Content-Type")) { if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Content-Type: application/" "Content-Type: application/"
"x-www-form-urlencoded\r\n"); "x-www-form-urlencoded\r\n");
if(result) if(result)
@ -2765,31 +2773,31 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
is no magic limit but only set to prevent really huge POSTs to is no magic limit but only set to prevent really huge POSTs to
get the data duplicated with malloc() and family. */ get the data duplicated with malloc() and family. */
result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result) if(result)
return result; return result;
if(!data->req.upload_chunky) { if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request /* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */ already now to reduce the number if send() calls */
result = Curl_add_buffer(req_buffer, data->set.postfields, result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize); (size_t)postsize);
included_body = postsize; included_body = postsize;
} }
else { else {
if(postsize) { if(postsize) {
/* Append the POST data chunky-style */ /* Append the POST data chunky-style */
result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize);
if(!result) { if(!result) {
result = Curl_add_buffer(req_buffer, data->set.postfields, result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize); (size_t)postsize);
if(!result) if(!result)
result = Curl_add_buffer(req_buffer, "\r\n", 2); result = Curl_add_buffer(&req_buffer, "\r\n", 2);
included_body = postsize + 2; included_body = postsize + 2;
} }
} }
if(!result) if(!result)
result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5); result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
/* 0 CR LF CR LF */ /* 0 CR LF CR LF */
included_body += 5; included_body += 5;
} }
@ -2811,20 +2819,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* set the upload size to the progress meter */ /* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result) if(result)
return result; return result;
} }
} }
else { else {
result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result) if(result)
return result; return result;
if(data->req.upload_chunky && conn->bits.authneg) { if(data->req.upload_chunky && conn->bits.authneg) {
/* Chunky upload is selected and we're negotiating auth still, send /* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */ end-of-data only */
result = Curl_add_buffer(req_buffer, result = Curl_add_buffer(&req_buffer,
"\x30\x0d\x0a\x0d\x0a", 5); "\x30\x0d\x0a\x0d\x0a", 5);
/* 0 CR LF CR LF */ /* 0 CR LF CR LF */
if(result) if(result)
@ -2845,7 +2853,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
} }
/* issue the request */ /* issue the request */
result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size,
(size_t)included_body, FIRSTSOCKET); (size_t)included_body, FIRSTSOCKET);
if(result) if(result)
@ -2857,12 +2865,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break; break;
default: default:
result = Curl_add_buffer(req_buffer, "\r\n", 2); result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result) if(result)
return result; return result;
/* issue the request */ /* issue the request */
result = Curl_add_buffer_send(req_buffer, conn, result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET); &data->info.request_size, 0, FIRSTSOCKET);
if(result) if(result)

View File

@ -58,10 +58,12 @@ struct Curl_send_buffer {
typedef struct Curl_send_buffer Curl_send_buffer; typedef struct Curl_send_buffer Curl_send_buffer;
Curl_send_buffer *Curl_add_buffer_init(void); Curl_send_buffer *Curl_add_buffer_init(void);
void Curl_add_buffer_free(Curl_send_buffer *buff); void Curl_add_buffer_free(Curl_send_buffer **inp);
CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...); CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size); WARN_UNUSED_RESULT;
CURLcode Curl_add_buffer_send(Curl_send_buffer *in, CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
size_t size) WARN_UNUSED_RESULT;
CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
struct connectdata *conn, struct connectdata *conn,
long *bytes_written, long *bytes_written,
size_t included_body_bytes, size_t included_body_bytes,
@ -154,9 +156,11 @@ struct HTTP {
HTTPSEND_LAST /* never use this */ HTTPSEND_LAST /* never use this */
} sending; } sending;
void *send_buffer; /* used if the request couldn't be sent in one chunk, #ifndef CURL_DISABLE_HTTP
points to an allocated send_buffer struct */ Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in
one chunk, points to an allocated
send_buffer struct */
#endif
#ifdef USE_NGHTTP2 #ifdef USE_NGHTTP2
/*********** for HTTP/2 we store stream-local data here *************/ /*********** for HTTP/2 we store stream-local data here *************/
int32_t stream_id; /* stream we are interested in */ int32_t stream_id; /* stream we are interested in */

View File

@ -141,10 +141,8 @@ static int http2_getsock(struct connectdata *conn,
static void http2_stream_free(struct HTTP *http) static void http2_stream_free(struct HTTP *http)
{ {
if(http) { if(http) {
Curl_add_buffer_free(http->header_recvbuf); Curl_add_buffer_free(&http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */ Curl_add_buffer_free(&http->trailer_recvbuf);
Curl_add_buffer_free(http->trailer_recvbuf);
http->trailer_recvbuf = NULL; /* clear the pointer */
for(; http->push_headers_used > 0; --http->push_headers_used) { for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]); free(http->push_headers[http->push_headers_used - 1]);
} }
@ -630,6 +628,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
int rv; int rv;
size_t left, ncopy; size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id; int32_t stream_id = frame->hd.stream_id;
CURLcode result;
if(!stream_id) { if(!stream_id) {
/* stream ID zero is for connection-oriented stuff */ /* stream ID zero is for connection-oriented stuff */
@ -705,7 +704,9 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = -1; stream->status_code = -1;
} }
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2); result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf; left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
ncopy = CURLMIN(stream->len, left); ncopy = CURLMIN(stream->len, left);
@ -929,6 +930,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
struct Curl_easy *data_s; struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id; int32_t stream_id = frame->hd.stream_id;
struct connectdata *conn = (struct connectdata *)userp; struct connectdata *conn = (struct connectdata *)userp;
CURLcode result;
(void)flags; (void)flags;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
@ -983,11 +985,21 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value)); value));
Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n)); result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
Curl_add_buffer(stream->trailer_recvbuf, name, namelen); if(result)
Curl_add_buffer(stream->trailer_recvbuf, ": ", 2); return NGHTTP2_ERR_CALLBACK_FAILURE;
Curl_add_buffer(stream->trailer_recvbuf, value, valuelen); result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
Curl_add_buffer(stream->trailer_recvbuf, "\r\n\0", 3); if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
return 0; return 0;
} }
@ -1000,10 +1012,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = decode_status_code(value, valuelen); stream->status_code = decode_status_code(value, valuelen);
DEBUGASSERT(stream->status_code != -1); DEBUGASSERT(stream->status_code != -1);
Curl_add_buffer(stream->header_recvbuf, "HTTP/2 ", 7); result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
Curl_add_buffer(stream->header_recvbuf, value, valuelen); if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* the space character after the status code is mandatory */ /* the space character after the status code is mandatory */
Curl_add_buffer(stream->header_recvbuf, " \r\n", 3); result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */ /* if we receive data for another handle, wake that up */
if(conn->data != data_s) if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW); Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
@ -1016,10 +1034,18 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* nghttp2 guarantees that namelen > 0, and :status was already /* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */ received, and this is not pseudo-header field . */
/* convert to a HTTP1-style header */ /* convert to a HTTP1-style header */
Curl_add_buffer(stream->header_recvbuf, name, namelen); result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
Curl_add_buffer(stream->header_recvbuf, ": ", 2); if(result)
Curl_add_buffer(stream->header_recvbuf, value, valuelen); return NGHTTP2_ERR_CALLBACK_FAILURE;
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2); result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */ /* if we receive data for another handle, wake that up */
if(conn->data != data_s) if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW); Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
@ -1123,10 +1149,8 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
drained_transfer(data, httpc); drained_transfer(data, httpc);
if(http->header_recvbuf) { if(http->header_recvbuf) {
Curl_add_buffer_free(http->header_recvbuf); Curl_add_buffer_free(&http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */ Curl_add_buffer_free(&http->trailer_recvbuf);
Curl_add_buffer_free(http->trailer_recvbuf);
http->trailer_recvbuf = NULL; /* clear the pointer */
if(http->push_headers) { if(http->push_headers) {
/* if they weren't used and then freed before */ /* if they weren't used and then freed before */
for(; http->push_headers_used > 0; --http->push_headers_used) { for(; http->push_headers_used > 0; --http->push_headers_used) {
@ -1235,7 +1259,7 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
httpc->local_settings_num); httpc->local_settings_num);
if(!binlen) { if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
Curl_add_buffer_free(req); Curl_add_buffer_free(&req);
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
conn->proto.httpc.binlen = binlen; conn->proto.httpc.binlen = binlen;
@ -1243,11 +1267,11 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen); &base64, &blen);
if(result) { if(result) {
Curl_add_buffer_free(req); Curl_add_buffer_free(&req);
return result; return result;
} }
result = Curl_add_bufferf(req, result = Curl_add_bufferf(&req,
"Connection: Upgrade, HTTP2-Settings\r\n" "Connection: Upgrade, HTTP2-Settings\r\n"
"Upgrade: %s\r\n" "Upgrade: %s\r\n"
"HTTP2-Settings: %s\r\n", "HTTP2-Settings: %s\r\n",
@ -2108,8 +2132,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
result = Curl_http2_init(conn); result = Curl_http2_init(conn);
if(result) { if(result) {
Curl_add_buffer_free(stream->header_recvbuf); Curl_add_buffer_free(&stream->header_recvbuf);
stream->header_recvbuf = NULL;
return result; return result;
} }

View File

@ -222,7 +222,7 @@ static CURLcode CONNECT(struct connectdata *conn,
host_port = aprintf("%s:%d", hostname, remote_port); host_port = aprintf("%s:%d", hostname, remote_port);
if(!host_port) { if(!host_port) {
Curl_add_buffer_free(req_buffer); Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -247,7 +247,7 @@ static CURLcode CONNECT(struct connectdata *conn,
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port); remote_port);
if(!hostheader) { if(!hostheader) {
Curl_add_buffer_free(req_buffer); Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -255,7 +255,7 @@ static CURLcode CONNECT(struct connectdata *conn,
host = aprintf("Host: %s\r\n", hostheader); host = aprintf("Host: %s\r\n", hostheader);
if(!host) { if(!host) {
free(hostheader); free(hostheader);
Curl_add_buffer_free(req_buffer); Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }
@ -267,7 +267,7 @@ static CURLcode CONNECT(struct connectdata *conn,
useragent = conn->allocptr.uagent; useragent = conn->allocptr.uagent;
result = result =
Curl_add_bufferf(req_buffer, Curl_add_bufferf(&req_buffer,
"CONNECT %s HTTP/%s\r\n" "CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */ "%s" /* Host: */
"%s" /* Proxy-Authorization */ "%s" /* Proxy-Authorization */
@ -290,13 +290,13 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!result) if(!result)
/* CRLF terminate the request */ /* CRLF terminate the request */
result = Curl_add_bufferf(req_buffer, "\r\n"); result = Curl_add_bufferf(&req_buffer, "\r\n");
if(!result) { if(!result) {
/* Send the connect request to the proxy */ /* Send the connect request to the proxy */
/* BLOCKING */ /* BLOCKING */
result = result =
Curl_add_buffer_send(req_buffer, conn, Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, sockindex); &data->info.request_size, 0, sockindex);
} }
req_buffer = NULL; req_buffer = NULL;
@ -304,7 +304,7 @@ static CURLcode CONNECT(struct connectdata *conn,
failf(data, "Failed sending CONNECT to proxy"); failf(data, "Failed sending CONNECT to proxy");
} }
Curl_add_buffer_free(req_buffer); Curl_add_buffer_free(&req_buffer);
if(result) if(result)
return result; return result;

View File

@ -462,7 +462,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
result = result =
Curl_add_bufferf(req_buffer, Curl_add_bufferf(&req_buffer,
"%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
"CSeq: %ld\r\n", /* CSeq */ "CSeq: %ld\r\n", /* CSeq */
p_request, p_stream_uri, rtsp->CSeq_sent); p_request, p_stream_uri, rtsp->CSeq_sent);
@ -474,7 +474,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
* to make comparison easier * to make comparison easier
*/ */
if(p_session_id) { if(p_session_id) {
result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id); result = Curl_add_bufferf(&req_buffer, "Session: %s\r\n", p_session_id);
if(result) if(result)
return result; return result;
} }
@ -482,7 +482,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* /*
* Shared HTTP-like options * Shared HTTP-like options
*/ */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"%s" /* transport */ "%s" /* transport */
"%s" /* accept */ "%s" /* accept */
"%s" /* accept-encoding */ "%s" /* accept-encoding */
@ -541,9 +541,10 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* As stated in the http comments, it is probably not wise to /* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */ * actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(conn, "Content-Length")) { if(!Curl_checkheaders(conn, "Content-Length")) {
result = Curl_add_bufferf(req_buffer, result =
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", Curl_add_bufferf(&req_buffer,
(data->set.upload ? putsize : postsize)); "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
if(result) if(result)
return result; return result;
} }
@ -551,8 +552,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER || if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) { rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(conn, "Content-Type")) { if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Content-Type: text/parameters\r\n"); "Content-Type: text/parameters\r\n");
if(result) if(result)
return result; return result;
} }
@ -560,8 +561,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_ANNOUNCE) { if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(conn, "Content-Type")) { if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(&req_buffer,
"Content-Type: application/sdp\r\n"); "Content-Type: application/sdp\r\n");
if(result) if(result)
return result; return result;
} }
@ -579,19 +580,19 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* RTSP never allows chunked transfer */ /* RTSP never allows chunked transfer */
data->req.forbidchunk = TRUE; data->req.forbidchunk = TRUE;
/* Finish the request buffer */ /* Finish the request buffer */
result = Curl_add_buffer(req_buffer, "\r\n", 2); result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result) if(result)
return result; return result;
if(postsize > 0) { if(postsize > 0) {
result = Curl_add_buffer(req_buffer, data->set.postfields, result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize); (size_t)postsize);
if(result) if(result)
return result; return result;
} }
/* issue the request */ /* issue the request */
result = Curl_add_buffer_send(req_buffer, conn, result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET); &data->info.request_size, 0, FIRSTSOCKET);
if(result) { if(result) {
failf(data, "Failed sending RTSP request"); failf(data, "Failed sending RTSP request");