avformat/rtmppkt: Convert ff_amf_get_field_value() to bytestream2

Fixes: out of array accesses

Found-by: JunDong Xie of Ant-financial Light-Year Security Lab
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Michael Niedermayer 2017-07-28 14:37:26 +02:00
parent 08c073434e
commit ffcc82219c
1 changed files with 37 additions and 20 deletions

View File

@ -505,53 +505,70 @@ int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
return bytestream2_tell(&gb); return bytestream2_tell(&gb);
} }
int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, static int amf_get_field_value2(GetByteContext *gb,
const uint8_t *name, uint8_t *dst, int dst_size) const uint8_t *name, uint8_t *dst, int dst_size)
{ {
int namelen = strlen(name); int namelen = strlen(name);
int len; int len;
while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) { while (bytestream2_peek_byte(gb) != AMF_DATA_TYPE_OBJECT && bytestream2_get_bytes_left(gb) > 0) {
len = ff_amf_tag_size(data, data_end); int ret = amf_tag_skip(gb);
if (len < 0) if (ret < 0)
len = data_end - data; return -1;
data += len;
} }
if (data_end - data < 3) if (bytestream2_get_bytes_left(gb) < 3)
return -1; return -1;
data++; bytestream2_get_byte(gb);
for (;;) { for (;;) {
int size = bytestream_get_be16(&data); int size = bytestream2_get_be16(gb);
if (!size) if (!size)
break; break;
if (size < 0 || size >= data_end - data) if (size < 0 || size >= bytestream2_get_bytes_left(gb))
return -1; return -1;
data += size; bytestream2_skip(gb, size);
if (size == namelen && !memcmp(data-size, name, namelen)) { if (size == namelen && !memcmp(gb->buffer-size, name, namelen)) {
switch (*data++) { switch (bytestream2_get_byte(gb)) {
case AMF_DATA_TYPE_NUMBER: case AMF_DATA_TYPE_NUMBER:
snprintf(dst, dst_size, "%g", av_int2double(AV_RB64(data))); snprintf(dst, dst_size, "%g", av_int2double(bytestream2_get_be64(gb)));
break; break;
case AMF_DATA_TYPE_BOOL: case AMF_DATA_TYPE_BOOL:
snprintf(dst, dst_size, "%s", *data ? "true" : "false"); snprintf(dst, dst_size, "%s", bytestream2_get_byte(gb) ? "true" : "false");
break; break;
case AMF_DATA_TYPE_STRING: case AMF_DATA_TYPE_STRING:
len = bytestream_get_be16(&data); len = bytestream2_get_be16(gb);
av_strlcpy(dst, data, FFMIN(len+1, dst_size)); if (dst_size < 1)
return -1;
if (dst_size < len + 1)
len = dst_size - 1;
bytestream2_get_buffer(gb, dst, len);
dst[len] = 0;
break; break;
default: default:
return -1; return -1;
} }
return 0; return 0;
} }
len = ff_amf_tag_size(data, data_end); len = amf_tag_skip(gb);
if (len < 0 || len >= data_end - data) if (len < 0 || bytestream2_get_bytes_left(gb) <= 0)
return -1; return -1;
data += len;
} }
return -1; return -1;
} }
int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
const uint8_t *name, uint8_t *dst, int dst_size)
{
GetByteContext gb;
if (data >= data_end)
return -1;
bytestream2_init(&gb, data, data_end - data);
return amf_get_field_value2(&gb, name, dst, dst_size);
}
static const char* rtmp_packet_type(int type) static const char* rtmp_packet_type(int type)
{ {
switch (type) { switch (type) {