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