[FFmpeg-soc] [soc]: r4767 - in rtmp: rtmppkt.c rtmppkt.h rtmpproto.c

kostya subversion at mplayerhq.hu
Wed Jul 22 09:06:26 CEST 2009


Author: kostya
Date: Wed Jul 22 09:06:25 2009
New Revision: 4767

Log:
When working with AMF data, don't forget about buffer boundaries

Modified:
   rtmp/rtmppkt.c
   rtmp/rtmppkt.h
   rtmp/rtmpproto.c

Modified: rtmp/rtmppkt.c
==============================================================================
--- rtmp/rtmppkt.c	Wed Jul 22 08:54:22 2009	(r4766)
+++ rtmp/rtmppkt.c	Wed Jul 22 09:06:25 2009	(r4767)
@@ -187,10 +187,12 @@ void ff_rtmp_packet_destroy(RTMPPacket *
     pkt->data_size = 0;
 }
 
-int ff_amf_skip_data(const uint8_t *data)
+int ff_amf_skip_data(const uint8_t *data, const uint8_t *data_end)
 {
     const uint8_t *base = data;
 
+    if (data >= data_end)
+        return -1;
     switch (*data++) {
     case AMF_DATA_TYPE_NUMBER:      return 9;
     case AMF_DATA_TYPE_BOOL:        return 2;
@@ -202,12 +204,18 @@ int ff_amf_skip_data(const uint8_t *data
     case AMF_DATA_TYPE_OBJECT:
         for (;;) {
             int size = bytestream_get_be16(&data);
+            int t;
             if (!size) {
                 data++;
                 break;
             }
             data += size;
-            data += ff_amf_skip_data(data);
+            if (data >= data_end)
+                return -1;
+            t = ff_amf_skip_data(data, data_end);
+            if (t < 0 || data + t >= data_end)
+                return -1;
+            data += t;
         }
         return data - base;
     case AMF_DATA_TYPE_OBJECT_END:  return 1;
@@ -215,12 +223,14 @@ int ff_amf_skip_data(const uint8_t *data
     }
 }
 
-int ff_amf_find_field(const uint8_t *data, const uint8_t *name,
+int ff_amf_find_field(const uint8_t *data, const uint8_t *data_end, const uint8_t *name,
                       uint8_t *dst, int dst_size)
 {
     int namelen = strlen(name);
     int len;
 
+    if (data >= data_end - 3)
+        return -1;
     if (*data++ != AMF_DATA_TYPE_OBJECT)
         return -1;
     for (;;) {
@@ -228,6 +238,8 @@ int ff_amf_find_field(const uint8_t *dat
         if (!size)
             break;
         data += size;
+        if (data >= data_end)
+            return -1;
         if (size == namelen && !memcmp(data-size, name, namelen)) {
             switch (*data++) {
             case AMF_DATA_TYPE_NUMBER:
@@ -244,8 +256,8 @@ int ff_amf_find_field(const uint8_t *dat
                 return -1;
             }
         }
-        len = ff_amf_skip_data(data);
-        if (len < 0)
+        len = ff_amf_skip_data(data, data_end);
+        if (len < 0 || data + len >= data_end)
             return -1;
         data += len;
     }

Modified: rtmp/rtmppkt.h
==============================================================================
--- rtmp/rtmppkt.h	Wed Jul 22 08:54:22 2009	(r4766)
+++ rtmp/rtmppkt.h	Wed Jul 22 09:06:25 2009	(r4767)
@@ -136,20 +136,22 @@ int ff_rtmp_packet_write(URLContext *h, 
  * Calculates number of bytes needed to skip first AMF entry in data.
  *
  * @param data input data
+ * @param data_end input buffer end
  * @return number of bytes used by first AMF entry
  */
-int ff_amf_skip_data(const uint8_t *data);
+int ff_amf_skip_data(const uint8_t *data, const uint8_t *data_end);
 
 /**
  * Retrieves value of given AMF object field in string form.
  *
  * @param data     AMF object data
+ * @param data_end input buffer end
  * @param name     name of field to retrieve
  * @param dst      buffer for storing result
  * @param dst_size output buffer size
  * @return 0 if search and retrieval succeeded, negative value otherwise
  */
-int ff_amf_find_field(const uint8_t *data, const uint8_t *name,
+int ff_amf_find_field(const uint8_t *data, const uint8_t *data_end, const uint8_t *name,
                       uint8_t *dst, int dst_size);
 
 /**

Modified: rtmp/rtmpproto.c
==============================================================================
--- rtmp/rtmpproto.c	Wed Jul 22 08:54:22 2009	(r4766)
+++ rtmp/rtmpproto.c	Wed Jul 22 09:06:25 2009	(r4767)
@@ -402,7 +402,7 @@ static int rtmp_parse_result(URLContext 
         if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
             uint8_t tmpstr[256];
 
-            if (!ff_amf_find_field(pkt->data + 9, "description", tmpstr, sizeof(tmpstr)))
+            if (!ff_amf_find_field(pkt->data + 9, pkt->data + pkt->data_size, "description", tmpstr, sizeof(tmpstr)))
                 av_log(NULL/*s*/, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
             return -1;
         }
@@ -430,18 +430,18 @@ static int rtmp_parse_result(URLContext 
             int t;
 
             for (i = 0; i < 2; i++) {
-                t = ff_amf_skip_data(ptr);
+                t = ff_amf_skip_data(ptr, pkt->data + pkt->data_size);
                 if (t < 0)
                     return 1;
                 ptr += t;
             }
-            t = ff_amf_find_field(ptr, "level", tmpstr, sizeof(tmpstr));
+            t = ff_amf_find_field(ptr, pkt->data + pkt->data_size, "level", tmpstr, sizeof(tmpstr));
             if (!t && !strcmp(tmpstr, "error")) {
-                if (!ff_amf_find_field(ptr, "description", tmpstr, sizeof(tmpstr)))
+                if (!ff_amf_find_field(ptr, pkt->data + pkt->data_size, "description", tmpstr, sizeof(tmpstr)))
                     av_log(NULL/*s*/, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
                 return -1;
             }
-            t = ff_amf_find_field(ptr, "code", tmpstr, sizeof(tmpstr));
+            t = ff_amf_find_field(ptr, pkt->data + pkt->data_size, "code", tmpstr, sizeof(tmpstr));
             if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) {
                 rt->state = STATE_PLAYING;
                 return 0;


More information about the FFmpeg-soc mailing list