[vlc-commits] decomp: fix heap overflow and cleanup (fixes #12052)

Rémi Denis-Courmont git at videolan.org
Sat Aug 30 15:38:45 CEST 2014


vlc/vlc-2.2 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Aug 30 16:34:39 2014 +0300| [97e514bf7322b6cfa7ab5d7c86badfeb7e4e8e38] | committer: Rémi Denis-Courmont

decomp: fix heap overflow and cleanup (fixes #12052)

(cherry picked from commit aed1b6da46d484f18dbb36dbb5e62c4d4f9ec070)

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=97e514bf7322b6cfa7ab5d7c86badfeb7e4e8e38
---

 modules/stream_filter/decomp.c |   63 ++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 25 deletions(-)

diff --git a/modules/stream_filter/decomp.c b/modules/stream_filter/decomp.c
index fa1013d..2b83310 100644
--- a/modules/stream_filter/decomp.c
+++ b/modules/stream_filter/decomp.c
@@ -183,16 +183,19 @@ static int Peek (stream_t *, const uint8_t **, unsigned int);
  */
 static int Read (stream_t *stream, void *buf, unsigned int buflen)
 {
-    stream_sys_t *p_sys = stream->p_sys;
-    block_t *peeked;
-    ssize_t length;
+    stream_sys_t *sys = stream->p_sys;
+    unsigned ret = 0;
 
     if (buf == NULL) /* caller skips data, get big enough peek buffer */
         buflen = Peek (stream, &(const uint8_t *){ NULL }, buflen);
 
-    if ((peeked = p_sys->peeked) != NULL)
+    block_t *peeked = sys->peeked;
+    if (peeked != NULL)
     {   /* dequeue peeked data */
-        length = (buflen > peeked->i_buffer) ? peeked->i_buffer : buflen;
+        size_t length = peeked->i_buffer;
+        if (length > buflen)
+            length = buflen;
+
         if (buf != NULL)
         {
             memcpy (buf, peeked->p_buffer, length);
@@ -201,24 +204,25 @@ static int Read (stream_t *stream, void *buf, unsigned int buflen)
         buflen -= length;
         peeked->p_buffer += length;
         peeked->i_buffer -= length;
+
         if (peeked->i_buffer == 0)
         {
             block_Release (peeked);
-            p_sys->peeked = NULL;
+            sys->peeked = NULL;
         }
-        p_sys->offset += length;
 
-        if (buflen > 0)
-            length += Read (stream, ((char *)buf) + length, buflen - length);
-        return length;
+        sys->offset += length;
+        ret += length;
     }
     assert ((buf != NULL) || (buflen == 0));
 
-    length = net_Read (stream, p_sys->read_fd, NULL, buf, buflen, false);
-    if (length < 0)
-        return 0;
-    p_sys->offset += length;
-    return length;
+    ssize_t val = net_Read (stream, sys->read_fd, NULL, buf, buflen, false);
+    if (val > 0)
+    {
+        sys->offset += val;
+        ret += val;
+    }
+    return ret;
 }
 
 /**
@@ -226,23 +230,32 @@ static int Read (stream_t *stream, void *buf, unsigned int buflen)
  */
 static int Peek (stream_t *stream, const uint8_t **pbuf, unsigned int len)
 {
-    stream_sys_t *p_sys = stream->p_sys;
-    block_t *peeked = p_sys->peeked;
-    size_t curlen = 0;
-    int fd = p_sys->read_fd;
+    stream_sys_t *sys = stream->p_sys;
+    block_t *peeked = sys->peeked;
+    size_t curlen;
 
-    if (peeked == NULL)
+    if (peeked != NULL)
+    {
+        curlen = peeked->i_buffer;
+        if (curlen < len)
+           peeked = block_Realloc (peeked, 0, len);
+    }
+    else
+    {
+        curlen = 0;
         peeked = block_Alloc (len);
-    else if ((curlen = peeked->i_buffer) < len)
-        peeked = block_Realloc (peeked, 0, len);
+    }
 
-    if ((p_sys->peeked = peeked) == NULL)
+    sys->peeked = peeked;
+    if (unlikely(peeked == NULL))
         return 0;
 
     while (curlen < len)
     {
-        ssize_t val = net_Read (stream, fd, NULL, peeked->p_buffer + curlen,
-                                len - curlen, false);
+        ssize_t val;
+
+        val = net_Read (stream, sys->read_fd, NULL,
+                        peeked->p_buffer + curlen, len - curlen, false);
         if (val <= 0)
             break;
         curlen += val;



More information about the vlc-commits mailing list