Browse code

Merge commit 'e930b112d14d7acd050d5087d11b6dd4c56a8e4e' into release/0.10

* commit 'e930b112d14d7acd050d5087d11b6dd4c56a8e4e':
oma: refactor seek function
8bps: Bound-check the input buffer
rtmp: Do not misuse memcmp

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2013/11/05 02:04:22
Showing 5 changed files
... ...
@@ -69,7 +69,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
69 69
         unsigned char *pixptr, *pixptr_end;
70 70
         unsigned int height = avctx->height; // Real image height
71 71
         unsigned int dlen, p, row;
72
-        const unsigned char *lp, *dp;
72
+        const unsigned char *lp, *dp, *ep;
73 73
         unsigned char count;
74 74
         unsigned int planes = c->planes;
75 75
         unsigned char *planemap = c->planemap;
... ...
@@ -84,6 +84,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
84 84
                 return -1;
85 85
         }
86 86
 
87
+        ep = encoded + buf_size;
88
+
87 89
         /* Set data pointer after line lengths */
88 90
         dp = encoded + planes * (height << 1);
89 91
 
... ...
@@ -95,16 +97,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
95 95
                 for(row = 0; row < height; row++) {
96 96
                         pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
97 97
                         pixptr_end = pixptr + c->pic.linesize[0];
98
+                        if (ep - lp < row * 2 + 2)
99
+                            return AVERROR_INVALIDDATA;
98 100
                         dlen = av_be2ne16(*(const unsigned short *)(lp+row*2));
99 101
                         /* Decode a row of this plane */
100 102
                         while(dlen > 0) {
101
-                                if(dp + 1 >= buf+buf_size) return -1;
103
+                                if(ep - dp <= 1) return -1;
102 104
                                 if ((count = *dp++) <= 127) {
103 105
                                         count++;
104 106
                                         dlen -= count + 1;
105 107
                                         if (pixptr + count * planes > pixptr_end)
106 108
                                             break;
107
-                                        if(dp + count > buf+buf_size) return -1;
109
+                                        if(ep - dp < count) return -1;
108 110
                                         while(count--) {
109 111
                                                 *pixptr = *dp++;
110 112
                                                 pixptr += planes;
... ...
@@ -425,22 +425,26 @@ static int oma_read_seek(struct AVFormatContext *s, int stream_index, int64_t ti
425 425
 {
426 426
     OMAContext *oc = s->priv_data;
427 427
 
428
-    pcm_read_seek(s, stream_index, timestamp, flags);
429
-
430
-    if (oc->encrypted) {
431
-        /* readjust IV for CBC */
432
-        int64_t pos = avio_tell(s->pb);
433
-        if (pos < oc->content_start)
434
-            memset(oc->iv, 0, 8);
435
-        else {
436
-            if (avio_seek(s->pb, -8, SEEK_CUR) < 0 || avio_read(s->pb, oc->iv, 8) < 8) {
437
-                memset(oc->iv, 0, 8);
438
-                return -1;
439
-            }
440
-        }
428
+    int err = pcm_read_seek(s, stream_index, timestamp, flags);
429
+
430
+    if (!oc->encrypted)
431
+        return err;
432
+
433
+    /* readjust IV for CBC */
434
+    if (err || avio_tell(s->pb) < oc->content_start)
435
+        goto wipe;
436
+    if ((err = avio_seek(s->pb, -8, SEEK_CUR)) < 0)
437
+        goto wipe;
438
+    if ((err = avio_read(s->pb, oc->iv, 8)) < 8) {
439
+        if (err >= 0)
440
+            err = AVERROR_EOF;
441
+        goto wipe;
441 442
     }
442 443
 
443 444
     return 0;
445
+wipe:
446
+    memset(oc->iv, 0, 8);
447
+    return err;
444 448
 }
445 449
 
446 450
 AVInputFormat ff_oma_demuxer = {
... ...
@@ -447,3 +447,36 @@ void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p)
447 447
         av_log(ctx, AV_LOG_DEBUG, "\n");
448 448
     }
449 449
 }
450
+
451
+int ff_amf_match_string(const uint8_t *data, int size, const char *str)
452
+{
453
+    int len = strlen(str);
454
+    int amf_len, type;
455
+
456
+    if (size < 1)
457
+        return 0;
458
+
459
+    type = *data++;
460
+
461
+    if (type != AMF_DATA_TYPE_LONG_STRING &&
462
+        type != AMF_DATA_TYPE_STRING)
463
+        return 0;
464
+
465
+    if (type == AMF_DATA_TYPE_LONG_STRING) {
466
+        if ((size -= 4 + 1) < 0)
467
+            return 0;
468
+        amf_len = bytestream_get_be32(&data);
469
+    } else {
470
+        if ((size -= 2 + 1) < 0)
471
+            return 0;
472
+        amf_len = bytestream_get_be16(&data);
473
+    }
474
+
475
+    if (amf_len > size)
476
+        return 0;
477
+
478
+    if (amf_len != len)
479
+        return 0;
480
+
481
+    return !memcmp(data, str, len);
482
+}
... ...
@@ -218,6 +218,13 @@ void ff_amf_write_field_name(uint8_t **dst, const char *str);
218 218
  */
219 219
 void ff_amf_write_object_end(uint8_t **dst);
220 220
 
221
+/**
222
+ * Match AMF string with a NULL-terminated string.
223
+ *
224
+ * @return 0 if the strings do not match.
225
+ */
226
+int ff_amf_match_string(const uint8_t *data, int size, const char *str);
227
+
221 228
 /** @} */ // AMF funcs
222 229
 
223 230
 #endif /* AVFORMAT_RTMPPKT_H */
... ...
@@ -588,14 +588,14 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
588 588
         break;
589 589
     case RTMP_PT_INVOKE:
590 590
         //TODO: check for the messages sent for wrong state?
591
-        if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
591
+        if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
592 592
             uint8_t tmpstr[256];
593 593
 
594 594
             if (!ff_amf_get_field_value(pkt->data + 9, data_end,
595 595
                                         "description", tmpstr, sizeof(tmpstr)))
596 596
                 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
597 597
             return -1;
598
-        } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
598
+        } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
599 599
             switch (rt->state) {
600 600
             case STATE_HANDSHAKED:
601 601
                 if (!rt->is_input) {
... ...
@@ -636,7 +636,7 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
636 636
                 rt->state = STATE_READY;
637 637
                 break;
638 638
             }
639
-        } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
639
+        } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
640 640
             const uint8_t* ptr = pkt->data + 11;
641 641
             uint8_t tmpstr[256];
642 642
 
... ...
@@ -724,7 +724,8 @@ static int get_packet(URLContext *s, int for_header)
724 724
             continue;
725 725
         }
726 726
         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
727
-           (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
727
+           (rpkt.type == RTMP_PT_NOTIFY &&
728
+            ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
728 729
             ts = rpkt.timestamp;
729 730
 
730 731
             // generate packet header and put data into buffer for FLV demuxer