Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…l?id=51751

Credit to OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52053
Avoid null pointer deref and heap buffer overflow.
  • Loading branch information
kevinbackhouse committed Oct 8, 2022
1 parent a2cb06a commit 459910c
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 24 deletions.
41 changes: 17 additions & 24 deletions src/quicktimevideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,14 @@ void QuickTimeVideo::decodeBlock(std::string const& entered_from) {
tagDecoder(buf, newsize);
} // QuickTimeVideo::decodeBlock

static std::string readString(BasicIo& io, size_t size) {
enforce(size <= io.size() - io.tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
Exiv2::DataBuf str(size + 1);
io.readOrThrow(str.data(), size);
str.write_uint8(size, 0); // nul-terminate string
return Exiv2::toString(str.data());
}

void QuickTimeVideo::tagDecoder(Exiv2::DataBuf& buf, size_t size) {
assert(buf.size() > 4);

Expand Down Expand Up @@ -626,30 +634,21 @@ void QuickTimeVideo::tagDecoder(Exiv2::DataBuf& buf, size_t size) {
keysTagDecoder(size);

else if (equalsQTimeTag(buf, "url ")) {
Exiv2::DataBuf url(size + 1);
io_->readOrThrow(url.data(), size);
url.write_uint8(size, 0);
if (currentStream_ == Video)
xmpData_["Xmp.video.URL"] = Exiv2::toString(url.data());
xmpData_["Xmp.video.URL"] = readString(*io_, size);
else if (currentStream_ == Audio)
xmpData_["Xmp.audio.URL"] = Exiv2::toString(url.data());
xmpData_["Xmp.audio.URL"] = readString(*io_, size);
}

else if (equalsQTimeTag(buf, "urn ")) {
Exiv2::DataBuf urn(size + 1);
io_->readOrThrow(urn.data(), size);
urn.write_uint8(size, 0);
if (currentStream_ == Video)
xmpData_["Xmp.video.URN"] = Exiv2::toString(urn.data());
xmpData_["Xmp.video.URN"] = readString(*io_, size);
else if (currentStream_ == Audio)
xmpData_["Xmp.audio.URN"] = Exiv2::toString(urn.data());
xmpData_["Xmp.audio.URN"] = readString(*io_, size);
}

else if (equalsQTimeTag(buf, "dcom")) {
Exiv2::DataBuf dcom(size + 1);
io_->readOrThrow(dcom.data(), size);
dcom.write_uint8(size, 0);
xmpData_["Xmp.video.Compressor"] = Exiv2::toString(dcom.data());
xmpData_["Xmp.video.Compressor"] = readString(*io_, size);
}

else if (equalsQTimeTag(buf, "smhd")) {
Expand Down Expand Up @@ -782,6 +781,7 @@ void QuickTimeVideo::CameraTagsDecoder(size_t size_external) {
xmpData_["Xmp.video.FocalLength"] = buf.read_uint32(0, littleEndian) / (double)buf2.read_uint32(0, littleEndian);
io_->seek(static_cast<long>(95), BasicIo::cur);
io_->readOrThrow(buf.data(), 48);
buf.write_uint8(48, 0);
xmpData_["Xmp.video.Software"] = Exiv2::toString(buf.data());
io_->readOrThrow(buf.data(), 4);
xmpData_["Xmp.video.ISO"] = buf.read_uint32(0, littleEndian);
Expand Down Expand Up @@ -829,8 +829,8 @@ void QuickTimeVideo::userDataDecoder(size_t size_external) {

else if (equalsQTimeTag(buf, "CNCV") || equalsQTimeTag(buf, "CNFV") || equalsQTimeTag(buf, "CNMN") ||
equalsQTimeTag(buf, "NCHD") || equalsQTimeTag(buf, "FFMV")) {
io_->readOrThrow(buf.data(), size - 8);
xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data());
enforce(tv, Exiv2::ErrorCode::kerCorruptedMetadata);
xmpData_[exvGettext(tv->label_)] = readString(*io_, size - 8);
}

else if (equalsQTimeTag(buf, "CMbo") || equalsQTimeTag(buf, "Cmbo")) {
Expand All @@ -845,15 +845,8 @@ void QuickTimeVideo::userDataDecoder(size_t size_external) {
}

else if (tv) {
const size_t tv_size = size - 12;
if (tv_size >= buf.size()) {
enforce(tv_size <= io_->size() - io_->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
buf.resize(tv_size + 1);
}
io_->readOrThrow(buf.data(), 4);
io_->readOrThrow(buf.data(), tv_size);
buf.write_uint8(tv_size, 0); // nul-terminate string
xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data());
xmpData_[exvGettext(tv->label_)] = readString(*io_, size - 12);
}

else if (td)
Expand Down
Binary file added test/data/issue_2376_poc.mp4
Binary file not shown.
Binary file added test/data/issue_2377_poc.mp4
Binary file not shown.
13 changes: 13 additions & 0 deletions tests/bugfixes/github/test_issue_2376.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-

from system_tests import CaseMeta, check_no_ASAN_UBSAN_errors

class issue_2376_QuickTimeVideo_userDataDecoder_null_deref(metaclass=CaseMeta):
url = "https://github.com/Exiv2/exiv2/issues/2376"
filename = "$data_path/issue_2376_poc.mp4"
commands = ["$exiv2 $filename"]
retval = [1]
stderr = ["""$exiv2_exception_message $filename:
$kerCorruptedMetadata
"""]
stdout = [""]
17 changes: 17 additions & 0 deletions tests/bugfixes/github/test_issue_2377.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-

from system_tests import CaseMeta, check_no_ASAN_UBSAN_errors

class issue_2377_QuickTimeVideo_userDataDecoder_buffer_overflow(metaclass=CaseMeta):
url = "https://github.com/Exiv2/exiv2/issues/2377"
filename = "$data_path/issue_2377_poc.mp4"
commands = ["$exiv2 $filename"]
retval = [253]
stderr = ["""$filename: No Exif data found in the file
"""]
stdout = ["""File name : $filename
File size : 225 Bytes
MIME type : video/quicktime
Image size : 0 x 0
"""]

2 changes: 2 additions & 0 deletions tests/regression_tests/test_regression_allfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def get_valid_files(data_dir):
"issue_2340_poc.mp4",
"issue_2345_poc.mp4",
"issue_2366_poc.mp4",
"issue_2376_poc.mp4",
"issue_2377_poc.mp4",
"2018-01-09-exiv2-crash-001.tiff",
"cve_2017_1000126_stack-oob-read.webp",
"exiv2-bug1247.jpg",
Expand Down

0 comments on commit 459910c

Please sign in to comment.