mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Fix mp4 security issue, check buffer when required size is variable.
This commit is contained in:
parent
9140e0f19d
commit
b63f2f283d
3 changed files with 48 additions and 29 deletions
|
@ -146,6 +146,7 @@ For previous versions, please read:
|
||||||
|
|
||||||
## V3 changes
|
## V3 changes
|
||||||
|
|
||||||
|
* v3.0, 2019-12-30, Fix mp4 security issue, check buffer when required size is variable.
|
||||||
* <strong>v3.0, 2019-12-29, [3.0 alpha7(3.0.90)][r3.0a7] released. 116356 lines.</strong>
|
* <strong>v3.0, 2019-12-29, [3.0 alpha7(3.0.90)][r3.0a7] released. 116356 lines.</strong>
|
||||||
* v3.0, 2019-12-29, For [#1255][bug #1255], support vhost/domain in query string for HTTP streaming. 3.0.90
|
* v3.0, 2019-12-29, For [#1255][bug #1255], support vhost/domain in query string for HTTP streaming. 3.0.90
|
||||||
* v3.0, 2019-12-29, For [#299][bug #299], increase dash segment size for avsync issue. 3.0.89
|
* v3.0, 2019-12-29, For [#299][bug #299], increase dash segment size for avsync issue. 3.0.89
|
||||||
|
|
|
@ -1061,7 +1061,7 @@ SrsMp4TrunEntry::~SrsMp4TrunEntry()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsMp4TrunEntry::nb_header()
|
int SrsMp4TrunEntry::nb_bytes()
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
|
@ -1081,7 +1081,7 @@ int SrsMp4TrunEntry::nb_header()
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsMp4TrunEntry::encode_header(SrsBuffer* buf)
|
srs_error_t SrsMp4TrunEntry::encode(SrsBuffer* buf)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -1107,7 +1107,7 @@ srs_error_t SrsMp4TrunEntry::encode_header(SrsBuffer* buf)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsMp4TrunEntry::decode_header(SrsBuffer* buf)
|
srs_error_t SrsMp4TrunEntry::decode(SrsBuffer* buf)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -1133,7 +1133,7 @@ srs_error_t SrsMp4TrunEntry::decode_header(SrsBuffer* buf)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringstream& SrsMp4TrunEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc)
|
stringstream& SrsMp4TrunEntry::dumps(stringstream& ss, SrsMp4DumpContext dc)
|
||||||
{
|
{
|
||||||
if ((owner->flags&SrsMp4TrunFlagsSampleDuration) == SrsMp4TrunFlagsSampleDuration) {
|
if ((owner->flags&SrsMp4TrunFlagsSampleDuration) == SrsMp4TrunFlagsSampleDuration) {
|
||||||
ss << "duration=" << sample_duration;
|
ss << "duration=" << sample_duration;
|
||||||
|
@ -1180,7 +1180,7 @@ int SrsMp4TrackFragmentRunBox::nb_header()
|
||||||
vector<SrsMp4TrunEntry*>::iterator it;
|
vector<SrsMp4TrunEntry*>::iterator it;
|
||||||
for (it = entries.begin(); it != entries.end(); ++it) {
|
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||||
SrsMp4TrunEntry* entry = *it;
|
SrsMp4TrunEntry* entry = *it;
|
||||||
size += entry->nb_header();
|
size += entry->nb_bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
@ -1206,7 +1206,7 @@ srs_error_t SrsMp4TrackFragmentRunBox::encode_header(SrsBuffer* buf)
|
||||||
vector<SrsMp4TrunEntry*>::iterator it;
|
vector<SrsMp4TrunEntry*>::iterator it;
|
||||||
for (it = entries.begin(); it != entries.end(); ++it) {
|
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||||
SrsMp4TrunEntry* entry = *it;
|
SrsMp4TrunEntry* entry = *it;
|
||||||
if ((err = entry->encode_header(buf)) != srs_success) {
|
if ((err = entry->encode(buf)) != srs_success) {
|
||||||
return srs_error_wrap(err, "encode entry");
|
return srs_error_wrap(err, "encode entry");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1234,8 +1234,12 @@ srs_error_t SrsMp4TrackFragmentRunBox::decode_header(SrsBuffer* buf)
|
||||||
for (int i = 0; i < (int)sample_count; i++) {
|
for (int i = 0; i < (int)sample_count; i++) {
|
||||||
SrsMp4TrunEntry* entry = new SrsMp4TrunEntry(this);
|
SrsMp4TrunEntry* entry = new SrsMp4TrunEntry(this);
|
||||||
entries.push_back(entry);
|
entries.push_back(entry);
|
||||||
|
|
||||||
|
if (!buf->require(entry->nb_bytes())) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "trun entry requires %d bytes", entry->nb_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = entry->decode_header(buf)) != srs_success) {
|
if ((err = entry->decode(buf)) != srs_success) {
|
||||||
return srs_error_wrap(err, "decode entry");
|
return srs_error_wrap(err, "decode entry");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1259,7 +1263,7 @@ stringstream& SrsMp4TrackFragmentRunBox::dumps_detail(stringstream& ss, SrsMp4Du
|
||||||
if (sample_count > 0) {
|
if (sample_count > 0) {
|
||||||
ss << endl;
|
ss << endl;
|
||||||
srs_mp4_padding(ss, dc.indent());
|
srs_mp4_padding(ss, dc.indent());
|
||||||
srs_dumps_array(entries, ss, dc.indent(), srs_mp4_pfn_detail2, srs_mp4_delimiter_newline);
|
srs_dumps_array(entries, ss, dc.indent(), srs_mp4_pfn_box2, srs_mp4_delimiter_newline);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
|
@ -2089,13 +2093,22 @@ srs_error_t SrsMp4EditListBox::decode_header(SrsBuffer* buf)
|
||||||
SrsMp4ElstEntry& entry = entries[i];
|
SrsMp4ElstEntry& entry = entries[i];
|
||||||
|
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
|
if (!buf->require(16)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
entry.segment_duration = buf->read_8bytes();
|
entry.segment_duration = buf->read_8bytes();
|
||||||
entry.media_time = buf->read_8bytes();
|
entry.media_time = buf->read_8bytes();
|
||||||
} else {
|
} else {
|
||||||
|
if (!buf->require(8)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
entry.segment_duration = buf->read_4bytes();
|
entry.segment_duration = buf->read_4bytes();
|
||||||
entry.media_time = buf->read_4bytes();
|
entry.media_time = buf->read_4bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!buf->require(4)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
entry.media_rate_integer = buf->read_2bytes();
|
entry.media_rate_integer = buf->read_2bytes();
|
||||||
entry.media_rate_fraction = buf->read_2bytes();
|
entry.media_rate_fraction = buf->read_2bytes();
|
||||||
}
|
}
|
||||||
|
@ -3873,7 +3886,7 @@ srs_error_t SrsMp4DecodingTime2SampleBox::on_sample(uint32_t sample_index, SrsMp
|
||||||
|
|
||||||
int SrsMp4DecodingTime2SampleBox::nb_header()
|
int SrsMp4DecodingTime2SampleBox::nb_header()
|
||||||
{
|
{
|
||||||
return SrsMp4FullBox::nb_header() + 4 + 8 * (int)entries.size();
|
return SrsMp4FullBox::nb_header() + 4 + 8*(int)entries.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf)
|
srs_error_t SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf)
|
||||||
|
@ -3907,6 +3920,10 @@ srs_error_t SrsMp4DecodingTime2SampleBox::decode_header(SrsBuffer* buf)
|
||||||
entries.resize(entry_count);
|
entries.resize(entry_count);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < (size_t)entry_count; i++) {
|
for (size_t i = 0; i < (size_t)entry_count; i++) {
|
||||||
|
if (!buf->require(8)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
|
|
||||||
SrsMp4SttsEntry& entry = entries[i];
|
SrsMp4SttsEntry& entry = entries[i];
|
||||||
entry.sample_count = buf->read_4bytes();
|
entry.sample_count = buf->read_4bytes();
|
||||||
entry.sample_delta = buf->read_4bytes();
|
entry.sample_delta = buf->read_4bytes();
|
||||||
|
@ -4581,16 +4598,27 @@ srs_error_t SrsMp4SegmentIndexBox::decode_header(SrsBuffer* buf)
|
||||||
flags = buf->read_3bytes();
|
flags = buf->read_3bytes();
|
||||||
reference_id = buf->read_4bytes();
|
reference_id = buf->read_4bytes();
|
||||||
timescale = buf->read_4bytes();
|
timescale = buf->read_4bytes();
|
||||||
|
|
||||||
if (!version) {
|
if (!version) {
|
||||||
|
if (!buf->require(8)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
earliest_presentation_time = buf->read_4bytes();
|
earliest_presentation_time = buf->read_4bytes();
|
||||||
first_offset = buf->read_4bytes();
|
first_offset = buf->read_4bytes();
|
||||||
} else {
|
} else {
|
||||||
|
if (!buf->require(16)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
earliest_presentation_time = buf->read_8bytes();
|
earliest_presentation_time = buf->read_8bytes();
|
||||||
first_offset = buf->read_8bytes();
|
first_offset = buf->read_8bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t nn_entries = (uint32_t)(buf->read_4bytes() & 0xffff);
|
uint32_t nn_entries = (uint32_t)(buf->read_4bytes() & 0xffff);
|
||||||
for (uint32_t i = 0; i < nn_entries; i++) {
|
for (uint32_t i = 0; i < nn_entries; i++) {
|
||||||
|
if (!buf->require(12)) {
|
||||||
|
return srs_error_new(ERROR_MP4_BOX_REQUIRE_SPACE, "no space");
|
||||||
|
}
|
||||||
|
|
||||||
SrsMp4SegmentIndexEntry entry;
|
SrsMp4SegmentIndexEntry entry;
|
||||||
|
|
||||||
uint32_t v = buf->read_4bytes();
|
uint32_t v = buf->read_4bytes();
|
||||||
|
|
|
@ -186,10 +186,8 @@ public:
|
||||||
// An extended type; in this case, the type field is set to ‘uuid’.
|
// An extended type; in this case, the type field is set to ‘uuid’.
|
||||||
SrsMp4BoxType type;
|
SrsMp4BoxType type;
|
||||||
// For box 'uuid'.
|
// For box 'uuid'.
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<char> usertype;
|
std::vector<char> usertype;
|
||||||
protected:
|
protected:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4Box*> boxes;
|
std::vector<SrsMp4Box*> boxes;
|
||||||
private:
|
private:
|
||||||
// The position at buffer to start demux the box.
|
// The position at buffer to start demux the box.
|
||||||
|
@ -283,7 +281,6 @@ public:
|
||||||
uint32_t minor_version;
|
uint32_t minor_version;
|
||||||
private:
|
private:
|
||||||
// A list, to the end of the box, of brands
|
// A list, to the end of the box, of brands
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4BoxBrand> compatible_brands;
|
std::vector<SrsMp4BoxBrand> compatible_brands;
|
||||||
public:
|
public:
|
||||||
SrsMp4FileTypeBox();
|
SrsMp4FileTypeBox();
|
||||||
|
@ -478,7 +475,7 @@ enum SrsMp4TrunFlags
|
||||||
|
|
||||||
// Entry for trun.
|
// Entry for trun.
|
||||||
// ISO_IEC_14496-12-base-format-2012.pdf, page 69
|
// ISO_IEC_14496-12-base-format-2012.pdf, page 69
|
||||||
class SrsMp4TrunEntry
|
class SrsMp4TrunEntry : public ISrsCodec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsMp4FullBox* owner;
|
SrsMp4FullBox* owner;
|
||||||
|
@ -492,10 +489,11 @@ public:
|
||||||
SrsMp4TrunEntry(SrsMp4FullBox* o);
|
SrsMp4TrunEntry(SrsMp4FullBox* o);
|
||||||
virtual ~SrsMp4TrunEntry();
|
virtual ~SrsMp4TrunEntry();
|
||||||
|
|
||||||
virtual int nb_header();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode_header(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
virtual srs_error_t decode_header(SrsBuffer* buf);
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc);
|
|
||||||
|
virtual std::stringstream& dumps(std::stringstream& ss, SrsMp4DumpContext dc);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 8.8.8 Track Fragment Run Box (trun)
|
// 8.8.8 Track Fragment Run Box (trun)
|
||||||
|
@ -516,7 +514,6 @@ public:
|
||||||
uint32_t first_sample_flags;
|
uint32_t first_sample_flags;
|
||||||
// all fields in the following array are optional
|
// all fields in the following array are optional
|
||||||
public:
|
public:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4TrunEntry*> entries;
|
std::vector<SrsMp4TrunEntry*> entries;
|
||||||
public:
|
public:
|
||||||
SrsMp4TrackFragmentRunBox();
|
SrsMp4TrackFragmentRunBox();
|
||||||
|
@ -606,7 +603,6 @@ public:
|
||||||
class SrsMp4FreeSpaceBox : public SrsMp4Box
|
class SrsMp4FreeSpaceBox : public SrsMp4Box
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<char> data;
|
std::vector<char> data;
|
||||||
public:
|
public:
|
||||||
SrsMp4FreeSpaceBox(SrsMp4BoxType v);
|
SrsMp4FreeSpaceBox(SrsMp4BoxType v);
|
||||||
|
@ -914,7 +910,6 @@ class SrsMp4EditListBox : public SrsMp4FullBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// An integer that gives the number of entries in the following table
|
// An integer that gives the number of entries in the following table
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4ElstEntry> entries;
|
std::vector<SrsMp4ElstEntry> entries;
|
||||||
public:
|
public:
|
||||||
SrsMp4EditListBox();
|
SrsMp4EditListBox();
|
||||||
|
@ -1165,7 +1160,6 @@ public:
|
||||||
class SrsMp4DataReferenceBox : public SrsMp4FullBox
|
class SrsMp4DataReferenceBox : public SrsMp4FullBox
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4DataEntryBox*> entries;
|
std::vector<SrsMp4DataEntryBox*> entries;
|
||||||
public:
|
public:
|
||||||
SrsMp4DataReferenceBox();
|
SrsMp4DataReferenceBox();
|
||||||
|
@ -1287,7 +1281,6 @@ public:
|
||||||
class SrsMp4AvccBox : public SrsMp4Box
|
class SrsMp4AvccBox : public SrsMp4Box
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<char> avc_config;
|
std::vector<char> avc_config;
|
||||||
public:
|
public:
|
||||||
SrsMp4AvccBox();
|
SrsMp4AvccBox();
|
||||||
|
@ -1398,7 +1391,6 @@ class SrsMp4DecoderSpecificInfo : public SrsMp4BaseDescriptor
|
||||||
public:
|
public:
|
||||||
// AAC Audio Specific Config.
|
// AAC Audio Specific Config.
|
||||||
// 1.6.2.1 AudioSpecificConfig, in ISO_IEC_14496-3-AAC-2001.pdf, page 33.
|
// 1.6.2.1 AudioSpecificConfig, in ISO_IEC_14496-3-AAC-2001.pdf, page 33.
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<char> asc;
|
std::vector<char> asc;
|
||||||
public:
|
public:
|
||||||
SrsMp4DecoderSpecificInfo();
|
SrsMp4DecoderSpecificInfo();
|
||||||
|
@ -1465,7 +1457,6 @@ public:
|
||||||
// if (streamDependenceFlag)
|
// if (streamDependenceFlag)
|
||||||
uint16_t dependsOn_ES_ID;
|
uint16_t dependsOn_ES_ID;
|
||||||
// if (URL_Flag)
|
// if (URL_Flag)
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<char> URLstring;
|
std::vector<char> URLstring;
|
||||||
// if (OCRstreamFlag)
|
// if (OCRstreamFlag)
|
||||||
uint16_t OCR_ES_Id;
|
uint16_t OCR_ES_Id;
|
||||||
|
@ -1511,7 +1502,6 @@ public:
|
||||||
class SrsMp4SampleDescriptionBox : public SrsMp4FullBox
|
class SrsMp4SampleDescriptionBox : public SrsMp4FullBox
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4SampleEntry*> entries;
|
std::vector<SrsMp4SampleEntry*> entries;
|
||||||
public:
|
public:
|
||||||
SrsMp4SampleDescriptionBox();
|
SrsMp4SampleDescriptionBox();
|
||||||
|
@ -1561,7 +1551,6 @@ class SrsMp4DecodingTime2SampleBox : public SrsMp4FullBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// An integer that gives the number of entries in the following table.
|
// An integer that gives the number of entries in the following table.
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4SttsEntry> entries;
|
std::vector<SrsMp4SttsEntry> entries;
|
||||||
private:
|
private:
|
||||||
// The index for counter to calc the dts for samples.
|
// The index for counter to calc the dts for samples.
|
||||||
|
@ -1802,7 +1791,6 @@ public:
|
||||||
class SrsMp4UserDataBox : public SrsMp4Box
|
class SrsMp4UserDataBox : public SrsMp4Box
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<char> data;
|
std::vector<char> data;
|
||||||
public:
|
public:
|
||||||
SrsMp4UserDataBox();
|
SrsMp4UserDataBox();
|
||||||
|
@ -1840,7 +1828,6 @@ public:
|
||||||
uint32_t timescale;
|
uint32_t timescale;
|
||||||
uint64_t earliest_presentation_time;
|
uint64_t earliest_presentation_time;
|
||||||
uint64_t first_offset;
|
uint64_t first_offset;
|
||||||
// TODO: FIXME: Should double check buffer.
|
|
||||||
std::vector<SrsMp4SegmentIndexEntry> entries;
|
std::vector<SrsMp4SegmentIndexEntry> entries;
|
||||||
public:
|
public:
|
||||||
SrsMp4SegmentIndexBox();
|
SrsMp4SegmentIndexBox();
|
||||||
|
@ -2142,6 +2129,7 @@ public:
|
||||||
virtual srs_error_t flush(uint64_t& dts);
|
virtual srs_error_t flush(uint64_t& dts);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// LCOV_EXCL_START
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
// MP4 dumps functions.
|
// MP4 dumps functions.
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2247,5 +2235,7 @@ void srs_mp4_pfn_elem(T& elem, std::stringstream& ss, SrsMp4DumpContext /*dc*/)
|
||||||
ss << elem;
|
ss << elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue