فهرست منبع

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.
Nico Weber 1 سال پیش
والد
کامیت
a2a5fc76aa
1فایلهای تغییر یافته به همراه43 افزوده شده و 33 حذف شده
  1. 43 33
      Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp

+ 43 - 33
Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp

@@ -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."