From: Daniel Stenberg Date: Mon, 24 Mar 2025 10:46:34 +0000 (+0100) Subject: mqtt: convert sendleftovers to dynbuf X-Git-Tag: curl-8_13_0~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2078c0e1c756b75b1e13b42800acf0c7ef5290b;p=thirdparty%2Fcurl.git mqtt: convert sendleftovers to dynbuf Avoid frequent strdups/free calls, including the double-free risk. Reported-by: Ronald Crane Closes #16823 --- diff --git a/lib/dynbuf.h b/lib/dynbuf.h index 71b0cc239d..cc7e5a12ed 100644 --- a/lib/dynbuf.h +++ b/lib/dynbuf.h @@ -97,5 +97,6 @@ char *Curl_dyn_take(struct dynbuf *s, size_t *plen); #define DYN_PINGPPONG_CMD (64*1024) #define DYN_IMAP_CMD (64*1024) #define DYN_MQTT_RECV (64*1024) +#define DYN_MQTT_SEND 0xFFFFFFF #define DYN_CRLFILE_SIZE (400*1024*1024) /* 400mb */ #endif diff --git a/lib/mqtt.c b/lib/mqtt.c index 69bbf658f8..287037d483 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -112,6 +112,7 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data, if(!mq) return CURLE_OUT_OF_MEMORY; Curl_dyn_init(&mq->recvbuf, DYN_MQTT_RECV); + Curl_dyn_init(&mq->sendbuf, DYN_MQTT_SEND); data->req.p.mqtt = mq; return CURLE_OK; } @@ -119,25 +120,24 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data, static CURLcode mqtt_send(struct Curl_easy *data, const char *buf, size_t len) { - CURLcode result = CURLE_OK; struct MQTT *mq = data->req.p.mqtt; size_t n; - result = Curl_xfer_send(data, buf, len, FALSE, &n); + CURLcode result = Curl_xfer_send(data, buf, len, FALSE, &n); if(result) return result; Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n); if(len != n) { size_t nsend = len - n; - char *sendleftovers = Curl_memdup(&buf[n], nsend); - if(!sendleftovers) - return CURLE_OUT_OF_MEMORY; - mq->sendleftovers = sendleftovers; - mq->nsend = nsend; - } - else { - mq->sendleftovers = NULL; - mq->nsend = 0; + if(Curl_dyn_len(&mq->sendbuf)) { + DEBUGASSERT(Curl_dyn_len(&mq->sendbuf) >= nsend); + result = Curl_dyn_tail(&mq->sendbuf, nsend); /* keep this much */ + } + else { + result = Curl_dyn_addn(&mq->sendbuf, &buf[n], nsend); + } } + else + Curl_dyn_reset(&mq->sendbuf); return result; } @@ -352,7 +352,7 @@ static CURLcode mqtt_disconnect(struct Curl_easy *data) CURLcode result = CURLE_OK; struct MQTT *mq = data->req.p.mqtt; result = mqtt_send(data, "\xe0\x00", 2); - Curl_safefree(mq->sendleftovers); + Curl_dyn_free(&mq->sendbuf); Curl_dyn_free(&mq->recvbuf); return result; } @@ -732,7 +732,7 @@ static CURLcode mqtt_done(struct Curl_easy *data, struct MQTT *mq = data->req.p.mqtt; (void)status; (void)premature; - Curl_safefree(mq->sendleftovers); + Curl_dyn_free(&mq->sendbuf); Curl_dyn_free(&mq->recvbuf); return CURLE_OK; } @@ -740,19 +740,17 @@ static CURLcode mqtt_done(struct Curl_easy *data, static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - struct connectdata *conn = data->conn; - struct mqtt_conn *mqtt = &conn->proto.mqtt; + struct mqtt_conn *mqtt = &data->conn->proto.mqtt; struct MQTT *mq = data->req.p.mqtt; ssize_t nread; unsigned char recvbyte; *done = FALSE; - if(mq->nsend) { + if(Curl_dyn_len(&mq->sendbuf)) { /* send the remainder of an outgoing packet */ - char *ptr = mq->sendleftovers; - result = mqtt_send(data, mq->sendleftovers, mq->nsend); - free(ptr); + result = mqtt_send(data, Curl_dyn_ptr(&mq->sendbuf), + Curl_dyn_len(&mq->sendbuf)); if(result) return result; } diff --git a/lib/mqtt.h b/lib/mqtt.h index 99ab12a98a..b181e3c16d 100644 --- a/lib/mqtt.h +++ b/lib/mqtt.h @@ -49,15 +49,13 @@ struct mqtt_conn { /* protocol-specific transfer-related data */ struct MQTT { - char *sendleftovers; - size_t nsend; /* size of sendleftovers */ - + struct dynbuf sendbuf; /* when receiving */ + struct dynbuf recvbuf; size_t npacket; /* byte counter */ - unsigned char firstbyte; size_t remaining_length; - struct dynbuf recvbuf; unsigned char pkt_hd[4]; /* for decoding the arriving packet length */ + unsigned char firstbyte; }; #endif /* HEADER_CURL_MQTT_H */