mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibGfx/JBIG2: Don't assert on unexpected OOB values in the bitstream
This should only happen on either invalid inputs or if our code has a bug (gasp!). Printing an error instead of asserting seems nicer.
This commit is contained in:
parent
b3c423e4ca
commit
a2a5fc76aa
Notes:
sideshowbarker
2024-07-17 21:11:12 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/a2a5fc76aa Pull-request: https://github.com/SerenityOS/serenity/pull/23726
1 changed files with 43 additions and 33 deletions
|
@ -224,6 +224,9 @@ public:
|
|||
// Returns OptionalNone for OOB.
|
||||
Optional<i32> decode();
|
||||
|
||||
// Returns Error for OOB.
|
||||
ErrorOr<i32> decode_non_oob();
|
||||
|
||||
private:
|
||||
ArithmeticDecoder& m_decoder;
|
||||
u16 PREV { 0 };
|
||||
|
@ -290,6 +293,14 @@ Optional<int> ArithmeticIntegerDecoder::decode()
|
|||
return S ? -V : V;
|
||||
}
|
||||
|
||||
ErrorOr<i32> ArithmeticIntegerDecoder::decode_non_oob()
|
||||
{
|
||||
auto result = decode();
|
||||
if (!result.has_value())
|
||||
return Error::from_string_literal("ArithmeticIntegerDecoder: Unexpected OOB");
|
||||
return result.value();
|
||||
}
|
||||
|
||||
class ArithmeticIntegerIDDecoder {
|
||||
public:
|
||||
ArithmeticIntegerIDDecoder(ArithmeticDecoder&, u32 code_length);
|
||||
|
@ -1200,8 +1211,8 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
// If SBHUFF is 0, decode a value using the IADT integer arithmetic decoding procedure (see Annex A) and multiply the resulting value by SBSTRIPS."
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder delta_t_integer_decoder(decoder);
|
||||
auto read_delta_t = [&]() -> i32 {
|
||||
return delta_t_integer_decoder.decode().value() * inputs.size_of_symbol_instance_strips;
|
||||
auto read_delta_t = [&]() -> ErrorOr<i32> {
|
||||
return TRY(delta_t_integer_decoder.decode_non_oob()) * inputs.size_of_symbol_instance_strips;
|
||||
};
|
||||
|
||||
// 6.4.7 First symbol instance S coordinate
|
||||
|
@ -1209,8 +1220,8 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
// If SBHUFF is 0, decode a value using the IAFS integer arithmetic decoding procedure (see Annex A)."
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder first_s_integer_decoder(decoder);
|
||||
auto read_first_s = [&]() -> i32 {
|
||||
return first_s_integer_decoder.decode().value();
|
||||
auto read_first_s = [&]() -> ErrorOr<i32> {
|
||||
return first_s_integer_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.4.8 Subsequent symbol instance S coordinate
|
||||
|
@ -1229,10 +1240,10 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
// • If SBHUFF is 0, decode a value using the IAIT integer arithmetic decoding procedure (see Annex A)."
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder instance_t_integer_decoder(decoder);
|
||||
auto read_instance_t = [&]() -> i32 {
|
||||
auto read_instance_t = [&]() -> ErrorOr<i32> {
|
||||
if (inputs.size_of_symbol_instance_strips == 1)
|
||||
return 0;
|
||||
return instance_t_integer_decoder.decode().value();
|
||||
return instance_t_integer_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.4.10 Symbol instance symbol ID
|
||||
|
@ -1246,29 +1257,29 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
// 6.4.11.1 Symbol instance refinement delta width
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder refinement_delta_width_decoder(decoder);
|
||||
auto read_refinement_delta_width = [&]() -> i32 {
|
||||
return refinement_delta_width_decoder.decode().value();
|
||||
auto read_refinement_delta_width = [&]() -> ErrorOr<i32> {
|
||||
return refinement_delta_width_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.4.11.2 Symbol instance refinement delta width
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder refinement_delta_height_decoder(decoder);
|
||||
auto read_refinement_delta_height = [&]() -> i32 {
|
||||
return refinement_delta_height_decoder.decode().value();
|
||||
auto read_refinement_delta_height = [&]() -> ErrorOr<i32> {
|
||||
return refinement_delta_height_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.4.11.3 Symbol instance refinement X offset
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder refinement_x_offset_decoder(decoder);
|
||||
auto read_refinement_x_offset = [&]() -> i32 {
|
||||
return refinement_x_offset_decoder.decode().value();
|
||||
auto read_refinement_x_offset = [&]() -> ErrorOr<i32> {
|
||||
return refinement_x_offset_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.4.11.4 Symbol instance refinement Y offset
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder refinement_y_offset_decoder(decoder);
|
||||
auto read_refinement_y_offset = [&]() -> i32 {
|
||||
return refinement_y_offset_decoder.decode().value();
|
||||
auto read_refinement_y_offset = [&]() -> ErrorOr<i32> {
|
||||
return refinement_y_offset_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.4.11 Symbol instance bitmap
|
||||
|
@ -1287,16 +1298,16 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
// "• If SBHUFF is 1, then read one bit and set RI to the value of that bit.
|
||||
// • If SBHUFF is 0, then decode one bit using the IARI integer arithmetic decoding procedure and set RI to the value of that bit."
|
||||
// FIXME: Implement support for SBHUFF = 1.
|
||||
has_refinement_image = has_refinement_image_decoder.decode().value();
|
||||
has_refinement_image = TRY(has_refinement_image_decoder.decode_non_oob());
|
||||
}
|
||||
|
||||
if (!has_refinement_image)
|
||||
return &symbol;
|
||||
|
||||
auto refinement_delta_width = read_refinement_delta_width();
|
||||
auto refinement_delta_height = read_refinement_delta_height();
|
||||
auto refinement_x_offset = read_refinement_x_offset();
|
||||
auto refinement_y_offset = read_refinement_y_offset();
|
||||
auto refinement_delta_width = TRY(read_refinement_delta_width());
|
||||
auto refinement_delta_height = TRY(read_refinement_delta_height());
|
||||
auto refinement_x_offset = TRY(read_refinement_x_offset());
|
||||
auto refinement_y_offset = TRY(read_refinement_y_offset());
|
||||
// FIXME: This is missing some steps needed for the SBHUFF = 1 case.
|
||||
|
||||
dbgln_if(JBIG2_DEBUG, "refinement delta width: {}, refinement delta height: {}, refinement x offset: {}, refinement y offset: {}", refinement_delta_width, refinement_delta_height, refinement_x_offset, refinement_y_offset);
|
||||
|
@ -1325,7 +1336,7 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
|
||||
// "2) Decode the initial STRIPT value as described in 6.4.6. Negate the decoded value and assign this negated value to the variable STRIPT.
|
||||
// Assign the value 0 to FIRSTS. Assign the value 0 to NINSTANCES."
|
||||
i32 strip_t = -read_delta_t();
|
||||
i32 strip_t = -TRY(read_delta_t());
|
||||
i32 first_s = 0;
|
||||
u32 n_instances = 0;
|
||||
|
||||
|
@ -1339,7 +1350,7 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
while (n_instances < inputs.number_of_instances) {
|
||||
// "b) Decode the strip's delta T value as described in 6.4.6. Let DT be the decoded value. Set:
|
||||
// STRIPT = STRIPT + DT"
|
||||
i32 delta_t = read_delta_t();
|
||||
i32 delta_t = TRY(read_delta_t());
|
||||
strip_t += delta_t;
|
||||
|
||||
i32 cur_s;
|
||||
|
@ -1357,7 +1368,7 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
// CURS = CURS + IDS + SBDSOFFSET"
|
||||
// Implementor's note: The spec means "proceed to step 4 d)" in 4c ii).
|
||||
if (is_first_symbol) {
|
||||
i32 delta_first_s = read_first_s();
|
||||
i32 delta_first_s = TRY(read_first_s());
|
||||
first_s += delta_first_s;
|
||||
cur_s = first_s;
|
||||
is_first_symbol = false;
|
||||
|
@ -1371,7 +1382,7 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> text_region_decoding_procedure(TextRegi
|
|||
|
||||
// "iii) Decode the symbol instance's T coordinate as described in 6.4.9. Let CURT be the decoded value. Set:
|
||||
// TI = STRIPT + CURT"
|
||||
i32 cur_t = read_instance_t();
|
||||
i32 cur_t = TRY(read_instance_t());
|
||||
i32 t_instance = strip_t + cur_t;
|
||||
|
||||
// "iv) Decode the symbol instance's symbol ID as described in 6.4.10. Let IDI be the decoded value."
|
||||
|
@ -1508,9 +1519,8 @@ static ErrorOr<Vector<NonnullRefPtr<Symbol>>> symbol_dictionary_decoding_procedu
|
|||
// If SDHUFF is 0, decode a value using the IADH integer arithmetic decoding procedure (see Annex A)."
|
||||
// FIXME: Implement support for SDHUFF = 1.
|
||||
JBIG2::ArithmeticIntegerDecoder delta_height_integer_decoder(decoder);
|
||||
auto read_delta_height = [&]() -> i32 {
|
||||
// No OOB values for delta height.
|
||||
return delta_height_integer_decoder.decode().value();
|
||||
auto read_delta_height = [&]() -> ErrorOr<i32> {
|
||||
return delta_height_integer_decoder.decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.5.7 Delta width
|
||||
|
@ -1532,10 +1542,10 @@ static ErrorOr<Vector<NonnullRefPtr<Symbol>>> symbol_dictionary_decoding_procedu
|
|||
// If SDHUFF is 0, decode a value using the IAAI integer arithmetic decoding procedure (see Annex A).
|
||||
// FIXME: Implement support for SDHUFF = 1.
|
||||
Optional<JBIG2::ArithmeticIntegerDecoder> number_of_symbol_instances_decoder;
|
||||
auto read_number_of_symbol_instances = [&]() -> i32 {
|
||||
auto read_number_of_symbol_instances = [&]() -> ErrorOr<i32> {
|
||||
if (!number_of_symbol_instances_decoder.has_value())
|
||||
number_of_symbol_instances_decoder = JBIG2::ArithmeticIntegerDecoder(decoder);
|
||||
return number_of_symbol_instances_decoder->decode().value();
|
||||
return number_of_symbol_instances_decoder->decode_non_oob();
|
||||
};
|
||||
|
||||
// 6.5.8.1 Direct-coded symbol bitmap
|
||||
|
@ -1569,7 +1579,7 @@ static ErrorOr<Vector<NonnullRefPtr<Symbol>>> symbol_dictionary_decoding_procedu
|
|||
|
||||
// 6.5.8.2 Refinement/aggregate-coded symbol bitmap
|
||||
// "1) Decode the number of symbol instances contained in the aggregation, as specified in 6.5.8.2.1. Let REFAGGNINST be the value decoded."
|
||||
auto number_of_symbol_instances = read_number_of_symbol_instances(); // "REFAGGNINST" in spec.
|
||||
auto number_of_symbol_instances = TRY(read_number_of_symbol_instances()); // "REFAGGNINST" in spec.
|
||||
dbgln_if(JBIG2_DEBUG, "Number of symbol instances: {}", number_of_symbol_instances);
|
||||
|
||||
if (number_of_symbol_instances > 1) {
|
||||
|
@ -1595,11 +1605,11 @@ static ErrorOr<Vector<NonnullRefPtr<Symbol>>> symbol_dictionary_decoding_procedu
|
|||
|
||||
if (!refinement_x_offset_decoder.has_value())
|
||||
refinement_x_offset_decoder = JBIG2::ArithmeticIntegerDecoder(decoder);
|
||||
i32 refinement_x_offset = refinement_x_offset_decoder->decode().value();
|
||||
i32 refinement_x_offset = TRY(refinement_x_offset_decoder->decode_non_oob());
|
||||
|
||||
if (!refinement_y_offset_decoder.has_value())
|
||||
refinement_y_offset_decoder = JBIG2::ArithmeticIntegerDecoder(decoder);
|
||||
i32 refinement_y_offset = refinement_y_offset_decoder->decode().value();
|
||||
i32 refinement_y_offset = TRY(refinement_y_offset_decoder->decode_non_oob());
|
||||
|
||||
if (symbol_id >= inputs.input_symbols.size() && symbol_id - inputs.input_symbols.size() >= new_symbols.size())
|
||||
return Error::from_string_literal("JBIG2ImageDecoderPlugin: Refinement/aggregate symbol ID out of range");
|
||||
|
@ -1641,7 +1651,7 @@ static ErrorOr<Vector<NonnullRefPtr<Symbol>>> symbol_dictionary_decoding_procedu
|
|||
// SYMWIDTH = 0
|
||||
// TOTWIDTH = 0
|
||||
// HCFIRSTSYM = NSYMSDECODED"
|
||||
i32 delta_height = read_delta_height();
|
||||
i32 delta_height = TRY(read_delta_height());
|
||||
height_class_height += delta_height;
|
||||
u32 symbol_width = 0;
|
||||
u32 total_width = 0;
|
||||
|
@ -1703,7 +1713,7 @@ static ErrorOr<Vector<NonnullRefPtr<Symbol>>> symbol_dictionary_decoding_procedu
|
|||
// "2) Decode a value using Table B.1 if SDHUFF is 1, or the IAEX integer arithmetic decoding procedure if
|
||||
// SDHUFF is 0. Let EXRUNLENGTH be the decoded value."
|
||||
// FIXME: Implement support for SDHUFF = 1.
|
||||
i32 export_run_length = export_integer_decoder.decode().value(); // No OOB value.
|
||||
i32 export_run_length = TRY(export_integer_decoder.decode_non_oob());
|
||||
|
||||
// "3) Set EXFLAGS[EXINDEX] through EXFLAGS[EXINDEX + EXRUNLENGTH – 1] to CUREXFLAG.
|
||||
// If EXRUNLENGTH = 0, then this step does not change any values."
|
||||
|
|
Loading…
Reference in a new issue