]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ws: fix buffer pointer use in the callback loop
authorDaniel Stenberg <daniel@haxx.se>
Sun, 9 Oct 2022 21:35:21 +0000 (23:35 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 10 Oct 2022 09:21:56 +0000 (11:21 +0200)
Closes #9678

lib/ws.c

index cfd267ee208d5154989de67d78293bffcc365d96..a673446625c17af912dbf8a87f6eb159a1af0f8a 100644 (file)
--- a/lib/ws.c
+++ b/lib/ws.c
@@ -189,8 +189,7 @@ static void ws_decode_clear(struct Curl_easy *data)
    out - stored pointed to extracted data
    olen - stored length of the extracted data
    oleft - number of unread bytes pending to that belongs to this frame
-   endp - stored pointer to data immediately following the parsed data, if
-          there is more data in there. NULL if there's no more data.
+   more - if there is more data in there
    flags - stored bitmask about the frame
 
    Returns CURLE_AGAIN if there is only a partial frame in the buffer. Then it
@@ -202,7 +201,7 @@ static CURLcode ws_decode(struct Curl_easy *data,
                           unsigned char *wpkt, size_t ilen,
                           unsigned char **out, size_t *olen,
                           curl_off_t *oleft,
-                          unsigned char **endp,
+                          bool *more,
                           unsigned int *flags)
 {
   bool fin;
@@ -304,16 +303,21 @@ static CURLcode ws_decode(struct Curl_easy *data,
     *oleft = total - dataindex;
     payloadsize = total - dataindex;
   }
-  else
+  else {
     *oleft = 0;
+    if(plen > total)
+      /* there is another fragment after */
+      *more = TRUE;
+  }
 
   /* point to the payload */
   *out = &p[dataindex];
 
   /* return the payload length */
   *olen = payloadsize;
-  wsp->usedbuf = total; /* number of bytes "used" from the buffer */
-  *endp = &p[total];
+
+  /* number of bytes "used" from the buffer */
+  wsp->usedbuf = dataindex + payloadsize;
   infof(data, "WS: received %zu bytes payload (%zu left)",
         payloadsize, *oleft);
   return CURLE_OK;
@@ -336,16 +340,16 @@ size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
     size_t flen = 0;
     size_t wrote = 0;
     CURLcode result;
-    unsigned char *endp;
+    bool more; /* there's is more to parse in the buffer */
     curl_off_t oleft;
 
     decode:
-
+    more = FALSE;
     oleft = ws->ws.frame.bytesleft;
     if(!oleft) {
       unsigned int recvflags;
       result = ws_decode(data, (unsigned char *)buffer, nitems,
-                         &frame, &flen, &oleft, &endp, &recvflags);
+                         &frame, &flen, &oleft, &more, &recvflags);
       if(result == CURLE_AGAIN)
         /* insufficient amount of data, keep it for later */
         return nitems;
@@ -363,10 +367,10 @@ size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
     else {
       if(nitems > (size_t)ws->ws.frame.bytesleft) {
         nitems = ws->ws.frame.bytesleft;
-        endp = (unsigned char *)&buffer[nitems];
+        more = TRUE;
       }
       else
-        endp = NULL;
+        more = FALSE;
       ws->ws.frame.offset += nitems;
       ws->ws.frame.bytesleft -= nitems;
       frame = (unsigned char *)buffer;
@@ -394,9 +398,9 @@ size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
       ws->ws.frame.offset += flen;
     /* the websocket frame has been delivered */
     ws_decode_clear(data);
-    if(endp) {
+    if(more) {
       /* there's more websocket data to deal with in the buffer */
-      buffer = NULL; /* don't pass in the data again */
+      buffer = NULL; /* the buffer as been drained already */
       goto decode;
     }
   }
@@ -437,14 +441,14 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
     if(bytes) {
       unsigned char *out;
       size_t olen;
-      unsigned char *endp;
+      bool more;
       unsigned int recvflags;
       curl_off_t oleft = wsp->frame.bytesleft;
 
       infof(data, "WS: got %u websocket bytes to decode", (int)bytes);
       if(!oleft && !drain) {
         result = ws_decode(data, (unsigned char *)inbuf, bytes,
-                           &out, &olen, &oleft, &endp, &recvflags);
+                           &out, &olen, &oleft, &more, &recvflags);
         if(result == CURLE_AGAIN)
           /* a packet fragment only */
           break;