[vlc-commits] sap: use vlc_memstream, fix heap overflow

Rémi Denis-Courmont git at videolan.org
Mon May 29 17:40:33 CEST 2017


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon May 29 18:36:54 2017 +0300| [94ab32470fff2642269ec706a8ea42dc0d5965c1] | committer: Rémi Denis-Courmont

sap: use vlc_memstream, fix heap overflow

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=94ab32470fff2642269ec706a8ea42dc0d5965c1
---

 src/stream_output/sap.c | 78 +++++++++++++++++++++++--------------------------
 1 file changed, 36 insertions(+), 42 deletions(-)

diff --git a/src/stream_output/sap.c b/src/stream_output/sap.c
index 6bac144a27..ee5312eb7d 100644
--- a/src/stream_output/sap.c
+++ b/src/stream_output/sap.c
@@ -36,6 +36,7 @@
 
 #include <vlc_sout.h>
 #include <vlc_network.h>
+#include <vlc_memstream.h>
 
 #include "stream_output.h"
 #include "libvlc.h"
@@ -47,8 +48,8 @@
 struct session_descriptor_t
 {
     struct session_descriptor_t *next;
-    size_t  length;
-    uint8_t data[];
+    size_t length;
+    char *data;
 };
 
 /* A SAP announce address. For each of these, we run the
@@ -298,43 +299,26 @@ sout_AnnounceRegisterSDP (vlc_object_t *obj, const char *sdp,
     vlc_mutex_lock (&sap_addr->lock);
     vlc_mutex_unlock (&sap_mutex);
 
-    size_t length = 20;
-    switch (sap_addr->orig.ss_family)
-    {
-#ifdef AF_INET6
-        case AF_INET6:
-            length += 16;
-            break;
-#endif
-        case AF_INET:
-            length += 4;
-            break;
-        default:
-            vlc_assert_unreachable ();
-    }
-
-    /* XXX: Check for dupes */
-    length += strlen (sdp);
-
-    session_descriptor_t *session = malloc (sizeof (*session) + length);
+    session_descriptor_t *session = malloc(sizeof (*session));
     if (unlikely(session == NULL))
-    {
-        vlc_mutex_unlock (&sap_addr->lock);
-        return NULL; /* NOTE: we should destroy the thread if left unused */
-    }
+        goto out; /* NOTE: we should destroy the thread if left unused */
+
     session->next = sap_addr->first;
-    sap_addr->first = session;
-    session->length = length;
 
     /* Build the SAP Headers */
-    uint8_t *buf = session->data;
+    struct vlc_memstream stream;
+    vlc_memstream_open(&stream);
 
     /* SAPv1, not encrypted, not compressed */
-    buf[0] = 0x20;
-    buf[1] = 0x00; /* No authentication length */
-    SetWBE(buf + 2, mdate()); /* ID hash */
+    uint8_t flags = 0x20;
+#ifdef AF_INET6
+    if (sap_addr->orig.ss_family == AF_INET6)
+        flags |= 0x10;
+#endif
+    vlc_memstream_putc(&stream, flags);
+    vlc_memstream_putc(&stream, 0x00); /* No authentication length */
+    vlc_memstream_write(&stream, &(uint16_t){ mdate() }, 2); /* ID hash */
 
-    size_t offset = 4;
     switch (sap_addr->orig.ss_family)
     {
 #ifdef AF_INET6
@@ -342,9 +326,7 @@ sout_AnnounceRegisterSDP (vlc_object_t *obj, const char *sdp,
         {
             const struct in6_addr *a6 =
                 &((const struct sockaddr_in6 *)&sap_addr->orig)->sin6_addr;
-            memcpy (buf + offset, a6, 16);
-            buf[0] |= 0x10; /* IPv6 flag */
-            offset += 16;
+            vlc_memstream_write(&stream, &a6, 16);
             break;
         }
 #endif
@@ -352,21 +334,32 @@ sout_AnnounceRegisterSDP (vlc_object_t *obj, const char *sdp,
         {
             const struct in_addr *a4 =
                 &((const struct sockaddr_in *)&sap_addr->orig)->sin_addr;
-            memcpy (buf + offset, a4, 4);
-            offset += 4;
+            vlc_memstream_write(&stream, &a4, 4);
             break;
         }
-
+        default:
+            vlc_assert_unreachable ();
     }
 
-    memcpy (buf + offset, "application/sdp", 16);
-    offset += 16;
+    vlc_memstream_puts(&stream, "application/sdp");
+    vlc_memstream_putc(&stream, '\0');
 
     /* Build the final message */
-    strcpy((char *)buf + offset, sdp);
+    vlc_memstream_puts(&stream, sdp);
+
+    if (vlc_memstream_close(&stream))
+    {
+        free(session);
+        session = NULL;
+        goto out;
+    }
 
+    session->data = stream.ptr;
+    session->length = stream.length;
+    sap_addr->first = session;
     sap_addr->session_count++;
     vlc_cond_signal (&sap_addr->wait);
+out:
     vlc_mutex_unlock (&sap_addr->lock);
     return session;
 }
@@ -424,5 +417,6 @@ found:
         vlc_mutex_unlock (&addr->lock);
     }
 
-    free (session);
+    free(session->data);
+    free(session);
 }



More information about the vlc-commits mailing list