mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:57:47 +00:00
JPGLoader: Check existence of Huffman tables in scan header segment (#3442)
DC and AC table IDs read in the scan header segment weren't validated against the IDs of Huffman tables read in the DHT segment. This caused an OOB read when a Huffman table was accessed using the ID read in the scan header segment. Furthermore, the decoder now replaces the old DC or AC table if a redefinition has been found prior to the scan header. Fixes #3439.
This commit is contained in:
parent
d830c107ce
commit
2a3166e523
3 changed files with 57 additions and 5 deletions
|
@ -6,6 +6,8 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
|
<h3>Issue-3439</h3>
|
||||||
|
<img alt="lena" src="jpgsuite_files/offending-3439.jpg"/><br>
|
||||||
<h3>Non-subsampled Lena</h3> <br>
|
<h3>Non-subsampled Lena</h3> <br>
|
||||||
<img alt="lena" src="jpgsuite_files/non-subsampled-lena.jpg"/> <br>
|
<img alt="lena" src="jpgsuite_files/non-subsampled-lena.jpg"/> <br>
|
||||||
<h3>Chroma Horizontally Halved Lena</h3> <br>
|
<h3>Chroma Horizontally Halved Lena</h3> <br>
|
||||||
|
|
BIN
Base/res/html/misc/jpgsuite_files/offending-3439.jpg
Normal file
BIN
Base/res/html/misc/jpgsuite_files/offending-3439.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
|
@ -536,8 +536,31 @@ static bool read_start_of_scan(BufferStream& stream, JPGLoadingContext& context)
|
||||||
stream >> table_ids;
|
stream >> table_ids;
|
||||||
if (stream.handle_read_failure())
|
if (stream.handle_read_failure())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
component->dc_destination_id = table_ids >> 4;
|
component->dc_destination_id = table_ids >> 4;
|
||||||
component->ac_destination_id = table_ids & 0x0F;
|
component->ac_destination_id = table_ids & 0x0F;
|
||||||
|
|
||||||
|
if (context.dc_tables.size() != context.ac_tables.size()) {
|
||||||
|
dbg() << stream.offset() << ": DC & AC table count mismatch!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dc_table_exists = false;
|
||||||
|
bool ac_table_exists = false;
|
||||||
|
for (unsigned t = 0; t < context.dc_tables.size(); t++) {
|
||||||
|
dc_table_exists = dc_table_exists || (context.dc_tables[t].destination_id == component->dc_destination_id);
|
||||||
|
ac_table_exists = ac_table_exists || (context.ac_tables[t].destination_id == component->ac_destination_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dc_table_exists) {
|
||||||
|
dbg() << stream.offset() << ": Invalid DC huffman table destination id: " << component->dc_destination_id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ac_table_exists) {
|
||||||
|
dbg() << stream.offset() << ": Invalid AC huffman table destination id: " << component->ac_destination_id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 spectral_selection_start;
|
u8 spectral_selection_start;
|
||||||
|
@ -576,6 +599,34 @@ static bool read_reset_marker(BufferStream& stream, JPGLoadingContext& context)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool huffman_table_reset_helper(HuffmanTableSpec& src, JPGLoadingContext& context)
|
||||||
|
{
|
||||||
|
auto& table = src.type == 0 ? context.dc_tables : context.ac_tables;
|
||||||
|
if (src.destination_id == 0) {
|
||||||
|
if (table.is_empty())
|
||||||
|
table.append(move(src));
|
||||||
|
else
|
||||||
|
table[0] = move(src);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src.destination_id == 1) {
|
||||||
|
if (table.size() < 1) {
|
||||||
|
String table_str = src.type == 0 ? "DC" : "AC";
|
||||||
|
dbg() << table_str << "[1] showed up before " << table_str << "[0]!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (table.size() == 1)
|
||||||
|
table.append(move(src));
|
||||||
|
else
|
||||||
|
table[1] = move(src);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg() << "Unsupported huffman table destination id: " << src.destination_id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool read_huffman_table(BufferStream& stream, JPGLoadingContext& context)
|
static bool read_huffman_table(BufferStream& stream, JPGLoadingContext& context)
|
||||||
{
|
{
|
||||||
i32 bytes_to_read = read_be_word(stream);
|
i32 bytes_to_read = read_be_word(stream);
|
||||||
|
@ -594,7 +645,7 @@ static bool read_huffman_table(BufferStream& stream, JPGLoadingContext& context)
|
||||||
dbg() << stream.offset() << String::format(": Unrecognized huffman table: %i!", table_type);
|
dbg() << stream.offset() << String::format(": Unrecognized huffman table: %i!", table_type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (table_destination_id > 3) {
|
if (table_destination_id > 1) {
|
||||||
dbg() << stream.offset()
|
dbg() << stream.offset()
|
||||||
<< String::format(": Invalid huffman table destination id: %i!", table_destination_id);
|
<< String::format(": Invalid huffman table destination id: %i!", table_destination_id);
|
||||||
return false;
|
return false;
|
||||||
|
@ -625,13 +676,12 @@ static bool read_huffman_table(BufferStream& stream, JPGLoadingContext& context)
|
||||||
if (stream.handle_read_failure())
|
if (stream.handle_read_failure())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (table_type == 0)
|
if (!huffman_table_reset_helper(table, context))
|
||||||
context.dc_tables.append(move(table));
|
return false;
|
||||||
else
|
|
||||||
context.ac_tables.append(move(table));
|
|
||||||
|
|
||||||
bytes_to_read -= 1 + 16 + total_codes;
|
bytes_to_read -= 1 + 16 + total_codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_to_read != 0) {
|
if (bytes_to_read != 0) {
|
||||||
dbg() << stream.offset() << ": Extra bytes detected in huffman header!";
|
dbg() << stream.offset() << ": Extra bytes detected in huffman header!";
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue