tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

error_handling_test.cc (41832B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include <cstddef>
      7 #include <cstdint>
      8 #include <cstdlib>
      9 #include <cstring>
     10 #include <vector>
     11 
     12 #include "lib/jpegli/common.h"
     13 #include "lib/jpegli/decode.h"
     14 #include "lib/jpegli/encode.h"
     15 #include "lib/jpegli/libjpeg_test_util.h"
     16 #include "lib/jpegli/test_params.h"
     17 #include "lib/jpegli/test_utils.h"
     18 #include "lib/jpegli/testing.h"
     19 
     20 namespace jpegli {
     21 namespace {
     22 
     23 TEST(EncoderErrorHandlingTest, MinimalSuccess) {
     24  uint8_t* buffer = nullptr;
     25  unsigned long buffer_size = 0;  // NOLINT
     26  {
     27    jpeg_compress_struct cinfo;
     28    const auto try_catch_block = [&]() -> bool {
     29      ERROR_HANDLER_SETUP(jpegli);
     30      jpegli_create_compress(&cinfo);
     31      jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
     32      cinfo.image_width = 1;
     33      cinfo.image_height = 1;
     34      cinfo.input_components = 1;
     35      jpegli_set_defaults(&cinfo);
     36      jpegli_start_compress(&cinfo, TRUE);
     37      JSAMPLE image[1] = {0};
     38      JSAMPROW row[] = {image};
     39      jpegli_write_scanlines(&cinfo, row, 1);
     40      jpegli_finish_compress(&cinfo);
     41      return true;
     42    };
     43    EXPECT_TRUE(try_catch_block());
     44    jpegli_destroy_compress(&cinfo);
     45  }
     46  TestImage output;
     47  DecodeWithLibjpeg(CompressParams(), DecompressParams(), nullptr, 0, buffer,
     48                    buffer_size, &output);
     49  EXPECT_EQ(1, output.xsize);
     50  EXPECT_EQ(1, output.ysize);
     51  EXPECT_EQ(1, output.components);
     52  EXPECT_EQ(0, output.pixels[0]);
     53  if (buffer) free(buffer);
     54 }
     55 
     56 TEST(EncoderErrorHandlingTest, NoDestination) {
     57  jpeg_compress_struct cinfo;
     58  const auto try_catch_block = [&]() -> bool {
     59    ERROR_HANDLER_SETUP(jpegli);
     60    jpegli_create_compress(&cinfo);
     61    cinfo.image_width = 1;
     62    cinfo.image_height = 1;
     63    cinfo.input_components = 1;
     64    jpegli_set_defaults(&cinfo);
     65    jpegli_start_compress(&cinfo, TRUE);
     66    return true;
     67  };
     68  EXPECT_FALSE(try_catch_block());
     69  jpegli_destroy_compress(&cinfo);
     70 }
     71 
     72 TEST(EncoderErrorHandlingTest, NoImageDimensions) {
     73  uint8_t* buffer = nullptr;
     74  unsigned long buffer_size = 0;  // NOLINT
     75  jpeg_compress_struct cinfo;
     76  const auto try_catch_block = [&]() -> bool {
     77    ERROR_HANDLER_SETUP(jpegli);
     78    jpegli_create_compress(&cinfo);
     79    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
     80    cinfo.input_components = 1;
     81    jpegli_set_defaults(&cinfo);
     82    jpegli_start_compress(&cinfo, TRUE);
     83    return true;
     84  };
     85  EXPECT_FALSE(try_catch_block());
     86  jpegli_destroy_compress(&cinfo);
     87  if (buffer) free(buffer);
     88 }
     89 
     90 TEST(EncoderErrorHandlingTest, ImageTooBig) {
     91  uint8_t* buffer = nullptr;
     92  unsigned long buffer_size = 0;  // NOLINT
     93  jpeg_compress_struct cinfo;
     94  const auto try_catch_block = [&]() -> bool {
     95    ERROR_HANDLER_SETUP(jpegli);
     96    jpegli_create_compress(&cinfo);
     97    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
     98    cinfo.image_width = 100000;
     99    cinfo.image_height = 1;
    100    cinfo.input_components = 1;
    101    jpegli_set_defaults(&cinfo);
    102    jpegli_start_compress(&cinfo, TRUE);
    103    return true;
    104  };
    105  EXPECT_FALSE(try_catch_block());
    106  jpegli_destroy_compress(&cinfo);
    107  if (buffer) free(buffer);
    108 }
    109 
    110 TEST(EncoderErrorHandlingTest, NoInputComponents) {
    111  uint8_t* buffer = nullptr;
    112  unsigned long buffer_size = 0;  // NOLINT
    113  jpeg_compress_struct cinfo;
    114  const auto try_catch_block = [&]() -> bool {
    115    ERROR_HANDLER_SETUP(jpegli);
    116    jpegli_create_compress(&cinfo);
    117    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    118    cinfo.image_width = 1;
    119    cinfo.image_height = 1;
    120    jpegli_set_defaults(&cinfo);
    121    jpegli_start_compress(&cinfo, TRUE);
    122    return true;
    123  };
    124  EXPECT_FALSE(try_catch_block());
    125  jpegli_destroy_compress(&cinfo);
    126  if (buffer) free(buffer);
    127 }
    128 
    129 TEST(EncoderErrorHandlingTest, TooManyInputComponents) {
    130  uint8_t* buffer = nullptr;
    131  unsigned long buffer_size = 0;  // NOLINT
    132  jpeg_compress_struct cinfo;
    133  const auto try_catch_block = [&]() -> bool {
    134    ERROR_HANDLER_SETUP(jpegli);
    135    jpegli_create_compress(&cinfo);
    136    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    137    cinfo.image_width = 1;
    138    cinfo.image_height = 1;
    139    cinfo.input_components = 1000;
    140    jpegli_set_defaults(&cinfo);
    141    jpegli_start_compress(&cinfo, TRUE);
    142    return true;
    143  };
    144  EXPECT_FALSE(try_catch_block());
    145  jpegli_destroy_compress(&cinfo);
    146  if (buffer) free(buffer);
    147 }
    148 
    149 TEST(EncoderErrorHandlingTest, NoSetDefaults) {
    150  uint8_t* buffer = nullptr;
    151  unsigned long buffer_size = 0;  // NOLINT
    152  jpeg_compress_struct cinfo;
    153  const auto try_catch_block = [&]() -> bool {
    154    ERROR_HANDLER_SETUP(jpegli);
    155    jpegli_create_compress(&cinfo);
    156    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    157    cinfo.image_width = 1;
    158    cinfo.image_height = 1;
    159    cinfo.input_components = 1;
    160    jpegli_start_compress(&cinfo, TRUE);
    161    JSAMPLE image[1] = {0};
    162    JSAMPROW row[] = {image};
    163    jpegli_write_scanlines(&cinfo, row, 1);
    164    jpegli_finish_compress(&cinfo);
    165    return true;
    166  };
    167  EXPECT_FALSE(try_catch_block());
    168  jpegli_destroy_compress(&cinfo);
    169  if (buffer) free(buffer);
    170 }
    171 
    172 TEST(EncoderErrorHandlingTest, NoStartCompress) {
    173  uint8_t* buffer = nullptr;
    174  unsigned long buffer_size = 0;  // NOLINT
    175  jpeg_compress_struct cinfo;
    176  const auto try_catch_block = [&]() -> bool {
    177    ERROR_HANDLER_SETUP(jpegli);
    178    jpegli_create_compress(&cinfo);
    179    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    180    cinfo.image_width = 1;
    181    cinfo.image_height = 1;
    182    cinfo.input_components = 1;
    183    jpegli_set_defaults(&cinfo);
    184    JSAMPLE image[1] = {0};
    185    JSAMPROW row[] = {image};
    186    jpegli_write_scanlines(&cinfo, row, 1);
    187    return true;
    188  };
    189  EXPECT_FALSE(try_catch_block());
    190  jpegli_destroy_compress(&cinfo);
    191  if (buffer) free(buffer);
    192 }
    193 
    194 TEST(EncoderErrorHandlingTest, NoWriteScanlines) {
    195  uint8_t* buffer = nullptr;
    196  unsigned long buffer_size = 0;  // NOLINT
    197  jpeg_compress_struct cinfo;
    198  const auto try_catch_block = [&]() -> bool {
    199    ERROR_HANDLER_SETUP(jpegli);
    200    jpegli_create_compress(&cinfo);
    201    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    202    cinfo.image_width = 1;
    203    cinfo.image_height = 1;
    204    cinfo.input_components = 1;
    205    jpegli_set_defaults(&cinfo);
    206    jpegli_start_compress(&cinfo, TRUE);
    207    jpegli_finish_compress(&cinfo);
    208    return true;
    209  };
    210  EXPECT_FALSE(try_catch_block());
    211  jpegli_destroy_compress(&cinfo);
    212  if (buffer) free(buffer);
    213 }
    214 
    215 TEST(EncoderErrorHandlingTest, NoWriteAllScanlines) {
    216  uint8_t* buffer = nullptr;
    217  unsigned long buffer_size = 0;  // NOLINT
    218  jpeg_compress_struct cinfo;
    219  const auto try_catch_block = [&]() -> bool {
    220    ERROR_HANDLER_SETUP(jpegli);
    221    jpegli_create_compress(&cinfo);
    222    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    223    cinfo.image_width = 1;
    224    cinfo.image_height = 2;
    225    cinfo.input_components = 1;
    226    jpegli_set_defaults(&cinfo);
    227    jpegli_start_compress(&cinfo, TRUE);
    228    JSAMPLE image[1] = {0};
    229    JSAMPROW row[] = {image};
    230    jpegli_write_scanlines(&cinfo, row, 1);
    231    jpegli_finish_compress(&cinfo);
    232    return true;
    233  };
    234  EXPECT_FALSE(try_catch_block());
    235  jpegli_destroy_compress(&cinfo);
    236  if (buffer) free(buffer);
    237 }
    238 
    239 TEST(EncoderErrorHandlingTest, InvalidQuantValue) {
    240  uint8_t* buffer = nullptr;
    241  unsigned long buffer_size = 0;  // NOLINT
    242  jpeg_compress_struct cinfo;
    243  const auto try_catch_block = [&]() -> bool {
    244    ERROR_HANDLER_SETUP(jpegli);
    245    jpegli_create_compress(&cinfo);
    246    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    247    cinfo.image_width = 1;
    248    cinfo.image_height = 1;
    249    cinfo.input_components = 1;
    250    jpegli_set_defaults(&cinfo);
    251    cinfo.quant_tbl_ptrs[0] =
    252        jpegli_alloc_quant_table(reinterpret_cast<j_common_ptr>(&cinfo));
    253    for (UINT16& q : cinfo.quant_tbl_ptrs[0]->quantval) {
    254      q = 0;
    255    }
    256    jpegli_start_compress(&cinfo, TRUE);
    257    JSAMPLE image[1] = {0};
    258    JSAMPROW row[] = {image};
    259    jpegli_write_scanlines(&cinfo, row, 1);
    260    jpegli_finish_compress(&cinfo);
    261    return true;
    262  };
    263  EXPECT_FALSE(try_catch_block());
    264  jpegli_destroy_compress(&cinfo);
    265  if (buffer) free(buffer);
    266 }
    267 
    268 TEST(EncoderErrorHandlingTest, InvalidQuantTableIndex) {
    269  uint8_t* buffer = nullptr;
    270  unsigned long buffer_size = 0;  // NOLINT
    271  jpeg_compress_struct cinfo;
    272  const auto try_catch_block = [&]() -> bool {
    273    ERROR_HANDLER_SETUP(jpegli);
    274    jpegli_create_compress(&cinfo);
    275    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    276    cinfo.image_width = 1;
    277    cinfo.image_height = 1;
    278    cinfo.input_components = 1;
    279    jpegli_set_defaults(&cinfo);
    280    cinfo.comp_info[0].quant_tbl_no = 3;
    281    jpegli_start_compress(&cinfo, TRUE);
    282    JSAMPLE image[1] = {0};
    283    JSAMPROW row[] = {image};
    284    jpegli_write_scanlines(&cinfo, row, 1);
    285    jpegli_finish_compress(&cinfo);
    286    return true;
    287  };
    288  EXPECT_FALSE(try_catch_block());
    289  jpegli_destroy_compress(&cinfo);
    290  if (buffer) free(buffer);
    291 }
    292 
    293 TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch1) {
    294  uint8_t* buffer = nullptr;
    295  unsigned long buffer_size = 0;  // NOLINT
    296  jpeg_compress_struct cinfo;
    297  const auto try_catch_block = [&]() -> bool {
    298    ERROR_HANDLER_SETUP(jpegli);
    299    jpegli_create_compress(&cinfo);
    300    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    301    cinfo.image_width = 1;
    302    cinfo.image_height = 1;
    303    cinfo.input_components = 1;
    304    jpegli_set_defaults(&cinfo);
    305    cinfo.num_components = 100;
    306    jpegli_start_compress(&cinfo, TRUE);
    307    return true;
    308  };
    309  EXPECT_FALSE(try_catch_block());
    310  jpegli_destroy_compress(&cinfo);
    311  if (buffer) free(buffer);
    312 }
    313 
    314 TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch2) {
    315  uint8_t* buffer = nullptr;
    316  unsigned long buffer_size = 0;  // NOLINT
    317  jpeg_compress_struct cinfo;
    318  const auto try_catch_block = [&]() -> bool {
    319    ERROR_HANDLER_SETUP(jpegli);
    320    jpegli_create_compress(&cinfo);
    321    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    322    cinfo.image_width = 1;
    323    cinfo.image_height = 1;
    324    cinfo.input_components = 1;
    325    jpegli_set_defaults(&cinfo);
    326    cinfo.num_components = 2;
    327    jpegli_start_compress(&cinfo, TRUE);
    328    return true;
    329  };
    330  EXPECT_FALSE(try_catch_block());
    331  jpegli_destroy_compress(&cinfo);
    332  if (buffer) free(buffer);
    333 }
    334 
    335 TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch3) {
    336  uint8_t* buffer = nullptr;
    337  unsigned long buffer_size = 0;  // NOLINT
    338  jpeg_compress_struct cinfo;
    339  const auto try_catch_block = [&]() -> bool {
    340    ERROR_HANDLER_SETUP(jpegli);
    341    jpegli_create_compress(&cinfo);
    342    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    343    cinfo.image_width = 1;
    344    cinfo.image_height = 1;
    345    cinfo.input_components = 1;
    346    jpegli_set_defaults(&cinfo);
    347    cinfo.num_components = 2;
    348    cinfo.comp_info[1].h_samp_factor = cinfo.comp_info[1].v_samp_factor = 1;
    349    jpegli_start_compress(&cinfo, TRUE);
    350    JSAMPLE image[1] = {0};
    351    JSAMPROW row[] = {image};
    352    jpegli_write_scanlines(&cinfo, row, 1);
    353    jpegli_finish_compress(&cinfo);
    354    return true;
    355  };
    356  EXPECT_FALSE(try_catch_block());
    357  jpegli_destroy_compress(&cinfo);
    358  if (buffer) free(buffer);
    359 }
    360 
    361 TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch4) {
    362  uint8_t* buffer = nullptr;
    363  unsigned long buffer_size = 0;  // NOLINT
    364  jpeg_compress_struct cinfo;
    365  const auto try_catch_block = [&]() -> bool {
    366    ERROR_HANDLER_SETUP(jpegli);
    367    jpegli_create_compress(&cinfo);
    368    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    369    cinfo.image_width = 1;
    370    cinfo.image_height = 1;
    371    cinfo.input_components = 1;
    372    cinfo.in_color_space = JCS_RGB;
    373    jpegli_set_defaults(&cinfo);
    374    jpegli_start_compress(&cinfo, TRUE);
    375    JSAMPLE image[1] = {0};
    376    JSAMPROW row[] = {image};
    377    jpegli_write_scanlines(&cinfo, row, 1);
    378    jpegli_finish_compress(&cinfo);
    379    return true;
    380  };
    381  EXPECT_FALSE(try_catch_block());
    382  jpegli_destroy_compress(&cinfo);
    383  if (buffer) free(buffer);
    384 }
    385 
    386 TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch5) {
    387  uint8_t* buffer = nullptr;
    388  unsigned long buffer_size = 0;  // NOLINT
    389  jpeg_compress_struct cinfo;
    390  const auto try_catch_block = [&]() -> bool {
    391    ERROR_HANDLER_SETUP(jpegli);
    392    jpegli_create_compress(&cinfo);
    393    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    394    cinfo.image_width = 1;
    395    cinfo.image_height = 1;
    396    cinfo.input_components = 3;
    397    cinfo.in_color_space = JCS_GRAYSCALE;
    398    jpegli_set_defaults(&cinfo);
    399    jpegli_start_compress(&cinfo, TRUE);
    400    JSAMPLE image[3] = {0};
    401    JSAMPROW row[] = {image};
    402    jpegli_write_scanlines(&cinfo, row, 1);
    403    jpegli_finish_compress(&cinfo);
    404    return true;
    405  };
    406  EXPECT_FALSE(try_catch_block());
    407  jpegli_destroy_compress(&cinfo);
    408  if (buffer) free(buffer);
    409 }
    410 
    411 TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch6) {
    412  uint8_t* buffer = nullptr;
    413  unsigned long buffer_size = 0;  // NOLINT
    414  jpeg_compress_struct cinfo;
    415  const auto try_catch_block = [&]() -> bool {
    416    ERROR_HANDLER_SETUP(jpegli);
    417    jpegli_create_compress(&cinfo);
    418    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    419    cinfo.image_width = 1;
    420    cinfo.image_height = 1;
    421    cinfo.input_components = 3;
    422    cinfo.in_color_space = JCS_RGB;
    423    jpegli_set_defaults(&cinfo);
    424    cinfo.num_components = 2;
    425    jpegli_start_compress(&cinfo, TRUE);
    426    JSAMPLE image[3] = {0};
    427    JSAMPROW row[] = {image};
    428    jpegli_write_scanlines(&cinfo, row, 1);
    429    jpegli_finish_compress(&cinfo);
    430    return true;
    431  };
    432  EXPECT_FALSE(try_catch_block());
    433  jpegli_destroy_compress(&cinfo);
    434  if (buffer) free(buffer);
    435 }
    436 
    437 TEST(EncoderErrorHandlingTest, InvalidColorTransform) {
    438  uint8_t* buffer = nullptr;
    439  unsigned long buffer_size = 0;  // NOLINT
    440  jpeg_compress_struct cinfo;
    441  const auto try_catch_block = [&]() -> bool {
    442    ERROR_HANDLER_SETUP(jpegli);
    443    jpegli_create_compress(&cinfo);
    444    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    445    cinfo.image_width = 1;
    446    cinfo.image_height = 1;
    447    cinfo.input_components = 3;
    448    cinfo.in_color_space = JCS_YCbCr;
    449    jpegli_set_defaults(&cinfo);
    450    cinfo.jpeg_color_space = JCS_RGB;
    451    jpegli_start_compress(&cinfo, TRUE);
    452    JSAMPLE image[3] = {0};
    453    JSAMPROW row[] = {image};
    454    jpegli_write_scanlines(&cinfo, row, 1);
    455    jpegli_finish_compress(&cinfo);
    456    return true;
    457  };
    458  EXPECT_FALSE(try_catch_block());
    459  jpegli_destroy_compress(&cinfo);
    460  if (buffer) free(buffer);
    461 }
    462 
    463 TEST(EncoderErrorHandlingTest, DuplicateComponentIds) {
    464  uint8_t* buffer = nullptr;
    465  unsigned long buffer_size = 0;  // NOLINT
    466  jpeg_compress_struct cinfo;
    467  const auto try_catch_block = [&]() -> bool {
    468    ERROR_HANDLER_SETUP(jpegli);
    469    jpegli_create_compress(&cinfo);
    470    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    471    cinfo.image_width = 1;
    472    cinfo.image_height = 1;
    473    cinfo.input_components = 3;
    474    jpegli_set_defaults(&cinfo);
    475    cinfo.comp_info[0].component_id = 0;
    476    cinfo.comp_info[1].component_id = 0;
    477    jpegli_start_compress(&cinfo, TRUE);
    478    return true;
    479  };
    480  EXPECT_FALSE(try_catch_block());
    481  jpegli_destroy_compress(&cinfo);
    482  if (buffer) free(buffer);
    483 }
    484 
    485 TEST(EncoderErrorHandlingTest, InvalidComponentIndex) {
    486  uint8_t* buffer = nullptr;
    487  unsigned long buffer_size = 0;  // NOLINT
    488  jpeg_compress_struct cinfo;
    489  const auto try_catch_block = [&]() -> bool {
    490    ERROR_HANDLER_SETUP(jpegli);
    491    jpegli_create_compress(&cinfo);
    492    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    493    cinfo.image_width = 1;
    494    cinfo.image_height = 1;
    495    cinfo.input_components = 3;
    496    jpegli_set_defaults(&cinfo);
    497    cinfo.comp_info[0].component_index = 17;
    498    jpegli_start_compress(&cinfo, TRUE);
    499    return true;
    500  };
    501  EXPECT_FALSE(try_catch_block());
    502  jpegli_destroy_compress(&cinfo);
    503  if (buffer) free(buffer);
    504 }
    505 
    506 TEST(EncoderErrorHandlingTest, ArithmeticCoding) {
    507  uint8_t* buffer = nullptr;
    508  unsigned long buffer_size = 0;  // NOLINT
    509  jpeg_compress_struct cinfo;
    510  const auto try_catch_block = [&]() -> bool {
    511    ERROR_HANDLER_SETUP(jpegli);
    512    jpegli_create_compress(&cinfo);
    513    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    514    cinfo.image_width = 1;
    515    cinfo.image_height = 1;
    516    cinfo.input_components = 3;
    517    jpegli_set_defaults(&cinfo);
    518    cinfo.arith_code = TRUE;
    519    jpegli_start_compress(&cinfo, TRUE);
    520    return true;
    521  };
    522  EXPECT_FALSE(try_catch_block());
    523  jpegli_destroy_compress(&cinfo);
    524  if (buffer) free(buffer);
    525 }
    526 
    527 TEST(EncoderErrorHandlingTest, CCIR601Sampling) {
    528  uint8_t* buffer = nullptr;
    529  unsigned long buffer_size = 0;  // NOLINT
    530  jpeg_compress_struct cinfo;
    531  const auto try_catch_block = [&]() -> bool {
    532    ERROR_HANDLER_SETUP(jpegli);
    533    jpegli_create_compress(&cinfo);
    534    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    535    cinfo.image_width = 1;
    536    cinfo.image_height = 1;
    537    cinfo.input_components = 3;
    538    jpegli_set_defaults(&cinfo);
    539    cinfo.CCIR601_sampling = TRUE;
    540    jpegli_start_compress(&cinfo, TRUE);
    541    return true;
    542  };
    543  EXPECT_FALSE(try_catch_block());
    544  jpegli_destroy_compress(&cinfo);
    545  if (buffer) free(buffer);
    546 }
    547 
    548 TEST(EncoderErrorHandlingTest, InvalidScanScript1) {
    549  uint8_t* buffer = nullptr;
    550  unsigned long buffer_size = 0;  // NOLINT
    551  jpeg_compress_struct cinfo;
    552  const auto try_catch_block = [&]() -> bool {
    553    ERROR_HANDLER_SETUP(jpegli);
    554    jpegli_create_compress(&cinfo);
    555    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    556    cinfo.image_width = 1;
    557    cinfo.image_height = 1;
    558    cinfo.input_components = 1;
    559    jpegli_set_defaults(&cinfo);
    560    static constexpr jpeg_scan_info kScript[] = {{1, {0}, 0, 63, 0, 0}};  //
    561    cinfo.scan_info = kScript;
    562    cinfo.num_scans = 0;
    563    jpegli_start_compress(&cinfo, TRUE);
    564    return true;
    565  };
    566  EXPECT_FALSE(try_catch_block());
    567  jpegli_destroy_compress(&cinfo);
    568  if (buffer) free(buffer);
    569 }
    570 
    571 TEST(EncoderErrorHandlingTest, InvalidScanScript2) {
    572  uint8_t* buffer = nullptr;
    573  unsigned long buffer_size = 0;  // NOLINT
    574  jpeg_compress_struct cinfo;
    575  const auto try_catch_block = [&]() -> bool {
    576    ERROR_HANDLER_SETUP(jpegli);
    577    jpegli_create_compress(&cinfo);
    578    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    579    cinfo.image_width = 1;
    580    cinfo.image_height = 1;
    581    cinfo.input_components = 1;
    582    jpegli_set_defaults(&cinfo);
    583    static constexpr jpeg_scan_info kScript[] = {{2, {0, 1}, 0, 63, 0, 0}};  //
    584    cinfo.scan_info = kScript;
    585    cinfo.num_scans = ARRAY_SIZE(kScript);
    586    jpegli_start_compress(&cinfo, TRUE);
    587    return true;
    588  };
    589  EXPECT_FALSE(try_catch_block());
    590  jpegli_destroy_compress(&cinfo);
    591  if (buffer) free(buffer);
    592 }
    593 
    594 TEST(EncoderErrorHandlingTest, InvalidScanScript3) {
    595  uint8_t* buffer = nullptr;
    596  unsigned long buffer_size = 0;  // NOLINT
    597  jpeg_compress_struct cinfo;
    598  const auto try_catch_block = [&]() -> bool {
    599    ERROR_HANDLER_SETUP(jpegli);
    600    jpegli_create_compress(&cinfo);
    601    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    602    cinfo.image_width = 1;
    603    cinfo.image_height = 1;
    604    cinfo.input_components = 1;
    605    jpegli_set_defaults(&cinfo);
    606    static constexpr jpeg_scan_info kScript[] = {{5, {0}, 0, 63, 0, 0}};  //
    607    cinfo.scan_info = kScript;
    608    cinfo.num_scans = ARRAY_SIZE(kScript);
    609    jpegli_start_compress(&cinfo, TRUE);
    610    return true;
    611  };
    612  EXPECT_FALSE(try_catch_block());
    613  jpegli_destroy_compress(&cinfo);
    614  if (buffer) free(buffer);
    615 }
    616 
    617 TEST(EncoderErrorHandlingTest, InvalidScanScript4) {
    618  uint8_t* buffer = nullptr;
    619  unsigned long buffer_size = 0;  // NOLINT
    620  jpeg_compress_struct cinfo;
    621  const auto try_catch_block = [&]() -> bool {
    622    ERROR_HANDLER_SETUP(jpegli);
    623    jpegli_create_compress(&cinfo);
    624    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    625    cinfo.image_width = 1;
    626    cinfo.image_height = 1;
    627    cinfo.input_components = 2;
    628    jpegli_set_defaults(&cinfo);
    629    static constexpr jpeg_scan_info kScript[] = {{2, {0, 0}, 0, 63, 0, 0}};  //
    630    cinfo.scan_info = kScript;
    631    cinfo.num_scans = ARRAY_SIZE(kScript);
    632    jpegli_start_compress(&cinfo, TRUE);
    633    return true;
    634  };
    635  EXPECT_FALSE(try_catch_block());
    636  jpegli_destroy_compress(&cinfo);
    637  if (buffer) free(buffer);
    638 }
    639 
    640 TEST(EncoderErrorHandlingTest, InvalidScanScript5) {
    641  uint8_t* buffer = nullptr;
    642  unsigned long buffer_size = 0;  // NOLINT
    643  jpeg_compress_struct cinfo;
    644  const auto try_catch_block = [&]() -> bool {
    645    ERROR_HANDLER_SETUP(jpegli);
    646    jpegli_create_compress(&cinfo);
    647    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    648    cinfo.image_width = 1;
    649    cinfo.image_height = 1;
    650    cinfo.input_components = 2;
    651    jpegli_set_defaults(&cinfo);
    652    static constexpr jpeg_scan_info kScript[] = {{2, {1, 0}, 0, 63, 0, 0}};  //
    653    cinfo.scan_info = kScript;
    654    cinfo.num_scans = ARRAY_SIZE(kScript);
    655    jpegli_start_compress(&cinfo, TRUE);
    656    return true;
    657  };
    658  EXPECT_FALSE(try_catch_block());
    659  jpegli_destroy_compress(&cinfo);
    660  if (buffer) free(buffer);
    661 }
    662 
    663 TEST(EncoderErrorHandlingTest, InvalidScanScript6) {
    664  uint8_t* buffer = nullptr;
    665  unsigned long buffer_size = 0;  // NOLINT
    666  jpeg_compress_struct cinfo;
    667  const auto try_catch_block = [&]() -> bool {
    668    ERROR_HANDLER_SETUP(jpegli);
    669    jpegli_create_compress(&cinfo);
    670    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    671    cinfo.image_width = 1;
    672    cinfo.image_height = 1;
    673    cinfo.input_components = 1;
    674    jpegli_set_defaults(&cinfo);
    675    static constexpr jpeg_scan_info kScript[] = {{1, {0}, 0, 64, 0, 0}};  //
    676    cinfo.scan_info = kScript;
    677    cinfo.num_scans = ARRAY_SIZE(kScript);
    678    jpegli_start_compress(&cinfo, TRUE);
    679    return true;
    680  };
    681  EXPECT_FALSE(try_catch_block());
    682  jpegli_destroy_compress(&cinfo);
    683  if (buffer) free(buffer);
    684 }
    685 
    686 TEST(EncoderErrorHandlingTest, InvalidScanScript7) {
    687  uint8_t* buffer = nullptr;
    688  unsigned long buffer_size = 0;  // NOLINT
    689  jpeg_compress_struct cinfo;
    690  const auto try_catch_block = [&]() -> bool {
    691    ERROR_HANDLER_SETUP(jpegli);
    692    jpegli_create_compress(&cinfo);
    693    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    694    cinfo.image_width = 1;
    695    cinfo.image_height = 1;
    696    cinfo.input_components = 1;
    697    jpegli_set_defaults(&cinfo);
    698    static constexpr jpeg_scan_info kScript[] = {{1, {0}, 2, 1, 0, 0}};  //
    699    cinfo.scan_info = kScript;
    700    cinfo.num_scans = ARRAY_SIZE(kScript);
    701    jpegli_start_compress(&cinfo, TRUE);
    702    return true;
    703  };
    704  EXPECT_FALSE(try_catch_block());
    705  jpegli_destroy_compress(&cinfo);
    706  if (buffer) free(buffer);
    707 }
    708 
    709 TEST(EncoderErrorHandlingTest, InvalidScanScript8) {
    710  uint8_t* buffer = nullptr;
    711  unsigned long buffer_size = 0;  // NOLINT
    712  jpeg_compress_struct cinfo;
    713  const auto try_catch_block = [&]() -> bool {
    714    ERROR_HANDLER_SETUP(jpegli);
    715    jpegli_create_compress(&cinfo);
    716    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    717    cinfo.image_width = 1;
    718    cinfo.image_height = 1;
    719    cinfo.input_components = 2;
    720    jpegli_set_defaults(&cinfo);
    721    static constexpr jpeg_scan_info kScript[] = {
    722        {1, {0}, 0, 63, 0, 0}, {1, {1}, 0, 0, 0, 0}, {1, {1}, 1, 63, 0, 0}  //
    723    };
    724    cinfo.scan_info = kScript;
    725    cinfo.num_scans = ARRAY_SIZE(kScript);
    726    jpegli_start_compress(&cinfo, TRUE);
    727    return true;
    728  };
    729  EXPECT_FALSE(try_catch_block());
    730  jpegli_destroy_compress(&cinfo);
    731  if (buffer) free(buffer);
    732 }
    733 
    734 TEST(EncoderErrorHandlingTest, InvalidScanScript9) {
    735  uint8_t* buffer = nullptr;
    736  unsigned long buffer_size = 0;  // NOLINT
    737  jpeg_compress_struct cinfo;
    738  const auto try_catch_block = [&]() -> bool {
    739    ERROR_HANDLER_SETUP(jpegli);
    740    jpegli_create_compress(&cinfo);
    741    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    742    cinfo.image_width = 1;
    743    cinfo.image_height = 1;
    744    cinfo.input_components = 1;
    745    jpegli_set_defaults(&cinfo);
    746    static constexpr jpeg_scan_info kScript[] = {
    747        {1, {0}, 0, 1, 0, 0}, {1, {0}, 2, 63, 0, 0},  //
    748    };
    749    cinfo.scan_info = kScript;
    750    cinfo.num_scans = ARRAY_SIZE(kScript);
    751    jpegli_start_compress(&cinfo, TRUE);
    752    return true;
    753  };
    754  EXPECT_FALSE(try_catch_block());
    755  jpegli_destroy_compress(&cinfo);
    756  if (buffer) free(buffer);
    757 }
    758 
    759 TEST(EncoderErrorHandlingTest, InvalidScanScript10) {
    760  uint8_t* buffer = nullptr;
    761  unsigned long buffer_size = 0;  // NOLINT
    762  jpeg_compress_struct cinfo;
    763  const auto try_catch_block = [&]() -> bool {
    764    ERROR_HANDLER_SETUP(jpegli);
    765    jpegli_create_compress(&cinfo);
    766    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    767    cinfo.image_width = 1;
    768    cinfo.image_height = 1;
    769    cinfo.input_components = 2;
    770    jpegli_set_defaults(&cinfo);
    771    static constexpr jpeg_scan_info kScript[] = {
    772        {2, {0, 1}, 0, 0, 0, 0}, {2, {0, 1}, 1, 63, 0, 0}  //
    773    };
    774    cinfo.scan_info = kScript;
    775    cinfo.num_scans = ARRAY_SIZE(kScript);
    776    jpegli_start_compress(&cinfo, TRUE);
    777    return true;
    778  };
    779  EXPECT_FALSE(try_catch_block());
    780  jpegli_destroy_compress(&cinfo);
    781  if (buffer) free(buffer);
    782 }
    783 
    784 TEST(EncoderErrorHandlingTest, InvalidScanScript11) {
    785  uint8_t* buffer = nullptr;
    786  unsigned long buffer_size = 0;  // NOLINT
    787  jpeg_compress_struct cinfo;
    788  const auto try_catch_block = [&]() -> bool {
    789    ERROR_HANDLER_SETUP(jpegli);
    790    jpegli_create_compress(&cinfo);
    791    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    792    cinfo.image_width = 1;
    793    cinfo.image_height = 1;
    794    cinfo.input_components = 1;
    795    jpegli_set_defaults(&cinfo);
    796    static constexpr jpeg_scan_info kScript[] = {
    797        {1, {0}, 1, 63, 0, 0}, {1, {0}, 0, 0, 0, 0}  //
    798    };
    799    cinfo.scan_info = kScript;
    800    cinfo.num_scans = ARRAY_SIZE(kScript);
    801    jpegli_start_compress(&cinfo, TRUE);
    802    return true;
    803  };
    804  EXPECT_FALSE(try_catch_block());
    805  jpegli_destroy_compress(&cinfo);
    806  if (buffer) free(buffer);
    807 }
    808 
    809 TEST(EncoderErrorHandlingTest, InvalidScanScript12) {
    810  uint8_t* buffer = nullptr;
    811  unsigned long buffer_size = 0;  // NOLINT
    812  jpeg_compress_struct cinfo;
    813  const auto try_catch_block = [&]() -> bool {
    814    ERROR_HANDLER_SETUP(jpegli);
    815    jpegli_create_compress(&cinfo);
    816    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    817    cinfo.image_width = 1;
    818    cinfo.image_height = 1;
    819    cinfo.input_components = 1;
    820    jpegli_set_defaults(&cinfo);
    821    static constexpr jpeg_scan_info kScript[] = {
    822        {1, {0}, 0, 0, 10, 1}, {1, {0}, 0, 0, 1, 0}, {1, {0}, 1, 63, 0, 0}  //
    823    };
    824    cinfo.scan_info = kScript;
    825    cinfo.num_scans = ARRAY_SIZE(kScript);
    826    jpegli_start_compress(&cinfo, TRUE);
    827    return true;
    828  };
    829  EXPECT_FALSE(try_catch_block());
    830  jpegli_destroy_compress(&cinfo);
    831  if (buffer) free(buffer);
    832 }
    833 
    834 TEST(EncoderErrorHandlingTest, InvalidScanScript13) {
    835  uint8_t* buffer = nullptr;
    836  unsigned long buffer_size = 0;  // NOLINT
    837  jpeg_compress_struct cinfo;
    838  const auto try_catch_block = [&]() -> bool {
    839    ERROR_HANDLER_SETUP(jpegli);
    840    jpegli_create_compress(&cinfo);
    841    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    842    cinfo.image_width = 1;
    843    cinfo.image_height = 1;
    844    cinfo.input_components = 1;
    845    jpegli_set_defaults(&cinfo);
    846    static constexpr jpeg_scan_info kScript[] = {
    847        {1, {0}, 0, 0, 0, 2},
    848        {1, {0}, 0, 0, 1, 0},
    849        {1, {0}, 0, 0, 2, 1},  //
    850        {1, {0}, 1, 63, 0, 0}  //
    851    };
    852    cinfo.scan_info = kScript;
    853    cinfo.num_scans = ARRAY_SIZE(kScript);
    854    jpegli_start_compress(&cinfo, TRUE);
    855    return true;
    856  };
    857  EXPECT_FALSE(try_catch_block());
    858  jpegli_destroy_compress(&cinfo);
    859  if (buffer) free(buffer);
    860 }
    861 
    862 TEST(EncoderErrorHandlingTest, MCUSizeTooBig) {
    863  uint8_t* buffer = nullptr;
    864  unsigned long buffer_size = 0;  // NOLINT
    865  jpeg_compress_struct cinfo;
    866  const auto try_catch_block = [&]() -> bool {
    867    ERROR_HANDLER_SETUP(jpegli);
    868    jpegli_create_compress(&cinfo);
    869    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    870    cinfo.image_width = 1;
    871    cinfo.image_height = 1;
    872    cinfo.input_components = 3;
    873    jpegli_set_defaults(&cinfo);
    874    jpegli_set_progressive_level(&cinfo, 0);
    875    cinfo.comp_info[0].h_samp_factor = 3;
    876    cinfo.comp_info[0].v_samp_factor = 3;
    877    jpegli_start_compress(&cinfo, TRUE);
    878    return true;
    879  };
    880  EXPECT_FALSE(try_catch_block());
    881  jpegli_destroy_compress(&cinfo);
    882  if (buffer) free(buffer);
    883 }
    884 
    885 TEST(EncoderErrorHandlingTest, RestartIntervalTooBig) {
    886  uint8_t* buffer = nullptr;
    887  unsigned long buffer_size = 0;  // NOLINT
    888  jpeg_compress_struct cinfo;
    889  const auto try_catch_block = [&]() -> bool {
    890    ERROR_HANDLER_SETUP(jpegli);
    891    jpegli_create_compress(&cinfo);
    892    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    893    cinfo.image_width = 1;
    894    cinfo.image_height = 1;
    895    cinfo.input_components = 1;
    896    jpegli_set_defaults(&cinfo);
    897    cinfo.restart_interval = 1000000;
    898    jpegli_start_compress(&cinfo, TRUE);
    899    return true;
    900  };
    901  EXPECT_FALSE(try_catch_block());
    902  jpegli_destroy_compress(&cinfo);
    903  if (buffer) free(buffer);
    904 }
    905 
    906 TEST(EncoderErrorHandlingTest, SamplingFactorTooBig) {
    907  uint8_t* buffer = nullptr;
    908  unsigned long buffer_size = 0;  // NOLINT
    909  jpeg_compress_struct cinfo;
    910  const auto try_catch_block = [&]() -> bool {
    911    ERROR_HANDLER_SETUP(jpegli);
    912    jpegli_create_compress(&cinfo);
    913    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    914    cinfo.image_width = 1;
    915    cinfo.image_height = 1;
    916    cinfo.input_components = 3;
    917    jpegli_set_defaults(&cinfo);
    918    cinfo.comp_info[0].h_samp_factor = 5;
    919    jpegli_start_compress(&cinfo, TRUE);
    920    return true;
    921  };
    922  EXPECT_FALSE(try_catch_block());
    923  jpegli_destroy_compress(&cinfo);
    924  if (buffer) free(buffer);
    925 }
    926 
    927 TEST(EncoderErrorHandlingTest, NonIntegralSamplingRatio) {
    928  uint8_t* buffer = nullptr;
    929  unsigned long buffer_size = 0;  // NOLINT
    930  jpeg_compress_struct cinfo;
    931  const auto try_catch_block = [&]() -> bool {
    932    ERROR_HANDLER_SETUP(jpegli);
    933    jpegli_create_compress(&cinfo);
    934    jpegli_mem_dest(&cinfo, &buffer, &buffer_size);
    935    cinfo.image_width = 1;
    936    cinfo.image_height = 1;
    937    cinfo.input_components = 3;
    938    jpegli_set_defaults(&cinfo);
    939    cinfo.comp_info[0].h_samp_factor = 3;
    940    cinfo.comp_info[1].h_samp_factor = 2;
    941    jpegli_start_compress(&cinfo, TRUE);
    942    return true;
    943  };
    944  EXPECT_FALSE(try_catch_block());
    945  jpegli_destroy_compress(&cinfo);
    946  if (buffer) free(buffer);
    947 }
    948 
    949 constexpr const char* kAddOnTable[] = {"First message",
    950                                       "Second message with int param %d",
    951                                       "Third message with string param %s"};
    952 
    953 TEST(EncoderErrorHandlingTest, AddOnTableNoParam) {
    954  jpeg_compress_struct cinfo;
    955  const auto try_catch_block = [&]() -> bool {
    956    ERROR_HANDLER_SETUP(jpegli);
    957    jpegli_create_compress(&cinfo);
    958    cinfo.err->addon_message_table = kAddOnTable;
    959    cinfo.err->first_addon_message = 10000;
    960    cinfo.err->last_addon_message = 10002;
    961    cinfo.err->msg_code = 10000;
    962    (*cinfo.err->error_exit)(reinterpret_cast<j_common_ptr>(&cinfo));
    963    return true;
    964  };
    965  EXPECT_FALSE(try_catch_block());
    966  jpegli_destroy_compress(&cinfo);
    967 }
    968 
    969 TEST(EncoderErrorHandlingTest, AddOnTableIntParam) {
    970  jpeg_compress_struct cinfo;
    971  const auto try_catch_block = [&]() -> bool {
    972    ERROR_HANDLER_SETUP(jpegli);
    973    jpegli_create_compress(&cinfo);
    974    cinfo.err->addon_message_table = kAddOnTable;
    975    cinfo.err->first_addon_message = 10000;
    976    cinfo.err->last_addon_message = 10002;
    977    cinfo.err->msg_code = 10001;
    978    cinfo.err->msg_parm.i[0] = 17;
    979    (*cinfo.err->error_exit)(reinterpret_cast<j_common_ptr>(&cinfo));
    980    return true;
    981  };
    982  EXPECT_FALSE(try_catch_block());
    983  jpegli_destroy_compress(&cinfo);
    984 }
    985 
    986 TEST(EncoderErrorHandlingTest, AddOnTableNoStringParam) {
    987  jpeg_compress_struct cinfo;
    988  const auto try_catch_block = [&]() -> bool {
    989    ERROR_HANDLER_SETUP(jpegli);
    990    jpegli_create_compress(&cinfo);
    991    cinfo.err->addon_message_table = kAddOnTable;
    992    cinfo.err->first_addon_message = 10000;
    993    cinfo.err->last_addon_message = 10002;
    994    cinfo.err->msg_code = 10002;
    995    memcpy(cinfo.err->msg_parm.s, "MESSAGE PARAM", 14);
    996    (*cinfo.err->error_exit)(reinterpret_cast<j_common_ptr>(&cinfo));
    997    return true;
    998  };
    999  EXPECT_FALSE(try_catch_block());
   1000  jpegli_destroy_compress(&cinfo);
   1001 }
   1002 
   1003 const uint8_t kCompressed0[] = {
   1004    // SOI
   1005    0xff, 0xd8,  //
   1006    // SOF
   1007    0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01,  //
   1008    0x01, 0x11, 0x00,                                            //
   1009    // DQT
   1010    0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x03, 0x02,  //
   1011    0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05,  //
   1012    0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, 0x07, 0x06,  //
   1013    0x08, 0x0c, 0x0a, 0x0c, 0x0c, 0x0b, 0x0a, 0x0b, 0x0b, 0x0d,  //
   1014    0x0e, 0x12, 0x10, 0x0d, 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10,  //
   1015    0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f,  //
   1016    0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14,        //
   1017    // DHT
   1018    0xff, 0xc4, 0x00, 0xd2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,  //
   1019    0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //
   1020    0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,  //
   1021    0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,  //
   1022    0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,  //
   1023    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,  //
   1024    0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,  //
   1025    0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,  //
   1026    0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,  //
   1027    0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,  //
   1028    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,  //
   1029    0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,  //
   1030    0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,  //
   1031    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,  //
   1032    0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,  //
   1033    0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,  //
   1034    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,  //
   1035    0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,  //
   1036    0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,  //
   1037    0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,  //
   1038    0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,  //
   1039    0xf9, 0xfa,                                                  //
   1040    // SOS
   1041    0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00,  //
   1042    // entropy coded data
   1043    0xfc, 0xaa, 0xaf,  //
   1044    // EOI
   1045    0xff, 0xd9,  //
   1046 };
   1047 const size_t kLen0 = sizeof(kCompressed0);
   1048 
   1049 const size_t kSOFOffset = 2;
   1050 const size_t kDQTOffset = 15;
   1051 const size_t kDHTOffset = 84;
   1052 const size_t kSOSOffset = 296;
   1053 
   1054 TEST(DecoderErrorHandlingTest, MinimalSuccess) {
   1055  ASSERT_TRUE(kCompressed0[kDQTOffset] == 0xff);
   1056  ASSERT_TRUE(kCompressed0[kSOFOffset] == 0xff);
   1057  ASSERT_TRUE(kCompressed0[kDHTOffset] == 0xff);
   1058  ASSERT_TRUE(kCompressed0[kSOSOffset] == 0xff);
   1059  jpeg_decompress_struct cinfo = {};
   1060  const auto try_catch_block = [&]() -> bool {
   1061    ERROR_HANDLER_SETUP(jpegli);
   1062    jpegli_create_decompress(&cinfo);
   1063    jpegli_mem_src(&cinfo, kCompressed0, kLen0);
   1064    jpegli_read_header(&cinfo, TRUE);
   1065    EXPECT_EQ(1, cinfo.image_width);
   1066    EXPECT_EQ(1, cinfo.image_height);
   1067    jpegli_start_decompress(&cinfo);
   1068    JSAMPLE image[1];
   1069    JSAMPROW row[] = {image};
   1070    jpegli_read_scanlines(&cinfo, row, 1);
   1071    EXPECT_EQ(0, image[0]);
   1072    jpegli_finish_decompress(&cinfo);
   1073    return true;
   1074  };
   1075  EXPECT_TRUE(try_catch_block());
   1076  jpegli_destroy_decompress(&cinfo);
   1077 }
   1078 
   1079 TEST(DecoderErrorHandlingTest, NoSource) {
   1080  jpeg_decompress_struct cinfo = {};
   1081  const auto try_catch_block = [&]() -> bool {
   1082    ERROR_HANDLER_SETUP(jpegli);
   1083    jpegli_create_decompress(&cinfo);
   1084    jpegli_read_header(&cinfo, TRUE);
   1085    return true;
   1086  };
   1087  EXPECT_FALSE(try_catch_block());
   1088  jpegli_destroy_decompress(&cinfo);
   1089 }
   1090 
   1091 TEST(DecoderErrorHandlingTest, NoReadHeader) {
   1092  jpeg_decompress_struct cinfo = {};
   1093  const auto try_catch_block = [&]() -> bool {
   1094    ERROR_HANDLER_SETUP(jpegli);
   1095    jpegli_create_decompress(&cinfo);
   1096    jpegli_mem_src(&cinfo, kCompressed0, kLen0);
   1097    jpegli_start_decompress(&cinfo);
   1098    return true;
   1099  };
   1100  EXPECT_FALSE(try_catch_block());
   1101  jpegli_destroy_decompress(&cinfo);
   1102 }
   1103 
   1104 TEST(DecoderErrorHandlingTest, NoStartDecompress) {
   1105  jpeg_decompress_struct cinfo = {};
   1106  const auto try_catch_block = [&]() -> bool {
   1107    ERROR_HANDLER_SETUP(jpegli);
   1108    jpegli_create_decompress(&cinfo);
   1109    jpegli_mem_src(&cinfo, kCompressed0, kLen0);
   1110    jpegli_read_header(&cinfo, TRUE);
   1111    EXPECT_EQ(1, cinfo.image_width);
   1112    EXPECT_EQ(1, cinfo.image_height);
   1113    JSAMPLE image[1];
   1114    JSAMPROW row[] = {image};
   1115    jpegli_read_scanlines(&cinfo, row, 1);
   1116    EXPECT_EQ(0, image[0]);
   1117    jpegli_finish_decompress(&cinfo);
   1118    return true;
   1119  };
   1120  EXPECT_FALSE(try_catch_block());
   1121  jpegli_destroy_decompress(&cinfo);
   1122 }
   1123 
   1124 TEST(DecoderErrorHandlingTest, NoReadScanlines) {
   1125  jpeg_decompress_struct cinfo = {};
   1126  const auto try_catch_block = [&]() -> bool {
   1127    ERROR_HANDLER_SETUP(jpegli);
   1128    jpegli_create_decompress(&cinfo);
   1129    jpegli_mem_src(&cinfo, kCompressed0, kLen0);
   1130    jpegli_read_header(&cinfo, TRUE);
   1131    EXPECT_EQ(1, cinfo.image_width);
   1132    EXPECT_EQ(1, cinfo.image_height);
   1133    jpegli_start_decompress(&cinfo);
   1134    jpegli_finish_decompress(&cinfo);
   1135    return true;
   1136  };
   1137  EXPECT_FALSE(try_catch_block());
   1138  jpegli_destroy_decompress(&cinfo);
   1139 }
   1140 
   1141 const size_t kMaxImageWidth = 0xffff;
   1142 JSAMPLE kOutputBuffer[MAX_COMPONENTS * kMaxImageWidth];
   1143 
   1144 bool ParseCompressed(const std::vector<uint8_t>& compressed) {
   1145  jpeg_decompress_struct cinfo = {};
   1146  const auto try_catch_block = [&]() -> bool {
   1147    ERROR_HANDLER_SETUP(jpegli);
   1148    jpegli_create_decompress(&cinfo);
   1149    jpegli_mem_src(&cinfo, compressed.data(), compressed.size());
   1150    jpegli_read_header(&cinfo, TRUE);
   1151    jpegli_start_decompress(&cinfo);
   1152    for (JDIMENSION i = 0; i < cinfo.output_height; ++i) {
   1153      JSAMPROW row[] = {kOutputBuffer};
   1154      jpegli_read_scanlines(&cinfo, row, 1);
   1155    }
   1156    jpegli_finish_decompress(&cinfo);
   1157    return true;
   1158  };
   1159  bool retval = try_catch_block();
   1160  jpegli_destroy_decompress(&cinfo);
   1161  return retval;
   1162 }
   1163 
   1164 TEST(DecoderErrorHandlingTest, NoSOI) {
   1165  for (int pos : {0, 1}) {
   1166    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1167    compressed[pos] = 0;
   1168    EXPECT_FALSE(ParseCompressed(compressed));
   1169  }
   1170 }
   1171 
   1172 TEST(DecoderErrorHandlingTest, InvalidDQT) {
   1173  // Bad marker length
   1174  for (int diff : {-2, -1, 1, 2}) {
   1175    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1176    compressed[kDQTOffset + 3] += diff;
   1177    EXPECT_FALSE(ParseCompressed(compressed));
   1178  }
   1179  // invalid table index / precision
   1180  for (int val : {0x20, 0x05}) {
   1181    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1182    compressed[kDQTOffset + 4] = val;
   1183    EXPECT_FALSE(ParseCompressed(compressed));
   1184  }
   1185  // zero quant value
   1186  for (int k : {0, 1, 17, 63}) {
   1187    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1188    compressed[kDQTOffset + 5 + k] = 0;
   1189    EXPECT_FALSE(ParseCompressed(compressed));
   1190  }
   1191 }
   1192 
   1193 TEST(DecoderErrorHandlingTest, InvalidSOF) {
   1194  // Bad marker length
   1195  for (int diff : {-2, -1, 1, 2}) {
   1196    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1197    compressed[kSOFOffset + 3] += diff;
   1198    EXPECT_FALSE(ParseCompressed(compressed));
   1199  }
   1200  // zero width, height or num_components
   1201  for (int pos : {6, 8, 9}) {
   1202    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1203    compressed[kSOFOffset + pos] = 0;
   1204    EXPECT_FALSE(ParseCompressed(compressed));
   1205  }
   1206  // invalid data precision
   1207  for (int val : {0, 1, 127}) {
   1208    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1209    compressed[kSOFOffset + 4] = val;
   1210    EXPECT_FALSE(ParseCompressed(compressed));
   1211  }
   1212  // too many num_components
   1213  for (int val : {5, 255}) {
   1214    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1215    compressed[kSOFOffset + 9] = val;
   1216    EXPECT_FALSE(ParseCompressed(compressed));
   1217  }
   1218  // invalid sampling factors
   1219  for (int val : {0x00, 0x01, 0x10, 0x15, 0x51}) {
   1220    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1221    compressed[kSOFOffset + 11] = val;
   1222    EXPECT_FALSE(ParseCompressed(compressed));
   1223  }
   1224  // invalid quant table index
   1225  for (int val : {5, 17}) {
   1226    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1227    compressed[kSOFOffset + 12] = val;
   1228    EXPECT_FALSE(ParseCompressed(compressed));
   1229  }
   1230 }
   1231 
   1232 TEST(DecoderErrorHandlingTest, InvalidDHT) {
   1233  // Bad marker length
   1234  for (int diff : {-2, -1, 1, 2}) {
   1235    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1236    compressed[kDHTOffset + 3] += diff;
   1237    EXPECT_FALSE(ParseCompressed(compressed));
   1238  }
   1239  {
   1240    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1241    compressed[kDHTOffset + 2] += 17;
   1242    EXPECT_FALSE(ParseCompressed(compressed));
   1243  }
   1244  // invalid table slot_id
   1245  for (int val : {0x05, 0x15, 0x20}) {
   1246    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1247    compressed[kDHTOffset + 4] = val;
   1248    EXPECT_FALSE(ParseCompressed(compressed));
   1249  }
   1250 }
   1251 
   1252 TEST(DecoderErrorHandlingTest, InvalidSOS) {
   1253  // Invalid comps_in_scan
   1254  for (int val : {2, 5, 17}) {
   1255    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1256    compressed[kSOSOffset + 4] = val;
   1257    EXPECT_FALSE(ParseCompressed(compressed));
   1258  }
   1259  // invalid Huffman table indexes
   1260  for (int val : {0x05, 0x50, 0x15, 0x51}) {
   1261    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1262    compressed[kSOSOffset + 6] = val;
   1263    EXPECT_FALSE(ParseCompressed(compressed));
   1264  }
   1265  // invalid Ss/Se
   1266  for (int pos : {7, 8}) {
   1267    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1268    compressed[kSOSOffset + pos] = 64;
   1269    EXPECT_FALSE(ParseCompressed(compressed));
   1270  }
   1271 }
   1272 
   1273 TEST(DecoderErrorHandlingTest, MutateSingleBytes) {
   1274  for (size_t pos = 0; pos < kLen0; ++pos) {
   1275    std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
   1276    for (int val : {0x00, 0x0f, 0xf0, 0xff}) {
   1277      compressed[pos] = val;
   1278      ParseCompressed(compressed);
   1279    }
   1280  }
   1281 }
   1282 
   1283 }  // namespace
   1284 }  // namespace jpegli