* commit 'e930b112d14d7acd050d5087d11b6dd4c56a8e4e':
oma: refactor seek function
8bps: Bound-check the input buffer
rtmp: Do not misuse memcmp
Merged-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -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 |