Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Simd/SimdAvx2ImageLoadJpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ namespace Simd
jpeg__context* s;
jpeg__huffman huff_dc[4];
jpeg__huffman huff_ac[4];
bool huff_dc_defined[4], huff_ac_defined[4];
jpeg__uint16 dequant[4][64];
jpeg__int16 fast_ac[4][1 << FAST_BITS];

Expand Down Expand Up @@ -1238,10 +1239,12 @@ namespace Simd
if (tc == 0) {
if (!jpeg__build_huffman(z->huff_dc + th, sizes)) return 0;
v = z->huff_dc[th].values;
z->huff_dc_defined[th] = true;
}
else {
if (!jpeg__build_huffman(z->huff_ac + th, sizes)) return 0;
v = z->huff_ac[th].values;
z->huff_ac_defined[th] = true;
}
for (i = 0; i < n; ++i)
v[i] = jpeg__get8(z->s);
Expand Down Expand Up @@ -1336,6 +1339,22 @@ namespace Simd
}
}

// The selectors above are bounded to 0..3 but never checked against the DHT markers
// that were actually seen, so a scan referencing a table no DHT defined runs the
// entropy decoder over an uninitialised jpeg__huffman and reads its garbage delta/values
// out of bounds. Reject such a scan before decoding. The DC table is used only for the
// first DC scan (spec_start == 0, succ_high == 0) and the AC table only for AC scans
// (spec_start != 0); a baseline scan uses both.
for (i = 0; i < z->scan_n; ++i) {
int which = z->order[i];
int useDc = !z->progressive || (z->spec_start == 0 && z->succ_high == 0);
int useAc = !z->progressive || z->spec_start != 0;
if (useDc && !z->huff_dc_defined[z->img_comp[which].hd])
return JpegLoadError("undefined DC huffman table", "Corrupt JPEG");
if (useAc && !z->huff_ac_defined[z->img_comp[which].ha])
return JpegLoadError("undefined AC huffman table", "Corrupt JPEG");
}

return 1;
}

Expand Down Expand Up @@ -1464,6 +1483,8 @@ namespace Simd
z->jfif = 0;
z->app14_color_transform = -1; // valid values are 0,1,2
z->marker = JPEG__MARKER_none; // initialize cached marker to empty
for (int i = 0; i < 4; ++i)
z->huff_dc_defined[i] = z->huff_ac_defined[i] = false;
m = jpeg__get_marker(z);
if (!jpeg__SOI(m)) return JpegLoadError("no SOI", "Corrupt JPEG");
if (scan == JPEG__SCAN_type) return 1;
Expand Down
21 changes: 21 additions & 0 deletions src/Simd/SimdBaseImageLoadJpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,12 +753,14 @@ namespace Simd
if (!z->huff_dc[th].Build(sizes))
return 0;
v = z->huff_dc[th].values;
z->huffDcDefined[th] = true;
}
else
{
if (!z->huff_ac[th].Build(sizes))
return 0;
v = z->huff_ac[th].values;
z->huffAcDefined[th] = true;
}
for (i = 0; i < n; ++i)
v[i] = z->stream->Get8u();
Expand Down Expand Up @@ -857,6 +859,23 @@ namespace Simd
return JpegLoadError("bad SOS", "Corrupt JPEG");
z->spec_end = 63;
}
// Each scan component is decoded with the Huffman tables its selector points at
// (huff_dc[hd] / huff_ac[ha]). The selectors are only bounded to 0..3 above, never
// checked against the DHT markers that were actually seen, so a scan referencing an
// undefined table sends JpegHuffmanDecode into an uninitialised JpegHuffman and reads
// its garbage delta/values out of bounds. Reject the scan here, before decoding. The
// DC table is used only for the first DC scan (spec_start == 0, succ_high == 0) and the
// AC table only for AC scans (spec_start != 0); a baseline scan uses both.
for (int i = 0; i < z->scan_n; ++i)
{
const JpegImgComp& comp = z->img_comp[z->order[i]];
bool useDc = !z->progressive || (z->spec_start == 0 && z->succ_high == 0);
bool useAc = !z->progressive || z->spec_start != 0;
if (useDc && !z->huffDcDefined[comp.hd])
return JpegLoadError("undefined DC huffman table", "Corrupt JPEG");
if (useAc && !z->huffAcDefined[comp.ha])
return JpegLoadError("undefined AC huffman table", "Corrupt JPEG");
}
return 1;
}

Expand Down Expand Up @@ -950,6 +969,8 @@ namespace Simd
z->jfif = 0;
z->app14_color_transform = -1;
z->marker = JpegMarkerNone;
for (int i = 0; i < 4; ++i)
z->huffDcDefined[i] = z->huffAcDefined[i] = false;
int m = JpegGetMarker(z);
if (m != JpegMarkerSoi)
return JpegLoadError("no SOI", "Corrupt JPEG");
Expand Down
1 change: 1 addition & 0 deletions src/Simd/SimdImageLoadJpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ namespace Simd
int img_n, img_out_n;
JpegHuffman huff_dc[4];
JpegHuffman huff_ac[4];
bool huffDcDefined[4], huffAcDefined[4];
uint16_t dequant[4][64];

int img_h_max, img_v_max;
Expand Down
Loading