Skip to content

Commit b66ebd9

Browse files
kmilosneheb
authored andcommitted
Fix regression parsing PNG text chunks with zero length payload
(cherry picked from commit 16c1cd7)
1 parent d234d63 commit b66ebd9

File tree

1 file changed

+18
-19
lines changed

1 file changed

+18
-19
lines changed

src/pngchunk_int.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,20 +100,24 @@ DataBuf PngChunk::parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkTyp
100100
}
101101

102102
// compressed string after the compression technique spec
103-
const byte* compressedText = data.c_data(keysize + nullSeparators);
104103
size_t compressedTextSize = data.size() - keysize - nullSeparators;
105-
enforce(compressedTextSize < data.size(), ErrorCode::kerCorruptedMetadata);
104+
if (compressedTextSize) {
105+
const byte* compressedText = data.c_data(keysize + nullSeparators);
106+
enforce(compressedTextSize < data.size(), ErrorCode::kerCorruptedMetadata);
106107

107-
zlibUncompress(compressedText, static_cast<uint32_t>(compressedTextSize), arr);
108+
zlibUncompress(compressedText, static_cast<uint32_t>(compressedTextSize), arr);
109+
}
108110
} else if (type == tEXt_Chunk) {
109111
enforce(data.size() >= Safe::add(keysize, static_cast<size_t>(1)), ErrorCode::kerCorruptedMetadata);
110112
// Extract a non-compressed Latin-1 text chunk
111113

112114
// the text comes after the key, but isn't null terminated
113-
const byte* text = data.c_data(keysize + 1);
114115
size_t textsize = data.size() - keysize - 1;
116+
if (textsize) {
117+
const byte* text = data.c_data(keysize + 1);
115118

116-
arr = DataBuf(text, textsize);
119+
arr = DataBuf(text, textsize);
120+
}
117121
} else if (type == iTXt_Chunk) {
118122
enforce(data.size() > Safe::add(keysize, static_cast<size_t>(3)), ErrorCode::kerCorruptedMetadata);
119123
const size_t nullCount = std::count(data.c_data(keysize + 3), data.c_data(data.size() - 1), '\0');
@@ -127,7 +131,8 @@ DataBuf PngChunk::parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkTyp
127131
const byte compressionMethod = data.read_uint8(keysize + 2);
128132

129133
enforce(compressionFlag == 0x00 || compressionFlag == 0x01, ErrorCode::kerCorruptedMetadata);
130-
enforce(compressionMethod == 0x00, ErrorCode::kerCorruptedMetadata);
134+
if (compressionFlag == 0x01)
135+
enforce(compressionMethod == 0x00, ErrorCode::kerFailedToReadImageData);
131136

132137
// language description string after the compression technique spec
133138
const size_t languageTextMaxSize = data.size() - keysize - 3;
@@ -141,22 +146,22 @@ DataBuf PngChunk::parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkTyp
141146
data.size() - (keysize + 3 + languageTextSize + 1));
142147
const size_t translatedKeyTextSize = translatedKeyText.size();
143148

144-
if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) {
145-
enforce(Safe::add(keysize + 3 + languageTextSize + 1, Safe::add(translatedKeyTextSize, static_cast<size_t>(1))) <=
146-
data.size(),
147-
ErrorCode::kerCorruptedMetadata);
149+
enforce(Safe::add(keysize + 3 + languageTextSize + 1, Safe::add(translatedKeyTextSize, static_cast<size_t>(1))) <=
150+
data.size(),
151+
ErrorCode::kerCorruptedMetadata);
148152

153+
const auto textsize =
154+
static_cast<long>(data.size() - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1));
155+
if (textsize) {
149156
const byte* text = data.c_data(keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
150-
const auto textsize =
151-
static_cast<long>(data.size() - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1));
152157

153158
if (compressionFlag == 0x00) {
154159
// then it's an uncompressed iTXt chunk
155160
#ifdef EXIV2_DEBUG_MESSAGES
156161
std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n";
157162
#endif
158163
arr = DataBuf(text, textsize);
159-
} else if (compressionFlag == 0x01 && compressionMethod == 0x00) {
164+
} else {
160165
// then it's a zlib compressed iTXt chunk
161166
#ifdef EXIV2_DEBUG_MESSAGES
162167
std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n";
@@ -165,12 +170,6 @@ DataBuf PngChunk::parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkTyp
165170
// the compressed text comes after the translated keyword, but isn't null terminated
166171
zlibUncompress(text, textsize, arr);
167172
}
168-
} else {
169-
// then it isn't zlib compressed and we are sunk
170-
#ifdef EXIV2_DEBUG_MESSAGES
171-
std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard iTXt compression method.\n";
172-
#endif
173-
throw Error(ErrorCode::kerFailedToReadImageData);
174173
}
175174
} else {
176175
#ifdef DEBUG

0 commit comments

Comments
 (0)