Merge "libvpx: cherry pick "register" removal"
diff --git a/libwebm/README.android b/libwebm/README.android
index dba2327..37b839a 100644
--- a/libwebm/README.android
+++ b/libwebm/README.android
@@ -1,7 +1,7 @@
Name: libwebm
URL: http://www.webmproject.org
-Commit: 5c50e310e7050192b952fe588186fd1dadc08b6e
+Commit: 8e1ae495138b578f4e144fc22d6872eacf07d11f
Description:
Contains the sources used to compile libwebm's matroska parser.
diff --git a/libwebm/common/webmids.h b/libwebm/common/webmids.h
index 32a0c5f..fc0c208 100644
--- a/libwebm/common/webmids.h
+++ b/libwebm/common/webmids.h
@@ -93,6 +93,7 @@
kMkvDisplayHeight = 0x54BA,
kMkvDisplayUnit = 0x54B2,
kMkvAspectRatioType = 0x54B3,
+ kMkvColourSpace = 0x2EB524,
kMkvFrameRate = 0x2383E3,
// end video
// colour
@@ -124,6 +125,14 @@
kMkvLuminanceMin = 0x55DA,
// end mastering metadata
// end colour
+ // projection
+ kMkvProjection = 0x7670,
+ kMkvProjectionType = 0x7671,
+ kMkvProjectionPrivate = 0x7672,
+ kMkvProjectionPoseYaw = 0x7673,
+ kMkvProjectionPosePitch = 0x7674,
+ kMkvProjectionPoseRoll = 0x7675,
+ // end projection
// audio
kMkvAudio = 0xE1,
kMkvSamplingFrequency = 0xB5,
diff --git a/libwebm/mkvparser/mkvparser.cc b/libwebm/mkvparser/mkvparser.cc
index ff13327..5a7b896 100644
--- a/libwebm/mkvparser/mkvparser.cc
+++ b/libwebm/mkvparser/mkvparser.cc
@@ -23,8 +23,10 @@
#include "common/webmids.h"
namespace mkvparser {
+const long long kStringElementSizeLimit = 20 * 1000 * 1000;
const float MasteringMetadata::kValueNotPresent = FLT_MAX;
const long long Colour::kValueNotPresent = LLONG_MAX;
+const float Projection::kValueNotPresent = FLT_MAX;
#ifdef MSC_COMPAT
inline bool isnan(double val) { return !!_isnan(val); }
@@ -34,8 +36,6 @@
inline bool isinf(double val) { return std::isinf(val); }
#endif // MSC_COMPAT
-IMkvReader::~IMkvReader() {}
-
template <typename Type>
Type* SafeArrayAlloc(unsigned long long num_elements,
unsigned long long element_size) {
@@ -324,7 +324,7 @@
delete[] str;
str = NULL;
- if (size >= LONG_MAX || size < 0)
+ if (size >= LONG_MAX || size < 0 || size > kStringElementSizeLimit)
return E_FILE_FORMAT_INVALID;
// +1 for '\0' terminator
@@ -1465,7 +1465,7 @@
return E_FILE_FORMAT_INVALID;
for (;;) {
- const int status = LoadCluster();
+ const long status = LoadCluster();
if (status < 0) // error
return status;
@@ -1475,6 +1475,8 @@
}
}
+SeekHead::Entry::Entry() : id(0), pos(0), element_start(0), element_size(0) {}
+
SeekHead::SeekHead(Segment* pSegment, long long start, long long size_,
long long element_start, long long element_size)
: m_pSegment(pSegment),
@@ -1525,15 +1527,19 @@
if (pos != stop)
return E_FILE_FORMAT_INVALID;
- m_entries = new (std::nothrow) Entry[entry_count];
+ if (entry_count > 0) {
+ m_entries = new (std::nothrow) Entry[entry_count];
- if (m_entries == NULL)
- return -1;
+ if (m_entries == NULL)
+ return -1;
+ }
- m_void_elements = new (std::nothrow) VoidElement[void_element_count];
+ if (void_element_count > 0) {
+ m_void_elements = new (std::nothrow) VoidElement[void_element_count];
- if (m_void_elements == NULL)
- return -1;
+ if (m_void_elements == NULL)
+ return -1;
+ }
// now parse the entries and void elements
@@ -1552,14 +1558,14 @@
if (status < 0) // error
return status;
- if (id == libwebm::kMkvSeek) {
+ if (id == libwebm::kMkvSeek && entry_count > 0) {
if (ParseEntry(pReader, pos, size, pEntry)) {
Entry& e = *pEntry++;
e.element_start = idpos;
e.element_size = (pos + size) - idpos;
}
- } else if (id == libwebm::kMkvVoid) {
+ } else if (id == libwebm::kMkvVoid && void_element_count > 0) {
VoidElement& e = *pVoidElement++;
e.element_start = idpos;
@@ -1766,18 +1772,7 @@
if ((pos + seekIdSize) > stop)
return false;
- // Note that the SeekId payload really is serialized
- // as a "Matroska integer", not as a plain binary value.
- // In fact, Matroska requires that ID values in the
- // stream exactly match the binary representation as listed
- // in the Matroska specification.
- //
- // This parser is more liberal, and permits IDs to have
- // any width. (This could make the representation in the stream
- // different from what's in the spec, but it doesn't matter here,
- // since we always normalize "Matroska integer" values.)
-
- pEntry->id = ReadUInt(pReader, pos, len); // payload
+ pEntry->id = ReadID(pReader, pos, len); // payload
if (pEntry->id <= 0)
return false;
@@ -2434,7 +2429,9 @@
}
const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const {
- assert(pTrack);
+ if (pTrack == NULL) {
+ return NULL;
+ }
const long long n = pTrack->GetNumber();
@@ -4034,7 +4031,7 @@
}
const double rollover_check = m_duration * m_timecodeScale;
- if (rollover_check > LLONG_MAX)
+ if (rollover_check > static_cast<double>(LLONG_MAX))
return E_FILE_FORMAT_INVALID;
if (pos != stop)
@@ -4125,7 +4122,7 @@
}
const ContentEncoding::ContentCompression*
- ContentEncoding::GetCompressionByIndex(unsigned long idx) const {
+ContentEncoding::GetCompressionByIndex(unsigned long idx) const {
const ptrdiff_t count = compression_entries_end_ - compression_entries_;
assert(count >= 0);
@@ -4983,29 +4980,27 @@
if (!reader)
return false;
- std::auto_ptr<PrimaryChromaticity> chromaticity_ptr;
+ if (!*chromaticity)
+ *chromaticity = new PrimaryChromaticity();
- if (!*chromaticity) {
- chromaticity_ptr.reset(new PrimaryChromaticity());
- } else {
- chromaticity_ptr.reset(*chromaticity);
- }
-
- if (!chromaticity_ptr.get())
+ if (!*chromaticity)
return false;
- float* value = is_x ? &chromaticity_ptr->x : &chromaticity_ptr->y;
+ PrimaryChromaticity* pc = *chromaticity;
+ float* value = is_x ? &pc->x : &pc->y;
double parser_value = 0;
- const long long value_parse_status =
+ const long long parse_status =
UnserializeFloat(reader, read_pos, value_size, parser_value);
+ // Valid range is [0, 1]. Make sure the double is representable as a float
+ // before casting.
+ if (parse_status < 0 || parser_value < 0.0 || parser_value > 1.0 ||
+ (parser_value > 0.0 && parser_value < FLT_MIN))
+ return false;
+
*value = static_cast<float>(parser_value);
- if (value_parse_status < 0 || *value < 0.0 || *value > 1.0)
- return false;
-
- *chromaticity = chromaticity_ptr.release();
return true;
}
@@ -5014,7 +5009,7 @@
if (!reader || *mm)
return false;
- std::auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
+ std::unique_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
if (!mm_ptr.get())
return false;
@@ -5034,6 +5029,10 @@
double value = 0;
const long long value_parse_status =
UnserializeFloat(reader, read_pos, child_size, value);
+ if (value < -FLT_MAX || value > FLT_MAX ||
+ (value > 0.0 && value < FLT_MIN)) {
+ return false;
+ }
mm_ptr->luminance_max = static_cast<float>(value);
if (value_parse_status < 0 || mm_ptr->luminance_max < 0.0 ||
mm_ptr->luminance_max > 9999.99) {
@@ -5043,6 +5042,10 @@
double value = 0;
const long long value_parse_status =
UnserializeFloat(reader, read_pos, child_size, value);
+ if (value < -FLT_MAX || value > FLT_MAX ||
+ (value > 0.0 && value < FLT_MIN)) {
+ return false;
+ }
mm_ptr->luminance_min = static_cast<float>(value);
if (value_parse_status < 0 || mm_ptr->luminance_min < 0.0 ||
mm_ptr->luminance_min > 999.9999) {
@@ -5095,7 +5098,7 @@
if (!reader || *colour)
return false;
- std::auto_ptr<Colour> colour_ptr(new Colour());
+ std::unique_ptr<Colour> colour_ptr(new Colour());
if (!colour_ptr.get())
return false;
@@ -5188,11 +5191,95 @@
return true;
}
+bool Projection::Parse(IMkvReader* reader, long long start, long long size,
+ Projection** projection) {
+ if (!reader || *projection)
+ return false;
+
+ std::unique_ptr<Projection> projection_ptr(new Projection());
+ if (!projection_ptr.get())
+ return false;
+
+ const long long end = start + size;
+ long long read_pos = start;
+
+ while (read_pos < end) {
+ long long child_id = 0;
+ long long child_size = 0;
+
+ const long long status =
+ ParseElementHeader(reader, read_pos, end, child_id, child_size);
+ if (status < 0)
+ return false;
+
+ if (child_id == libwebm::kMkvProjectionType) {
+ long long projection_type = kTypeNotPresent;
+ projection_type = UnserializeUInt(reader, read_pos, child_size);
+ if (projection_type < 0)
+ return false;
+
+ projection_ptr->type = static_cast<ProjectionType>(projection_type);
+ } else if (child_id == libwebm::kMkvProjectionPrivate) {
+ unsigned char* data = SafeArrayAlloc<unsigned char>(1, child_size);
+
+ if (data == NULL)
+ return false;
+
+ const int status =
+ reader->Read(read_pos, static_cast<long>(child_size), data);
+
+ if (status) {
+ delete[] data;
+ return false;
+ }
+
+ projection_ptr->private_data = data;
+ projection_ptr->private_data_length = static_cast<size_t>(child_size);
+ } else {
+ double value = 0;
+ const long long value_parse_status =
+ UnserializeFloat(reader, read_pos, child_size, value);
+ // Make sure value is representable as a float before casting.
+ if (value_parse_status < 0 || value < -FLT_MAX || value > FLT_MAX ||
+ (value > 0.0 && value < FLT_MIN)) {
+ return false;
+ }
+
+ switch (child_id) {
+ case libwebm::kMkvProjectionPoseYaw:
+ projection_ptr->pose_yaw = static_cast<float>(value);
+ break;
+ case libwebm::kMkvProjectionPosePitch:
+ projection_ptr->pose_pitch = static_cast<float>(value);
+ break;
+ case libwebm::kMkvProjectionPoseRoll:
+ projection_ptr->pose_roll = static_cast<float>(value);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ read_pos += child_size;
+ if (read_pos > end)
+ return false;
+ }
+
+ *projection = projection_ptr.release();
+ return true;
+}
+
VideoTrack::VideoTrack(Segment* pSegment, long long element_start,
long long element_size)
- : Track(pSegment, element_start, element_size), m_colour(NULL) {}
+ : Track(pSegment, element_start, element_size),
+ m_colour_space(NULL),
+ m_colour(NULL),
+ m_projection(NULL) {}
-VideoTrack::~VideoTrack() { delete m_colour; }
+VideoTrack::~VideoTrack() {
+ delete m_colour;
+ delete m_projection;
+}
long VideoTrack::Parse(Segment* pSegment, const Info& info,
long long element_start, long long element_size,
@@ -5211,6 +5298,7 @@
long long stereo_mode = 0;
double rate = 0.0;
+ char* colour_space = NULL;
IMkvReader* const pReader = pSegment->m_pReader;
@@ -5224,6 +5312,7 @@
const long long stop = pos + s.size;
Colour* colour = NULL;
+ Projection* projection = NULL;
while (pos < stop) {
long long id, size;
@@ -5274,6 +5363,13 @@
} else if (id == libwebm::kMkvColour) {
if (!Colour::Parse(pReader, pos, size, &colour))
return E_FILE_FORMAT_INVALID;
+ } else if (id == libwebm::kMkvProjection) {
+ if (!Projection::Parse(pReader, pos, size, &projection))
+ return E_FILE_FORMAT_INVALID;
+ } else if (id == libwebm::kMkvColourSpace) {
+ const long status = UnserializeString(pReader, pos, size, colour_space);
+ if (status < 0)
+ return status;
}
pos += size; // consume payload
@@ -5305,6 +5401,8 @@
pTrack->m_stereo_mode = stereo_mode;
pTrack->m_rate = rate;
pTrack->m_colour = colour;
+ pTrack->m_colour_space = colour_space;
+ pTrack->m_projection = projection;
pResult = pTrack;
return 0; // success
@@ -5405,6 +5503,8 @@
Colour* VideoTrack::GetColour() const { return m_colour; }
+Projection* VideoTrack::GetProjection() const { return m_projection; }
+
long long VideoTrack::GetWidth() const { return m_width; }
long long VideoTrack::GetHeight() const { return m_height; }
@@ -6698,8 +6798,10 @@
{}
Cluster::~Cluster() {
- if (m_entries_count <= 0)
+ if (m_entries_count <= 0) {
+ delete[] m_entries;
return;
+ }
BlockEntry** i = m_entries;
BlockEntry** const j = m_entries + m_entries_count;
@@ -7797,7 +7899,7 @@
if (pos > stop)
return E_FILE_FORMAT_INVALID;
- const int exp = 7 * len - 1;
+ const long exp = 7 * len - 1;
const long long bias = (1LL << exp) - 1LL;
const long long delta_size = delta_size_ - bias;
@@ -7810,6 +7912,10 @@
return E_FILE_FORMAT_INVALID;
curr.len = static_cast<long>(frame_size);
+ // Check if size + curr.len could overflow.
+ if (size > LLONG_MAX - curr.len) {
+ return E_FILE_FORMAT_INVALID;
+ }
size += curr.len; // contribution of this frame
--frame_count;
@@ -7850,7 +7956,6 @@
pf = m_frames;
while (pf != pf_end) {
Frame& f = *pf++;
- assert((pos + f.len) <= stop);
if ((pos + f.len) > stop)
return E_FILE_FORMAT_INVALID;
@@ -7872,6 +7977,11 @@
const long long tc0 = pCluster->GetTimeCode();
assert(tc0 >= 0);
+ // Check if tc0 + m_timecode would overflow.
+ if (tc0 < 0 || LLONG_MAX - tc0 < m_timecode) {
+ return -1;
+ }
+
const long long tc = tc0 + m_timecode;
return tc; // unscaled timecode units
@@ -7889,6 +7999,10 @@
const long long scale = pInfo->GetTimeCodeScale();
assert(scale >= 1);
+ // Check if tc * scale could overflow.
+ if (tc != 0 && scale > LLONG_MAX / tc) {
+ return -1;
+ }
const long long ns = tc * scale;
return ns;
diff --git a/libwebm/mkvparser/mkvparser.h b/libwebm/mkvparser/mkvparser.h
index 42e6e88..9f296ed 100644
--- a/libwebm/mkvparser/mkvparser.h
+++ b/libwebm/mkvparser/mkvparser.h
@@ -22,7 +22,7 @@
virtual int Length(long long* total, long long* available) = 0;
protected:
- virtual ~IMkvReader();
+ virtual ~IMkvReader() {}
};
template <typename Type>
@@ -473,6 +473,34 @@
MasteringMetadata* mastering_metadata;
};
+struct Projection {
+ enum ProjectionType {
+ kTypeNotPresent = -1,
+ kRectangular = 0,
+ kEquirectangular = 1,
+ kCubeMap = 2,
+ kMesh = 3,
+ };
+ static const float kValueNotPresent;
+ Projection()
+ : type(kTypeNotPresent),
+ private_data(NULL),
+ private_data_length(0),
+ pose_yaw(kValueNotPresent),
+ pose_pitch(kValueNotPresent),
+ pose_roll(kValueNotPresent) {}
+ ~Projection() { delete[] private_data; }
+ static bool Parse(IMkvReader* reader, long long element_start,
+ long long element_size, Projection** projection);
+
+ ProjectionType type;
+ unsigned char* private_data;
+ size_t private_data_length;
+ float pose_yaw;
+ float pose_pitch;
+ float pose_roll;
+};
+
class VideoTrack : public Track {
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
@@ -497,6 +525,10 @@
Colour* GetColour() const;
+ Projection* GetProjection() const;
+
+ const char* GetColourSpace() const { return m_colour_space; };
+
private:
long long m_width;
long long m_height;
@@ -504,10 +536,11 @@
long long m_display_height;
long long m_display_unit;
long long m_stereo_mode;
-
+ char* m_colour_space;
double m_rate;
Colour* m_colour;
+ Projection* m_projection;
};
class AudioTrack : public Track {
@@ -813,6 +846,8 @@
long Parse();
struct Entry {
+ Entry();
+
// the SeekHead entry payload
long long id;
long long pos;