diff --git a/CMakeLists.txt b/CMakeLists.txt index 8812b822d..ae07280b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(CMAKE_EXECUTABLE_SUFFIX) endif() project(mozjpeg C) -set(VERSION 4.0.4) +set(VERSION 4.1.0) string(REPLACE "." ";" VERSION_TRIPLET ${VERSION}) list(GET VERSION_TRIPLET 0 VERSION_MAJOR) list(GET VERSION_TRIPLET 1 VERSION_MINOR) @@ -62,14 +62,14 @@ if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR set(CMAKE_SYSTEM_PROCESSOR ${CPU_TYPE}) endif() elseif(CMAKE_SYSTEM_PROCESSOR_LC STREQUAL "aarch64" OR - CMAKE_SYSTEM_PROCESSOR_LC MATCHES "arm*") + CMAKE_SYSTEM_PROCESSOR_LC MATCHES "^arm") if(BITS EQUAL 64) set(CPU_TYPE arm64) else() set(CPU_TYPE arm) endif() -elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ppc*" OR - CMAKE_SYSTEM_PROCESSOR_LC MATCHES "powerpc*") +elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "^ppc" OR + CMAKE_SYSTEM_PROCESSOR_LC MATCHES "^powerpc") set(CPU_TYPE powerpc) else() set(CPU_TYPE ${CMAKE_SYSTEM_PROCESSOR_LC}) @@ -104,7 +104,7 @@ if(WIN32) endif() else() if(NOT CMAKE_INSTALL_DEFAULT_PREFIX) - set(CMAKE_INSTALL_DEFAULT_PREFIX /opt/${CMAKE_PROJECT_NAME}) + set(CMAKE_INSTALL_DEFAULT_PREFIX /opt/${CMAKE_PROJECT_NAME}) endif() endif() if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) @@ -194,6 +194,7 @@ option(WITH_SIMD "Include SIMD extensions, if available for this platform" TRUE) boolean_number(WITH_SIMD) option(WITH_TURBOJPEG "Include the TurboJPEG API library and associated test programs" TRUE) boolean_number(WITH_TURBOJPEG) +option(WITH_FUZZ "Build fuzz targets" FALSE) macro(report_option var desc) if(${var}) @@ -752,6 +753,10 @@ add_executable(wrjpgcom wrjpgcom.c) # TESTS ############################################################################### +if(WITH_FUZZ) + add_subdirectory(fuzz) +endif() + add_subdirectory(md5) if(MSVC_IDE OR XCODE) @@ -772,7 +777,7 @@ if(WITH_12BIT) set(MD5_JPEG_440_ISLOW e25c1912e38367be505a89c410c1c2d2) set(MD5_PPM_440_ISLOW e7d2e26288870cfcb30f3114ad01e380) set(MD5_PPM_422M_IFAST 07737bfe8a7c1c87aaa393a0098d16b0) - set(MD5_JPEG_420_IFAST_Q100_PROG 008ab68d6ddbba04a8f01deee4e0f9f8) + set(MD5_JPEG_420_IFAST_Q100_PROG 9447cef4803d9b0f74bcf333cc710a29) set(MD5_PPM_420_Q100_IFAST 1b3730122709f53d007255e8dfd3305e) set(MD5_PPM_420M_Q100_IFAST 980a1a3c5bf9510022869d30b7d26566) set(MD5_JPEG_GRAY_ISLOW 235c90707b16e2e069f37c888b2636d9) @@ -820,12 +825,12 @@ else() set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4) set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8) set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa) - set(MD5_JPEG_440_ISLOW 538bc02bd4b4658fd85de6ece6cbeda6) - set(MD5_PPM_440_ISLOW 11e7eab7ef7ef3276934bb7e7b6bb377) + set(MD5_JPEG_440_ISLOW 368200a98a9d5041170a6232491522f9) + set(MD5_PPM_440_ISLOW 59d718725c83d37a0b59b7e4e355d2fb) set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d) set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065) set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1) - set(MD5_JPEG_420_IFAST_Q100_PROG e59bb462016a8d9a748c330a3474bb55) + set(MD5_JPEG_420_IFAST_Q100_PROG 0ba15f9dab81a703505f835f9dbbac6d) set(MD5_PPM_420_Q100_IFAST 5a732542015c278ff43635e473a8a294) set(MD5_PPM_420M_Q100_IFAST ff692ee9323a3b424894862557c092f1) set(MD5_JPEG_GRAY_ISLOW 72b51f894b8f4a10b3ee3066770aa38d) @@ -851,7 +856,7 @@ else() set(MD5_PPM_3x2_IFAST fd283664b3b49127984af0a7f118fccd) set(MD5_JPEG_420_ISLOW_ARI e986fb0a637a8d833d96e8a6d6d84ea1) set(MD5_JPEG_444_ISLOW_PROGARI 0a8f1c8f66e113c3cf635df0a475a617) - set(MD5_PPM_420M_IFAST_ARI 57251da28a35b46eecb7177d82d10e0e) + set(MD5_PPM_420M_IFAST_ARI 57251da28a35b46eecb7177d82d10e0e) set(MD5_JPEG_420_ISLOW 9a68f56bc76e466aa7e52f415d0f4a5f) set(MD5_PPM_420M_ISLOW_2_1 9f9de8c0612f8d06869b960b05abf9c9) set(MD5_PPM_420M_ISLOW_15_8 b6875bc070720b899566cc06459b63b7) @@ -1224,9 +1229,9 @@ foreach(libtype ${TEST_LIBTYPES}) if(WITH_ARITH_DEC) # CC: RGB->YCC SAMP: h2v2 merged IDCT: ifast ENT: arith - add_bittest(djpeg 420m-ifast-ari "-fast;-skip;1,20;-ppm" - testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg - ${MD5_PPM_420M_IFAST_ARI}) + add_bittest(djpeg 420m-ifast-ari "-fast;-skip;1,20;-ppm" + testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg + ${MD5_PPM_420M_IFAST_ARI}) add_bittest(jpegtran 420-islow "-revert" testout_420_islow.jpg ${TESTIMAGES}/testimgari.jpg diff --git a/ChangeLog.md b/ChangeLog.md index 61a9095ec..498b8f272 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,5 @@ -2.1 post-beta -============= +2.1.0 +===== ### Significant changes relative to 2.1 beta1 @@ -15,9 +15,40 @@ block smoothing algorithm to read from uninitialized memory. encoders to generate incorrect results when using the Clang compiler with Visual Studio. -4. Fixed a floating point exception that occurred when attempting to compress a -specially-crafted malformed GIF image with a specified image width of 0 using -cjpeg. +4. Fixed a floating point exception (CVE-2021-20205) that occurred when +attempting to compress a specially-crafted malformed GIF image with a specified +image width of 0 using cjpeg. + +5. Fixed a regression introduced by 2.0 beta1[15] whereby attempting to +generate a progressive JPEG image on an SSE2-capable CPU using a scan script +containing one or more scans with lengths divisible by 32 and non-zero +successive approximation low bit positions would, under certain circumstances, +result in an error ("Missing Huffman code table entry") and an invalid JPEG +image. + +6. Introduced a new flag (`TJFLAG_LIMITSCANS` in the TurboJPEG C API and +`TJ.FLAG_LIMIT_SCANS` in the TurboJPEG Java API) and a corresponding TJBench +command-line argument (`-limitscans`) that causes the TurboJPEG decompression +and transform functions/operations to return/throw an error if a progressive +JPEG image contains an unreasonably large number of scans. This allows +applications that use the TurboJPEG API to guard against an exploit of the +progressive JPEG format described in the report +["Two Issues with the JPEG Standard"](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf). + +7. The PPM reader now throws an error, rather than segfaulting (due to a buffer +overrun) or generating incorrect pixels, if an application attempts to use the +`tjLoadImage()` function to load a 16-bit binary PPM file (a binary PPM file +with a maximum value greater than 255) into a grayscale image buffer or to load +a 16-bit binary PGM file into an RGB image buffer. + +8. Fixed an issue in the PPM reader that caused incorrect pixels to be +generated when using the `tjLoadImage()` function to load a 16-bit binary PPM +file into an extended RGB image buffer. + +9. Fixed an issue whereby, if a JPEG buffer was automatically re-allocated by +one of the TurboJPEG compression or transform functions and an error +subsequently occurred during compression or transformation, the JPEG buffer +pointer passed by the application was not updated when the function returned. 2.0.90 (2.1 beta1) diff --git a/cdjpeg.h b/cdjpeg.h index fcce35907..79e66240e 100644 --- a/cdjpeg.h +++ b/cdjpeg.h @@ -5,7 +5,7 @@ * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 2019 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2017, 2019, D. R. Commander. + * Copyright (C) 2017, 2019, 2021, D. R. Commander. * mozjpeg Modifications: * Copyright (C) 2014, Mozilla Corporation. * For conditions of distribution and use, see the accompanying README.ijg file. @@ -38,7 +38,9 @@ struct cjpeg_source_struct { JSAMPARRAY buffer; JDIMENSION buffer_height; - +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + JDIMENSION max_pixels; +#endif #if JPEG_RAW_READER // For reading JPEG JSAMPARRAY plane_pointer[4]; diff --git a/cjpeg.c b/cjpeg.c index 6c146a7b5..243be1cb4 100644 --- a/cjpeg.c +++ b/cjpeg.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2011 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2013-2014, 2017, 2019-2020, D. R. Commander. + * Copyright (C) 2010, 2013-2014, 2017, 2019-2021, D. R. Commander. * mozjpeg Modifications: * Copyright (C) 2014, Mozilla Corporation. * For conditions of distribution and use, see the accompanying README file. @@ -28,6 +28,9 @@ * works regardless of which command line style is used. */ +#ifdef CJPEG_FUZZER +#define JPEG_INTERNALS +#endif #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "jversion.h" /* for version message */ #include "jconfigint.h" @@ -157,6 +160,45 @@ boolean memdst; /* for -memdst switch */ boolean report; /* for -report switch */ +#ifdef CJPEG_FUZZER + +#include + +struct my_error_mgr { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +void my_error_exit(j_common_ptr cinfo) +{ + struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err; + + longjmp(myerr->setjmp_buffer, 1); +} + +static void my_emit_message(j_common_ptr cinfo, int msg_level) +{ + if (msg_level < 0) + cinfo->err->num_warnings++; +} + +#define HANDLE_ERROR() { \ + if (cinfo.global_state > CSTATE_START) { \ + if (memdst && outbuffer) \ + (*cinfo.dest->term_destination) (&cinfo); \ + jpeg_abort_compress(&cinfo); \ + } \ + jpeg_destroy_compress(&cinfo); \ + if (input_file != stdin && input_file != NULL) \ + fclose(input_file); \ + if (memdst) \ + free(outbuffer); \ + return EXIT_FAILURE; \ +} + +#endif + + LOCAL(void) usage(void) /* complain about bad command line */ @@ -662,11 +704,16 @@ int main(int argc, char **argv) { struct jpeg_compress_struct cinfo; +#ifdef CJPEG_FUZZER + struct my_error_mgr myerr; + struct jpeg_error_mgr &jerr = myerr.pub; +#else struct jpeg_error_mgr jerr; +#endif struct cdjpeg_progress_mgr progress; int file_index; cjpeg_source_ptr src_mgr; - FILE *input_file; + FILE *input_file = NULL; FILE *icc_file; JOCTET *icc_profile = NULL; long icc_len = 0; @@ -784,14 +831,24 @@ main(int argc, char **argv) fclose(icc_file); } +#ifdef CJPEG_FUZZER + jerr.error_exit = my_error_exit; + jerr.emit_message = my_emit_message; + if (setjmp(myerr.setjmp_buffer)) + HANDLE_ERROR() +#endif + if (report) { - start_progress_monitor((j_common_ptr)&cinfo, &progress); + start_progress_monitor((j_common_ptr)&cinfo, &progress); progress.report = report; } /* Figure out the input file format, and set up to read it. */ src_mgr = select_file_type(&cinfo, input_file); src_mgr->input_file = input_file; +#ifdef CJPEG_FUZZER + src_mgr->max_pixels = 1048576; +#endif /* Read the input file header to obtain file size & colorspace. */ (*src_mgr->start_input) (&cinfo, src_mgr); @@ -813,6 +870,11 @@ main(int argc, char **argv) #endif jpeg_stdio_dest(&cinfo, output_file); +#ifdef CJPEG_FUZZER + if (setjmp(myerr.setjmp_buffer)) + HANDLE_ERROR() +#endif + /* Start compressor */ jpeg_start_compress(&cinfo, TRUE); @@ -874,16 +936,17 @@ main(int argc, char **argv) fclose(output_file); if (report) - end_progress_monitor((j_common_ptr)&cinfo); + end_progress_monitor((j_common_ptr)&cinfo); if (memdst) { +#ifndef CJPEG_FUZZER fprintf(stderr, "Compressed size: %lu bytes\n", outsize); +#endif free(outbuffer); } free(icc_profile); /* All done. */ - exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); - return 0; /* suppress no-return-value warnings */ + return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); } diff --git a/doc/html/annotated.html b/doc/html/annotated.html index 08282d97f..b7773dd4a 100644 --- a/doc/html/annotated.html +++ b/doc/html/annotated.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/classes.html b/doc/html/classes.html index 756dfa922..bfcf32a95 100644 --- a/doc/html/classes.html +++ b/doc/html/classes.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/functions.html b/doc/html/functions.html index 7f85093ca..055b876fd 100644 --- a/doc/html/functions.html +++ b/doc/html/functions.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html index 68e20e1b0..540b3e44d 100644 --- a/doc/html/functions_vars.html +++ b/doc/html/functions_vars.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/group___turbo_j_p_e_g.html b/doc/html/group___turbo_j_p_e_g.html index 8c82803ba..bf100736f 100644 --- a/doc/html/group___turbo_j_p_e_g.html +++ b/doc/html/group___turbo_j_p_e_g.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
@@ -122,6 +122,9 @@ #define TJFLAG_PROGRESSIVE  Use progressive entropy coding in JPEG images generated by the compression and transform functions. More...
  +#define TJFLAG_LIMITSCANS + Limit the number of progressive JPEG scans that the decompression and transform functions will process. More...
+  #define TJ_NUMERR  The number of error codes. More...
  @@ -497,6 +500,23 @@

+

◆ TJFLAG_LIMITSCANS

+ +
+
+ + + + +
#define TJFLAG_LIMITSCANS
+
+ +

Limit the number of progressive JPEG scans that the decompression and transform functions will process.

+

If a progressive JPEG image contains an unreasonably large number of scans, then this flag will cause the decompression and transform functions to return an error. The primary purpose of this is to allow security-critical applications to guard against an exploit of the progressive JPEG format described in this report.

+
diff --git a/doc/html/index.html b/doc/html/index.html index c5ed7780e..165a589f0 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/modules.html b/doc/html/modules.html index de5be658b..b3fa1c061 100644 --- a/doc/html/modules.html +++ b/doc/html/modules.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/search/all_6.js b/doc/html/search/all_6.js index 5750e1dbc..aa311074e 100644 --- a/doc/html/search/all_6.js +++ b/doc/html/search/all_6.js @@ -35,68 +35,69 @@ var searchData= ['tjflag_5fbottomup_40',['TJFLAG_BOTTOMUP',['../group___turbo_j_p_e_g.html#ga72ecf4ebe6eb702d3c6f5ca27455e1ec',1,'turbojpeg.h']]], ['tjflag_5ffastdct_41',['TJFLAG_FASTDCT',['../group___turbo_j_p_e_g.html#gaabce235db80d3f698b27f36cbd453da2',1,'turbojpeg.h']]], ['tjflag_5ffastupsample_42',['TJFLAG_FASTUPSAMPLE',['../group___turbo_j_p_e_g.html#ga4ee4506c81177a06f77e2504a22efd2d',1,'turbojpeg.h']]], - ['tjflag_5fnorealloc_43',['TJFLAG_NOREALLOC',['../group___turbo_j_p_e_g.html#ga8808d403c68b62aaa58a4c1e58e98963',1,'turbojpeg.h']]], - ['tjflag_5fprogressive_44',['TJFLAG_PROGRESSIVE',['../group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b',1,'turbojpeg.h']]], - ['tjflag_5fstoponwarning_45',['TJFLAG_STOPONWARNING',['../group___turbo_j_p_e_g.html#ga519cfa4ef6c18d9e5b455fdf59306a3a',1,'turbojpeg.h']]], - ['tjfree_46',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]], - ['tjgeterrorcode_47',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]], - ['tjgeterrorstr2_48',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]], - ['tjgetscalingfactors_49',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]], - ['tjgreenoffset_50',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]], - ['tjhandle_51',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]], - ['tjinitcompress_52',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]], - ['tjinitdecompress_53',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]], - ['tjinittransform_54',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]], - ['tjloadimage_55',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]], - ['tjmcuheight_56',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]], - ['tjmcuwidth_57',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]], - ['tjpad_58',['TJPAD',['../group___turbo_j_p_e_g.html#ga0aba955473315e405295d978f0c16511',1,'turbojpeg.h']]], - ['tjpf_59',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]], - ['tjpf_5fabgr_60',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]], - ['tjpf_5fargb_61',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]], - ['tjpf_5fbgr_62',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]], - ['tjpf_5fbgra_63',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]], - ['tjpf_5fbgrx_64',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]], - ['tjpf_5fcmyk_65',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]], - ['tjpf_5fgray_66',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]], - ['tjpf_5frgb_67',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]], - ['tjpf_5frgba_68',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]], - ['tjpf_5frgbx_69',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]], - ['tjpf_5funknown_70',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]], - ['tjpf_5fxbgr_71',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], - ['tjpf_5fxrgb_72',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], - ['tjpixelsize_73',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], - ['tjplaneheight_74',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], - ['tjplanesizeyuv_75',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]], - ['tjplanewidth_76',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], - ['tjredoffset_77',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]], - ['tjregion_78',['tjregion',['../structtjregion.html',1,'']]], - ['tjsamp_79',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], - ['tjsamp_5f411_80',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]], - ['tjsamp_5f420_81',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]], - ['tjsamp_5f422_82',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]], - ['tjsamp_5f440_83',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]], - ['tjsamp_5f444_84',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]], - ['tjsamp_5fgray_85',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]], - ['tjsaveimage_86',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]], - ['tjscaled_87',['TJSCALED',['../group___turbo_j_p_e_g.html#ga84878bb65404204743aa18cac02781df',1,'turbojpeg.h']]], - ['tjscalingfactor_88',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]], - ['tjtransform_89',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'tjtransform(): turbojpeg.h'],['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'tjTransform(tjhandle handle, const unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *transforms, int flags): turbojpeg.h']]], - ['tjxop_90',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]], - ['tjxop_5fhflip_91',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]], - ['tjxop_5fnone_92',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]], - ['tjxop_5frot180_93',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]], - ['tjxop_5frot270_94',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]], - ['tjxop_5frot90_95',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]], - ['tjxop_5ftranspose_96',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]], - ['tjxop_5ftransverse_97',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]], - ['tjxop_5fvflip_98',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]], - ['tjxopt_5fcopynone_99',['TJXOPT_COPYNONE',['../group___turbo_j_p_e_g.html#ga153b468cfb905d0de61706c838986fe8',1,'turbojpeg.h']]], - ['tjxopt_5fcrop_100',['TJXOPT_CROP',['../group___turbo_j_p_e_g.html#ga9c771a757fc1294add611906b89ab2d2',1,'turbojpeg.h']]], - ['tjxopt_5fgray_101',['TJXOPT_GRAY',['../group___turbo_j_p_e_g.html#ga3acee7b48ade1b99e5588736007c2589',1,'turbojpeg.h']]], - ['tjxopt_5fnooutput_102',['TJXOPT_NOOUTPUT',['../group___turbo_j_p_e_g.html#gafbf992bbf6e006705886333703ffab31',1,'turbojpeg.h']]], - ['tjxopt_5fperfect_103',['TJXOPT_PERFECT',['../group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00',1,'turbojpeg.h']]], - ['tjxopt_5fprogressive_104',['TJXOPT_PROGRESSIVE',['../group___turbo_j_p_e_g.html#gad2371c80674584ecc1a7d75e564cf026',1,'turbojpeg.h']]], - ['tjxopt_5ftrim_105',['TJXOPT_TRIM',['../group___turbo_j_p_e_g.html#ga319826b7eb1583c0595bbe7b95428709',1,'turbojpeg.h']]], - ['turbojpeg_106',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]] + ['tjflag_5flimitscans_43',['TJFLAG_LIMITSCANS',['../group___turbo_j_p_e_g.html#ga163e6482dc5096831feef9c79ff3f805',1,'turbojpeg.h']]], + ['tjflag_5fnorealloc_44',['TJFLAG_NOREALLOC',['../group___turbo_j_p_e_g.html#ga8808d403c68b62aaa58a4c1e58e98963',1,'turbojpeg.h']]], + ['tjflag_5fprogressive_45',['TJFLAG_PROGRESSIVE',['../group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b',1,'turbojpeg.h']]], + ['tjflag_5fstoponwarning_46',['TJFLAG_STOPONWARNING',['../group___turbo_j_p_e_g.html#ga519cfa4ef6c18d9e5b455fdf59306a3a',1,'turbojpeg.h']]], + ['tjfree_47',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]], + ['tjgeterrorcode_48',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]], + ['tjgeterrorstr2_49',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]], + ['tjgetscalingfactors_50',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]], + ['tjgreenoffset_51',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]], + ['tjhandle_52',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]], + ['tjinitcompress_53',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]], + ['tjinitdecompress_54',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]], + ['tjinittransform_55',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]], + ['tjloadimage_56',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]], + ['tjmcuheight_57',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]], + ['tjmcuwidth_58',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]], + ['tjpad_59',['TJPAD',['../group___turbo_j_p_e_g.html#ga0aba955473315e405295d978f0c16511',1,'turbojpeg.h']]], + ['tjpf_60',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]], + ['tjpf_5fabgr_61',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]], + ['tjpf_5fargb_62',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]], + ['tjpf_5fbgr_63',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]], + ['tjpf_5fbgra_64',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]], + ['tjpf_5fbgrx_65',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]], + ['tjpf_5fcmyk_66',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]], + ['tjpf_5fgray_67',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]], + ['tjpf_5frgb_68',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]], + ['tjpf_5frgba_69',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]], + ['tjpf_5frgbx_70',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]], + ['tjpf_5funknown_71',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]], + ['tjpf_5fxbgr_72',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], + ['tjpf_5fxrgb_73',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], + ['tjpixelsize_74',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], + ['tjplaneheight_75',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], + ['tjplanesizeyuv_76',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]], + ['tjplanewidth_77',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], + ['tjredoffset_78',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]], + ['tjregion_79',['tjregion',['../structtjregion.html',1,'']]], + ['tjsamp_80',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], + ['tjsamp_5f411_81',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]], + ['tjsamp_5f420_82',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]], + ['tjsamp_5f422_83',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]], + ['tjsamp_5f440_84',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]], + ['tjsamp_5f444_85',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]], + ['tjsamp_5fgray_86',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]], + ['tjsaveimage_87',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]], + ['tjscaled_88',['TJSCALED',['../group___turbo_j_p_e_g.html#ga84878bb65404204743aa18cac02781df',1,'turbojpeg.h']]], + ['tjscalingfactor_89',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]], + ['tjtransform_90',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'tjtransform(): turbojpeg.h'],['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'tjTransform(tjhandle handle, const unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *transforms, int flags): turbojpeg.h']]], + ['tjxop_91',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]], + ['tjxop_5fhflip_92',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]], + ['tjxop_5fnone_93',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]], + ['tjxop_5frot180_94',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]], + ['tjxop_5frot270_95',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]], + ['tjxop_5frot90_96',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]], + ['tjxop_5ftranspose_97',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]], + ['tjxop_5ftransverse_98',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]], + ['tjxop_5fvflip_99',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]], + ['tjxopt_5fcopynone_100',['TJXOPT_COPYNONE',['../group___turbo_j_p_e_g.html#ga153b468cfb905d0de61706c838986fe8',1,'turbojpeg.h']]], + ['tjxopt_5fcrop_101',['TJXOPT_CROP',['../group___turbo_j_p_e_g.html#ga9c771a757fc1294add611906b89ab2d2',1,'turbojpeg.h']]], + ['tjxopt_5fgray_102',['TJXOPT_GRAY',['../group___turbo_j_p_e_g.html#ga3acee7b48ade1b99e5588736007c2589',1,'turbojpeg.h']]], + ['tjxopt_5fnooutput_103',['TJXOPT_NOOUTPUT',['../group___turbo_j_p_e_g.html#gafbf992bbf6e006705886333703ffab31',1,'turbojpeg.h']]], + ['tjxopt_5fperfect_104',['TJXOPT_PERFECT',['../group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00',1,'turbojpeg.h']]], + ['tjxopt_5fprogressive_105',['TJXOPT_PROGRESSIVE',['../group___turbo_j_p_e_g.html#gad2371c80674584ecc1a7d75e564cf026',1,'turbojpeg.h']]], + ['tjxopt_5ftrim_106',['TJXOPT_TRIM',['../group___turbo_j_p_e_g.html#ga319826b7eb1583c0595bbe7b95428709',1,'turbojpeg.h']]], + ['turbojpeg_107',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]] ]; diff --git a/doc/html/search/all_7.js b/doc/html/search/all_7.js index aa89546f5..46e499499 100644 --- a/doc/html/search/all_7.js +++ b/doc/html/search/all_7.js @@ -1,4 +1,4 @@ var searchData= [ - ['w_107',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]] + ['w_108',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]] ]; diff --git a/doc/html/search/all_8.js b/doc/html/search/all_8.js index 5d73a5a20..157ee9810 100644 --- a/doc/html/search/all_8.js +++ b/doc/html/search/all_8.js @@ -1,4 +1,4 @@ var searchData= [ - ['x_108',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]] + ['x_109',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]] ]; diff --git a/doc/html/search/all_9.js b/doc/html/search/all_9.js index 72ea57008..80ac52235 100644 --- a/doc/html/search/all_9.js +++ b/doc/html/search/all_9.js @@ -1,4 +1,4 @@ var searchData= [ - ['y_109',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]] + ['y_110',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]] ]; diff --git a/doc/html/search/classes_0.js b/doc/html/search/classes_0.js index ac6518bfc..ed057f2a0 100644 --- a/doc/html/search/classes_0.js +++ b/doc/html/search/classes_0.js @@ -1,6 +1,6 @@ var searchData= [ - ['tjregion_110',['tjregion',['../structtjregion.html',1,'']]], - ['tjscalingfactor_111',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]], - ['tjtransform_112',['tjtransform',['../structtjtransform.html',1,'']]] + ['tjregion_111',['tjregion',['../structtjregion.html',1,'']]], + ['tjscalingfactor_112',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]], + ['tjtransform_113',['tjtransform',['../structtjtransform.html',1,'']]] ]; diff --git a/doc/html/search/enums_0.js b/doc/html/search/enums_0.js index 2626d66bf..0e15c9a38 100644 --- a/doc/html/search/enums_0.js +++ b/doc/html/search/enums_0.js @@ -1,8 +1,8 @@ var searchData= [ - ['tjcs_161',['TJCS',['../group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720',1,'turbojpeg.h']]], - ['tjerr_162',['TJERR',['../group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe',1,'turbojpeg.h']]], - ['tjpf_163',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]], - ['tjsamp_164',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], - ['tjxop_165',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]] + ['tjcs_162',['TJCS',['../group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720',1,'turbojpeg.h']]], + ['tjerr_163',['TJERR',['../group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe',1,'turbojpeg.h']]], + ['tjpf_164',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]], + ['tjsamp_165',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], + ['tjxop_166',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]] ]; diff --git a/doc/html/search/enumvalues_0.js b/doc/html/search/enumvalues_0.js index 4612b1f31..67c78fef5 100644 --- a/doc/html/search/enumvalues_0.js +++ b/doc/html/search/enumvalues_0.js @@ -1,37 +1,37 @@ var searchData= [ - ['tjcs_5fcmyk_166',['TJCS_CMYK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53',1,'turbojpeg.h']]], - ['tjcs_5fgray_167',['TJCS_GRAY',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a',1,'turbojpeg.h']]], - ['tjcs_5frgb_168',['TJCS_RGB',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a677cb7ccb85c4038ac41964a2e09e555',1,'turbojpeg.h']]], - ['tjcs_5fycbcr_169',['TJCS_YCbCr',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75',1,'turbojpeg.h']]], - ['tjcs_5fycck_170',['TJCS_YCCK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e',1,'turbojpeg.h']]], - ['tjerr_5ffatal_171',['TJERR_FATAL',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950feafc9cceeada13122b09e4851e3788039a',1,'turbojpeg.h']]], - ['tjerr_5fwarning_172',['TJERR_WARNING',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950fea342dd6e2aedb47bb257b4e7568329b59',1,'turbojpeg.h']]], - ['tjpf_5fabgr_173',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]], - ['tjpf_5fargb_174',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]], - ['tjpf_5fbgr_175',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]], - ['tjpf_5fbgra_176',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]], - ['tjpf_5fbgrx_177',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]], - ['tjpf_5fcmyk_178',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]], - ['tjpf_5fgray_179',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]], - ['tjpf_5frgb_180',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]], - ['tjpf_5frgba_181',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]], - ['tjpf_5frgbx_182',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]], - ['tjpf_5funknown_183',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]], - ['tjpf_5fxbgr_184',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], - ['tjpf_5fxrgb_185',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], - ['tjsamp_5f411_186',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]], - ['tjsamp_5f420_187',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]], - ['tjsamp_5f422_188',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]], - ['tjsamp_5f440_189',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]], - ['tjsamp_5f444_190',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]], - ['tjsamp_5fgray_191',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]], - ['tjxop_5fhflip_192',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]], - ['tjxop_5fnone_193',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]], - ['tjxop_5frot180_194',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]], - ['tjxop_5frot270_195',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]], - ['tjxop_5frot90_196',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]], - ['tjxop_5ftranspose_197',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]], - ['tjxop_5ftransverse_198',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]], - ['tjxop_5fvflip_199',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]] + ['tjcs_5fcmyk_167',['TJCS_CMYK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53',1,'turbojpeg.h']]], + ['tjcs_5fgray_168',['TJCS_GRAY',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a',1,'turbojpeg.h']]], + ['tjcs_5frgb_169',['TJCS_RGB',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a677cb7ccb85c4038ac41964a2e09e555',1,'turbojpeg.h']]], + ['tjcs_5fycbcr_170',['TJCS_YCbCr',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75',1,'turbojpeg.h']]], + ['tjcs_5fycck_171',['TJCS_YCCK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e',1,'turbojpeg.h']]], + ['tjerr_5ffatal_172',['TJERR_FATAL',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950feafc9cceeada13122b09e4851e3788039a',1,'turbojpeg.h']]], + ['tjerr_5fwarning_173',['TJERR_WARNING',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950fea342dd6e2aedb47bb257b4e7568329b59',1,'turbojpeg.h']]], + ['tjpf_5fabgr_174',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]], + ['tjpf_5fargb_175',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]], + ['tjpf_5fbgr_176',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]], + ['tjpf_5fbgra_177',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]], + ['tjpf_5fbgrx_178',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]], + ['tjpf_5fcmyk_179',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]], + ['tjpf_5fgray_180',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]], + ['tjpf_5frgb_181',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]], + ['tjpf_5frgba_182',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]], + ['tjpf_5frgbx_183',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]], + ['tjpf_5funknown_184',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]], + ['tjpf_5fxbgr_185',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], + ['tjpf_5fxrgb_186',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], + ['tjsamp_5f411_187',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]], + ['tjsamp_5f420_188',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]], + ['tjsamp_5f422_189',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]], + ['tjsamp_5f440_190',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]], + ['tjsamp_5f444_191',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]], + ['tjsamp_5fgray_192',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]], + ['tjxop_5fhflip_193',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]], + ['tjxop_5fnone_194',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]], + ['tjxop_5frot180_195',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]], + ['tjxop_5frot270_196',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]], + ['tjxop_5frot90_197',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]], + ['tjxop_5ftranspose_198',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]], + ['tjxop_5ftransverse_199',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]], + ['tjxop_5fvflip_200',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]] ]; diff --git a/doc/html/search/functions_0.js b/doc/html/search/functions_0.js index 121df92e9..4a9ea5b4e 100644 --- a/doc/html/search/functions_0.js +++ b/doc/html/search/functions_0.js @@ -1,31 +1,31 @@ var searchData= [ - ['tjalloc_113',['tjAlloc',['../group___turbo_j_p_e_g.html#gaec627dd4c5f30b7a775a7aea3bec5d83',1,'turbojpeg.h']]], - ['tjbufsize_114',['tjBufSize',['../group___turbo_j_p_e_g.html#ga67ac12fee79073242cb216e07c9f1f90',1,'turbojpeg.h']]], - ['tjbufsizeyuv2_115',['tjBufSizeYUV2',['../group___turbo_j_p_e_g.html#ga2be2b9969d4df9ecce9b05deed273194',1,'turbojpeg.h']]], - ['tjcompress2_116',['tjCompress2',['../group___turbo_j_p_e_g.html#gafbdce0112fd78fd38efae841443a9bcf',1,'turbojpeg.h']]], - ['tjcompressfromyuv_117',['tjCompressFromYUV',['../group___turbo_j_p_e_g.html#ga7622a459b79aa1007e005b58783f875b',1,'turbojpeg.h']]], - ['tjcompressfromyuvplanes_118',['tjCompressFromYUVPlanes',['../group___turbo_j_p_e_g.html#ga29ec5dfbd2d84b8724e951d6fa0d5d9e',1,'turbojpeg.h']]], - ['tjdecodeyuv_119',['tjDecodeYUV',['../group___turbo_j_p_e_g.html#ga70abbf38f77a26fd6da8813bef96f695',1,'turbojpeg.h']]], - ['tjdecodeyuvplanes_120',['tjDecodeYUVPlanes',['../group___turbo_j_p_e_g.html#ga10e837c07fa9d25770565b237d3898d9',1,'turbojpeg.h']]], - ['tjdecompress2_121',['tjDecompress2',['../group___turbo_j_p_e_g.html#gae9eccef8b682a48f43a9117c231ed013',1,'turbojpeg.h']]], - ['tjdecompressheader3_122',['tjDecompressHeader3',['../group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77',1,'turbojpeg.h']]], - ['tjdecompresstoyuv2_123',['tjDecompressToYUV2',['../group___turbo_j_p_e_g.html#ga04d1e839ff9a0860dd1475cff78d3364',1,'turbojpeg.h']]], - ['tjdecompresstoyuvplanes_124',['tjDecompressToYUVPlanes',['../group___turbo_j_p_e_g.html#gaa59f901a5258ada5bd0185ad59368540',1,'turbojpeg.h']]], - ['tjdestroy_125',['tjDestroy',['../group___turbo_j_p_e_g.html#ga75f355fa27225ba1a4ee392c852394d2',1,'turbojpeg.h']]], - ['tjencodeyuv3_126',['tjEncodeYUV3',['../group___turbo_j_p_e_g.html#gac519b922cdf446e97d0cdcba513636bf',1,'turbojpeg.h']]], - ['tjencodeyuvplanes_127',['tjEncodeYUVPlanes',['../group___turbo_j_p_e_g.html#gae2d04c72457fe7f4d60cf78ab1b1feb1',1,'turbojpeg.h']]], - ['tjfree_128',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]], - ['tjgeterrorcode_129',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]], - ['tjgeterrorstr2_130',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]], - ['tjgetscalingfactors_131',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]], - ['tjinitcompress_132',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]], - ['tjinitdecompress_133',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]], - ['tjinittransform_134',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]], - ['tjloadimage_135',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]], - ['tjplaneheight_136',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], - ['tjplanesizeyuv_137',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]], - ['tjplanewidth_138',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], - ['tjsaveimage_139',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]], - ['tjtransform_140',['tjTransform',['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'turbojpeg.h']]] + ['tjalloc_114',['tjAlloc',['../group___turbo_j_p_e_g.html#gaec627dd4c5f30b7a775a7aea3bec5d83',1,'turbojpeg.h']]], + ['tjbufsize_115',['tjBufSize',['../group___turbo_j_p_e_g.html#ga67ac12fee79073242cb216e07c9f1f90',1,'turbojpeg.h']]], + ['tjbufsizeyuv2_116',['tjBufSizeYUV2',['../group___turbo_j_p_e_g.html#ga2be2b9969d4df9ecce9b05deed273194',1,'turbojpeg.h']]], + ['tjcompress2_117',['tjCompress2',['../group___turbo_j_p_e_g.html#gafbdce0112fd78fd38efae841443a9bcf',1,'turbojpeg.h']]], + ['tjcompressfromyuv_118',['tjCompressFromYUV',['../group___turbo_j_p_e_g.html#ga7622a459b79aa1007e005b58783f875b',1,'turbojpeg.h']]], + ['tjcompressfromyuvplanes_119',['tjCompressFromYUVPlanes',['../group___turbo_j_p_e_g.html#ga29ec5dfbd2d84b8724e951d6fa0d5d9e',1,'turbojpeg.h']]], + ['tjdecodeyuv_120',['tjDecodeYUV',['../group___turbo_j_p_e_g.html#ga70abbf38f77a26fd6da8813bef96f695',1,'turbojpeg.h']]], + ['tjdecodeyuvplanes_121',['tjDecodeYUVPlanes',['../group___turbo_j_p_e_g.html#ga10e837c07fa9d25770565b237d3898d9',1,'turbojpeg.h']]], + ['tjdecompress2_122',['tjDecompress2',['../group___turbo_j_p_e_g.html#gae9eccef8b682a48f43a9117c231ed013',1,'turbojpeg.h']]], + ['tjdecompressheader3_123',['tjDecompressHeader3',['../group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77',1,'turbojpeg.h']]], + ['tjdecompresstoyuv2_124',['tjDecompressToYUV2',['../group___turbo_j_p_e_g.html#ga04d1e839ff9a0860dd1475cff78d3364',1,'turbojpeg.h']]], + ['tjdecompresstoyuvplanes_125',['tjDecompressToYUVPlanes',['../group___turbo_j_p_e_g.html#gaa59f901a5258ada5bd0185ad59368540',1,'turbojpeg.h']]], + ['tjdestroy_126',['tjDestroy',['../group___turbo_j_p_e_g.html#ga75f355fa27225ba1a4ee392c852394d2',1,'turbojpeg.h']]], + ['tjencodeyuv3_127',['tjEncodeYUV3',['../group___turbo_j_p_e_g.html#gac519b922cdf446e97d0cdcba513636bf',1,'turbojpeg.h']]], + ['tjencodeyuvplanes_128',['tjEncodeYUVPlanes',['../group___turbo_j_p_e_g.html#gae2d04c72457fe7f4d60cf78ab1b1feb1',1,'turbojpeg.h']]], + ['tjfree_129',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]], + ['tjgeterrorcode_130',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]], + ['tjgeterrorstr2_131',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]], + ['tjgetscalingfactors_132',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]], + ['tjinitcompress_133',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]], + ['tjinitdecompress_134',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]], + ['tjinittransform_135',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]], + ['tjloadimage_136',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]], + ['tjplaneheight_137',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], + ['tjplanesizeyuv_138',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]], + ['tjplanewidth_139',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], + ['tjsaveimage_140',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]], + ['tjtransform_141',['tjTransform',['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'turbojpeg.h']]] ]; diff --git a/doc/html/search/groups_0.js b/doc/html/search/groups_0.js index dccb7c5dc..b4e000d7c 100644 --- a/doc/html/search/groups_0.js +++ b/doc/html/search/groups_0.js @@ -1,4 +1,4 @@ var searchData= [ - ['turbojpeg_200',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]] + ['turbojpeg_201',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]] ]; diff --git a/doc/html/search/typedefs_0.js b/doc/html/search/typedefs_0.js index 8d3d00fbc..bad1a2009 100644 --- a/doc/html/search/typedefs_0.js +++ b/doc/html/search/typedefs_0.js @@ -1,5 +1,5 @@ var searchData= [ - ['tjhandle_159',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]], - ['tjtransform_160',['tjtransform',['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'turbojpeg.h']]] + ['tjhandle_160',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]], + ['tjtransform_161',['tjtransform',['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'turbojpeg.h']]] ]; diff --git a/doc/html/search/variables_0.js b/doc/html/search/variables_0.js index ba55d234f..9ed036c11 100644 --- a/doc/html/search/variables_0.js +++ b/doc/html/search/variables_0.js @@ -1,4 +1,4 @@ var searchData= [ - ['customfilter_141',['customFilter',['../structtjtransform.html#afd7fc262df33f741e120ef4183202ef5',1,'tjtransform']]] + ['customfilter_142',['customFilter',['../structtjtransform.html#afd7fc262df33f741e120ef4183202ef5',1,'tjtransform']]] ]; diff --git a/doc/html/search/variables_1.js b/doc/html/search/variables_1.js index db6fbeab6..3dc210873 100644 --- a/doc/html/search/variables_1.js +++ b/doc/html/search/variables_1.js @@ -1,5 +1,5 @@ var searchData= [ - ['data_142',['data',['../structtjtransform.html#a688fe8f1a8ecc12a538d9e561cf338e3',1,'tjtransform']]], - ['denom_143',['denom',['../structtjscalingfactor.html#aefbcdf3e9e62274b2d312c695f133ce3',1,'tjscalingfactor']]] + ['data_143',['data',['../structtjtransform.html#a688fe8f1a8ecc12a538d9e561cf338e3',1,'tjtransform']]], + ['denom_144',['denom',['../structtjscalingfactor.html#aefbcdf3e9e62274b2d312c695f133ce3',1,'tjscalingfactor']]] ]; diff --git a/doc/html/search/variables_2.js b/doc/html/search/variables_2.js index d9d44197d..f0d8327c7 100644 --- a/doc/html/search/variables_2.js +++ b/doc/html/search/variables_2.js @@ -1,4 +1,4 @@ var searchData= [ - ['h_144',['h',['../structtjregion.html#aecefc45a26f4d8b60dd4d825c1710115',1,'tjregion']]] + ['h_145',['h',['../structtjregion.html#aecefc45a26f4d8b60dd4d825c1710115',1,'tjregion']]] ]; diff --git a/doc/html/search/variables_3.js b/doc/html/search/variables_3.js index ab99353a2..e7192581f 100644 --- a/doc/html/search/variables_3.js +++ b/doc/html/search/variables_3.js @@ -1,4 +1,4 @@ var searchData= [ - ['num_145',['num',['../structtjscalingfactor.html#a9b011e57f981ee23083e2c1aa5e640ec',1,'tjscalingfactor']]] + ['num_146',['num',['../structtjscalingfactor.html#a9b011e57f981ee23083e2c1aa5e640ec',1,'tjscalingfactor']]] ]; diff --git a/doc/html/search/variables_4.js b/doc/html/search/variables_4.js index 1dd2d1889..265062340 100644 --- a/doc/html/search/variables_4.js +++ b/doc/html/search/variables_4.js @@ -1,5 +1,5 @@ var searchData= [ - ['op_146',['op',['../structtjtransform.html#a2525aab4ba6978a1c273f74fef50e498',1,'tjtransform']]], - ['options_147',['options',['../structtjtransform.html#ac0e74655baa4402209a21e1ae481c8f6',1,'tjtransform']]] + ['op_147',['op',['../structtjtransform.html#a2525aab4ba6978a1c273f74fef50e498',1,'tjtransform']]], + ['options_148',['options',['../structtjtransform.html#ac0e74655baa4402209a21e1ae481c8f6',1,'tjtransform']]] ]; diff --git a/doc/html/search/variables_5.js b/doc/html/search/variables_5.js index 48f810326..2639dfd36 100644 --- a/doc/html/search/variables_5.js +++ b/doc/html/search/variables_5.js @@ -1,4 +1,4 @@ var searchData= [ - ['r_148',['r',['../structtjtransform.html#ac324e5e442abec8a961e5bf219db12cf',1,'tjtransform']]] + ['r_149',['r',['../structtjtransform.html#ac324e5e442abec8a961e5bf219db12cf',1,'tjtransform']]] ]; diff --git a/doc/html/search/variables_6.js b/doc/html/search/variables_6.js index 931d45618..50b3fd761 100644 --- a/doc/html/search/variables_6.js +++ b/doc/html/search/variables_6.js @@ -1,10 +1,10 @@ var searchData= [ - ['tjalphaoffset_149',['tjAlphaOffset',['../group___turbo_j_p_e_g.html#ga5af0ab065feefd526debf1e20c43e837',1,'turbojpeg.h']]], - ['tjblueoffset_150',['tjBlueOffset',['../group___turbo_j_p_e_g.html#ga84e2e35d3f08025f976ec1ec53693dea',1,'turbojpeg.h']]], - ['tjgreenoffset_151',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]], - ['tjmcuheight_152',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]], - ['tjmcuwidth_153',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]], - ['tjpixelsize_154',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], - ['tjredoffset_155',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]] + ['tjalphaoffset_150',['tjAlphaOffset',['../group___turbo_j_p_e_g.html#ga5af0ab065feefd526debf1e20c43e837',1,'turbojpeg.h']]], + ['tjblueoffset_151',['tjBlueOffset',['../group___turbo_j_p_e_g.html#ga84e2e35d3f08025f976ec1ec53693dea',1,'turbojpeg.h']]], + ['tjgreenoffset_152',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]], + ['tjmcuheight_153',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]], + ['tjmcuwidth_154',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]], + ['tjpixelsize_155',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], + ['tjredoffset_156',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]] ]; diff --git a/doc/html/search/variables_7.js b/doc/html/search/variables_7.js index bd954b547..cd4a68005 100644 --- a/doc/html/search/variables_7.js +++ b/doc/html/search/variables_7.js @@ -1,4 +1,4 @@ var searchData= [ - ['w_156',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]] + ['w_157',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]] ]; diff --git a/doc/html/search/variables_8.js b/doc/html/search/variables_8.js index 5b6b4c86a..61434f045 100644 --- a/doc/html/search/variables_8.js +++ b/doc/html/search/variables_8.js @@ -1,4 +1,4 @@ var searchData= [ - ['x_157',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]] + ['x_158',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]] ]; diff --git a/doc/html/search/variables_9.js b/doc/html/search/variables_9.js index d0591c58c..32719d415 100644 --- a/doc/html/search/variables_9.js +++ b/doc/html/search/variables_9.js @@ -1,4 +1,4 @@ var searchData= [ - ['y_158',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]] + ['y_159',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]] ]; diff --git a/doc/html/structtjregion.html b/doc/html/structtjregion.html index 12c7a2551..daa206aae 100644 --- a/doc/html/structtjregion.html +++ b/doc/html/structtjregion.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/structtjscalingfactor.html b/doc/html/structtjscalingfactor.html index 432aa2cb8..021a36f0e 100644 --- a/doc/html/structtjscalingfactor.html +++ b/doc/html/structtjscalingfactor.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doc/html/structtjtransform.html b/doc/html/structtjtransform.html index bdf270280..92aa3fa3d 100644 --- a/doc/html/structtjtransform.html +++ b/doc/html/structtjtransform.html @@ -23,7 +23,7 @@
TurboJPEG -  2.0 +  2.1
diff --git a/doxygen.config b/doxygen.config index cb884f9d6..6deb064ec 100644 --- a/doxygen.config +++ b/doxygen.config @@ -1,5 +1,5 @@ PROJECT_NAME = TurboJPEG -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 2.1 OUTPUT_DIRECTORY = doc/ USE_WINDOWS_ENCODING = NO OPTIMIZE_OUTPUT_FOR_C = YES diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt new file mode 100644 index 000000000..dcd19c3a8 --- /dev/null +++ b/fuzz/CMakeLists.txt @@ -0,0 +1,51 @@ +if(NOT ENABLE_STATIC) + message(FATAL_ERROR "Fuzz targets require static libraries.") +endif() +if(NOT WITH_TURBOJPEG) + message(FATAL_ERROR "Fuzz targets require the TurboJPEG API library.") +endif() + +set(FUZZ_BINDIR "" CACHE PATH + "Directory into which fuzz targets should be installed") +if(NOT FUZZ_BINDIR) + message(FATAL_ERROR "FUZZ_BINDIR must be specified.") +endif() +message(STATUS "FUZZ_BINDIR = ${FUZZ_BINDIR}") + +set(FUZZ_LIBRARY "" CACHE STRING + "Path to fuzzer library or flags necessary to link with it") +if(NOT FUZZ_LIBRARY) + message(FATAL_ERROR "FUZZ_LIBRARY must be specified.") +endif() +message(STATUS "FUZZ_LIBRARY = ${FUZZ_LIBRARY}") + +enable_language(CXX) + +set(EFFECTIVE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}") +message(STATUS "C++ Compiler flags = ${EFFECTIVE_CXX_FLAGS}") + +add_executable(cjpeg_fuzzer cjpeg.cc ../cdjpeg.c ../rdbmp.c ../rdgif.c + ../rdppm.c ../rdswitch.c ../rdtarga.c) +set_property(TARGET cjpeg_fuzzer PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) +target_link_libraries(cjpeg_fuzzer ${FUZZ_LIBRARY} jpeg-static) +install(TARGETS cjpeg_fuzzer RUNTIME DESTINATION ${FUZZ_BINDIR}) + +macro(add_fuzz_target target source_file) + add_executable(${target}_fuzzer ${source_file}) + target_link_libraries(${target}_fuzzer ${FUZZ_LIBRARY} turbojpeg-static) + install(TARGETS ${target}_fuzzer RUNTIME DESTINATION ${FUZZ_BINDIR}) +endmacro() + +add_fuzz_target(compress compress.cc) + +add_fuzz_target(compress_yuv compress_yuv.cc) + +# NOTE: This target is named libjpeg_turbo_fuzzer instead of decompress_fuzzer +# in order to preserve the corpora from Google's OSS-Fuzz target for +# libjpeg-turbo, which this target replaces. +add_fuzz_target(libjpeg_turbo decompress.cc) + +add_fuzz_target(decompress_yuv decompress_yuv.cc) + +add_fuzz_target(transform transform.cc) diff --git a/fuzz/build.sh b/fuzz/build.sh new file mode 100644 index 000000000..882ce7dc7 --- /dev/null +++ b/fuzz/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -u +set -e + +cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_STATIC=1 -DENABLE_SHARED=0 \ + -DCMAKE_C_FLAGS_RELWITHDEBINFO="-g -DNDEBUG" \ + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-g -DNDEBUG" -DCMAKE_INSTALL_PREFIX=$WORK \ + -DWITH_FUZZ=1 -DFUZZ_BINDIR=$OUT -DFUZZ_LIBRARY=$LIB_FUZZING_ENGINE +make "-j$(nproc)" "--load-average=$(nproc)" +make install + +cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg_fuzzer_seed_corpus.zip +cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer_seed_corpus.zip +cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer_seed_corpus.zip +cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/libjpeg_turbo_fuzzer_seed_corpus.zip +cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/decompress_yuv_fuzzer_seed_corpus.zip +cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/transform_fuzzer_seed_corpus.zip diff --git a/fuzz/cjpeg.cc b/fuzz/cjpeg.cc new file mode 100644 index 000000000..ee7b7ab8c --- /dev/null +++ b/fuzz/cjpeg.cc @@ -0,0 +1,89 @@ +/* + * Copyright (C)2021 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* This fuzz target wraps cjpeg in order to test esoteric compression options + as well as the GIF and Targa readers. */ + +#define main cjpeg_main +#define CJPEG_FUZZER +extern "C" { +#include "../cjpeg.c" +} +#undef main +#undef CJPEG_FUZZER + +#include +#include + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + char filename[FILENAME_MAX] = { 0 }; + char *argv1[] = { + (char *)"cjpeg", (char *)"-dct", (char *)"float", (char *)"-memdst", + (char *)"-optimize", (char *)"-quality", (char *)"100,99,98", + (char *)"-restart", (char *)"2", (char *)"-sample", (char *)"4x1,2x2,1x2", + (char *)"-targa", NULL + }; + char *argv2[] = { + (char *)"cjpeg", (char *)"-arithmetic", (char *)"-dct", (char *)"float", + (char *)"-memdst", (char *)"-quality", (char *)"90,80,70", (char *)"-rgb", + (char *)"-sample", (char *)"2x2", (char *)"-smooth", (char *)"50", + (char *)"-targa", NULL + }; + int fd = -1; +#if defined(__has_feature) && __has_feature(memory_sanitizer) + char env[18] = "JSIMD_FORCENONE=1"; + + /* The libjpeg-turbo SIMD extensions produce false positives with + MemorySanitizer. */ + putenv(env); +#endif + + snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_cjpeg_fuzz.XXXXXX"); + if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0) + goto bailout; + + argv1[12] = argv2[13] = filename; + + cjpeg_main(13, argv1); + cjpeg_main(14, argv2); + + argv1[12] = argv2[13] = NULL; + argv1[11] = argv2[12] = filename; + + cjpeg_main(12, argv1); + cjpeg_main(13, argv2); + +bailout: + if (fd >= 0) { + close(fd); + if (strlen(filename) > 0) unlink(filename); + } + return 0; +} diff --git a/fuzz/compress.cc b/fuzz/compress.cc new file mode 100644 index 000000000..539932f13 --- /dev/null +++ b/fuzz/compress.cc @@ -0,0 +1,133 @@ +/* + * Copyright (C)2021 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + + +#define NUMTESTS 7 +/* Private flag that triggers different TurboJPEG API behavior when fuzzing */ +#define TJFLAG_FUZZING (1 << 30) + + +struct test { + enum TJPF pf; + enum TJSAMP subsamp; + int quality; +}; + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + tjhandle handle = NULL; + unsigned char *srcBuf = NULL, *dstBuf = NULL; + int width = 0, height = 0, fd = -1, i, ti; + char filename[FILENAME_MAX] = { 0 }; + struct test tests[NUMTESTS] = { + { TJPF_RGB, TJSAMP_444, 100 }, + { TJPF_BGR, TJSAMP_422, 90 }, + { TJPF_RGBX, TJSAMP_420, 80 }, + { TJPF_BGRA, TJSAMP_411, 70 }, + { TJPF_XRGB, TJSAMP_GRAY, 60 }, + { TJPF_GRAY, TJSAMP_GRAY, 50 }, + { TJPF_CMYK, TJSAMP_440, 40 } + }; +#if defined(__has_feature) && __has_feature(memory_sanitizer) + char env[18] = "JSIMD_FORCENONE=1"; + + /* The libjpeg-turbo SIMD extensions produce false positives with + MemorySanitizer. */ + putenv(env); +#endif + + snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_fuzz.XXXXXX"); + if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0) + goto bailout; + + if ((handle = tjInitCompress()) == NULL) + goto bailout; + + for (ti = 0; ti < NUMTESTS; ti++) { + int flags = TJFLAG_FUZZING, sum = 0, pf = tests[ti].pf; + unsigned long dstSize = 0, maxBufSize; + + /* Test non-default compression options on specific iterations. */ + if (ti == 0) + flags |= TJFLAG_BOTTOMUP | TJFLAG_ACCURATEDCT; + else if (ti == 1) + flags |= TJFLAG_PROGRESSIVE; + if (ti != 2) + flags |= TJFLAG_NOREALLOC; + + /* tjLoadImage() refuses to load images larger than 1 Megapixel when + FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is defined (yes, that's a dirty + hack), so we don't need to check the width and height here. */ + if ((srcBuf = tjLoadImage(filename, &width, 1, &height, &pf, + flags)) == NULL) + continue; + + maxBufSize = tjBufSize(width, height, tests[ti].subsamp); + if (flags & TJFLAG_NOREALLOC) { + if ((dstBuf = (unsigned char *)malloc(maxBufSize)) == NULL) + goto bailout; + } else + dstBuf = NULL; + + if (tjCompress2(handle, srcBuf, width, 0, height, pf, &dstBuf, &dstSize, + tests[ti].subsamp, tests[ti].quality, flags) == 0) { + /* Touch all of the output pixels in order to catch uninitialized reads + when using MemorySanitizer. */ + for (i = 0; i < dstSize; i++) + sum += dstBuf[i]; + } + + free(dstBuf); + dstBuf = NULL; + tjFree(srcBuf); + srcBuf = NULL; + + /* Prevent the code above from being optimized out. This test should never + be true, but the compiler doesn't know that. */ + if (sum > 255 * maxBufSize) + goto bailout; + } + +bailout: + free(dstBuf); + tjFree(srcBuf); + if (fd >= 0) { + close(fd); + if (strlen(filename) > 0) unlink(filename); + } + if (handle) tjDestroy(handle); + return 0; +} diff --git a/fuzz/compress_yuv.cc b/fuzz/compress_yuv.cc new file mode 100644 index 000000000..021d66150 --- /dev/null +++ b/fuzz/compress_yuv.cc @@ -0,0 +1,148 @@ +/* + * Copyright (C)2021 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + + +#define NUMTESTS 6 +/* Private flag that triggers different TurboJPEG API behavior when fuzzing */ +#define TJFLAG_FUZZING (1 << 30) + + +struct test { + enum TJPF pf; + enum TJSAMP subsamp; + int quality; +}; + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + tjhandle handle = NULL; + unsigned char *srcBuf = NULL, *dstBuf = NULL, *yuvBuf = NULL; + int width = 0, height = 0, fd = -1, i, ti; + char filename[FILENAME_MAX] = { 0 }; + struct test tests[NUMTESTS] = { + { TJPF_XBGR, TJSAMP_444, 100 }, + { TJPF_XRGB, TJSAMP_422, 90 }, + { TJPF_BGR, TJSAMP_420, 80 }, + { TJPF_RGB, TJSAMP_411, 70 }, + { TJPF_BGR, TJSAMP_GRAY, 60 }, + { TJPF_GRAY, TJSAMP_GRAY, 50 } + }; + char arithEnv[16] = "TJ_ARITHMETIC=0"; + char restartEnv[13] = "TJ_RESTART=0"; +#if defined(__has_feature) && __has_feature(memory_sanitizer) + char simdEnv[18] = "JSIMD_FORCENONE=1"; + + /* The libjpeg-turbo SIMD extensions produce false positives with + MemorySanitizer. */ + putenv(simdEnv); +#endif + putenv(arithEnv); + putenv(restartEnv); + + snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_yuv_fuzz.XXXXXX"); + if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0) + goto bailout; + + if ((handle = tjInitCompress()) == NULL) + goto bailout; + + for (ti = 0; ti < NUMTESTS; ti++) { + int flags = TJFLAG_FUZZING | TJFLAG_NOREALLOC, sum = 0, pf = tests[ti].pf; + unsigned long dstSize = 0, maxBufSize; + + /* Test non-default compression options on specific iterations. */ + if (ti == 0) + flags |= TJFLAG_BOTTOMUP | TJFLAG_ACCURATEDCT; + else if (ti == 1 || ti == 3) + flags |= TJFLAG_PROGRESSIVE; + if (ti == 2 || ti == 3) + arithEnv[14] = '1'; + else + arithEnv[14] = '0'; + if (ti == 1 || ti == 2) + restartEnv[11] = '2'; + else + restartEnv[11] = '0'; + + /* tjLoadImage() refuses to load images larger than 1 Megapixel when + FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is defined (yes, that's a dirty + hack), so we don't need to check the width and height here. */ + if ((srcBuf = tjLoadImage(filename, &width, 1, &height, &pf, + flags)) == NULL) + continue; + + maxBufSize = tjBufSize(width, height, tests[ti].subsamp); + if ((dstBuf = (unsigned char *)malloc(maxBufSize)) == NULL) + goto bailout; + if ((yuvBuf = + (unsigned char *)malloc(tjBufSizeYUV2(width, 1, height, + tests[ti].subsamp))) == NULL) + goto bailout; + + if (tjEncodeYUV3(handle, srcBuf, width, 0, height, pf, yuvBuf, 1, + tests[ti].subsamp, flags) == 0 && + tjCompressFromYUV(handle, yuvBuf, width, 1, height, tests[ti].subsamp, + &dstBuf, &dstSize, tests[ti].quality, flags) == 0) { + /* Touch all of the output pixels in order to catch uninitialized reads + when using MemorySanitizer. */ + for (i = 0; i < dstSize; i++) + sum += dstBuf[i]; + } + + free(dstBuf); + dstBuf = NULL; + free(yuvBuf); + yuvBuf = NULL; + tjFree(srcBuf); + srcBuf = NULL; + + /* Prevent the code above from being optimized out. This test should never + be true, but the compiler doesn't know that. */ + if (sum > 255 * maxBufSize) + goto bailout; + } + +bailout: + free(dstBuf); + free(yuvBuf); + tjFree(srcBuf); + if (fd >= 0) { + close(fd); + if (strlen(filename) > 0) unlink(filename); + } + if (handle) tjDestroy(handle); + return 0; +} diff --git a/fuzz/decompress.cc b/fuzz/decompress.cc new file mode 100644 index 000000000..c7fcb5001 --- /dev/null +++ b/fuzz/decompress.cc @@ -0,0 +1,106 @@ +/* + * Copyright (C)2021 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + + +#define NUMPF 4 + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + tjhandle handle = NULL; + unsigned char *dstBuf = NULL; + int width = 0, height = 0, jpegSubsamp, jpegColorspace, pfi; + /* TJPF_RGB-TJPF_BGR share the same code paths, as do TJPF_RGBX-TJPF_XRGB and + TJPF_RGBA-TJPF_ARGB. Thus, the pixel formats below should be the minimum + necessary to achieve full coverage. */ + enum TJPF pixelFormats[NUMPF] = + { TJPF_RGB, TJPF_BGRX, TJPF_GRAY, TJPF_CMYK }; +#if defined(__has_feature) && __has_feature(memory_sanitizer) + char env[18] = "JSIMD_FORCENONE=1"; + + /* The libjpeg-turbo SIMD extensions produce false positives with + MemorySanitizer. */ + putenv(env); +#endif + + if ((handle = tjInitDecompress()) == NULL) + goto bailout; + + /* We ignore the return value of tjDecompressHeader3(), because some JPEG + images may have unusual subsampling configurations that the TurboJPEG API + cannot identify but can still decompress. */ + tjDecompressHeader3(handle, data, size, &width, &height, &jpegSubsamp, + &jpegColorspace); + + /* Ignore 0-pixel images and images larger than 1 Megapixel, as Google's + OSS-Fuzz target for libjpeg-turbo did. Casting width to (uint64_t) + prevents integer overflow if width * height > INT_MAX. */ + if (width < 1 || height < 1 || (uint64_t)width * height > 1048576) + goto bailout; + + for (pfi = 0; pfi < NUMPF; pfi++) { + int pf = pixelFormats[pfi], flags = TJFLAG_LIMITSCANS, i, sum = 0; + int w = width, h = height; + + /* Test non-default decompression options on the first iteration. */ + if (pfi == 0) + flags |= TJFLAG_BOTTOMUP | TJFLAG_FASTUPSAMPLE | TJFLAG_FASTDCT; + /* Test IDCT scaling on the second iteration. */ + else if (pfi == 1) { + w = (width + 1) / 2; + h = (height + 1) / 2; + } + + if ((dstBuf = (unsigned char *)malloc(w * h * tjPixelSize[pf])) == NULL) + goto bailout; + + if (tjDecompress2(handle, data, size, dstBuf, w, 0, h, pf, flags) == 0) { + /* Touch all of the output pixels in order to catch uninitialized reads + when using MemorySanitizer. */ + for (i = 0; i < w * h * tjPixelSize[pf]; i++) + sum += dstBuf[i]; + } + + free(dstBuf); + dstBuf = NULL; + + /* Prevent the code above from being optimized out. This test should never + be true, but the compiler doesn't know that. */ + if (sum > 255 * 1048576 * tjPixelSize[pf]) + goto bailout; + } + +bailout: + free(dstBuf); + if (handle) tjDestroy(handle); + return 0; +} diff --git a/fuzz/decompress_yuv.cc b/fuzz/decompress_yuv.cc new file mode 100644 index 000000000..d603fd819 --- /dev/null +++ b/fuzz/decompress_yuv.cc @@ -0,0 +1,111 @@ +/* + * Copyright (C)2021 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + + +#define NUMPF 3 + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + tjhandle handle = NULL; + unsigned char *dstBuf = NULL, *yuvBuf = NULL; + int width = 0, height = 0, jpegSubsamp, jpegColorspace, pfi; + /* TJPF_RGB-TJPF_BGR share the same code paths, as do TJPF_RGBX-TJPF_XRGB and + TJPF_RGBA-TJPF_ARGB. Thus, the pixel formats below should be the minimum + necessary to achieve full coverage. */ + enum TJPF pixelFormats[NUMPF] = + { TJPF_BGR, TJPF_XRGB, TJPF_GRAY }; +#if defined(__has_feature) && __has_feature(memory_sanitizer) + char env[18] = "JSIMD_FORCENONE=1"; + + /* The libjpeg-turbo SIMD extensions produce false positives with + MemorySanitizer. */ + putenv(env); +#endif + + if ((handle = tjInitDecompress()) == NULL) + goto bailout; + + if (tjDecompressHeader3(handle, data, size, &width, &height, &jpegSubsamp, + &jpegColorspace) < 0) + goto bailout; + + /* Ignore 0-pixel images and images larger than 1 Megapixel. Casting width + to (uint64_t) prevents integer overflow if width * height > INT_MAX. */ + if (width < 1 || height < 1 || (uint64_t)width * height > 1048576) + goto bailout; + + for (pfi = 0; pfi < NUMPF; pfi++) { + int pf = pixelFormats[pfi], flags = TJFLAG_LIMITSCANS, i, sum = 0; + int w = width, h = height; + + /* Test non-default decompression options on the first iteration. */ + if (pfi == 0) + flags |= TJFLAG_BOTTOMUP | TJFLAG_FASTUPSAMPLE | TJFLAG_FASTDCT; + /* Test IDCT scaling on the second iteration. */ + else if (pfi == 1) { + w = (width + 3) / 4; + h = (height + 3) / 4; + } + + if ((dstBuf = (unsigned char *)malloc(w * h * tjPixelSize[pf])) == NULL) + goto bailout; + if ((yuvBuf = + (unsigned char *)malloc(tjBufSizeYUV2(w, 1, h, jpegSubsamp))) == NULL) + goto bailout; + + if (tjDecompressToYUV2(handle, data, size, yuvBuf, w, 1, h, flags) == 0 && + tjDecodeYUV(handle, yuvBuf, 1, jpegSubsamp, dstBuf, w, 0, h, pf, + flags) == 0) { + /* Touch all of the output pixels in order to catch uninitialized reads + when using MemorySanitizer. */ + for (i = 0; i < w * h * tjPixelSize[pf]; i++) + sum += dstBuf[i]; + } + + free(dstBuf); + dstBuf = NULL; + free(yuvBuf); + yuvBuf = NULL; + + /* Prevent the code above from being optimized out. This test should never + be true, but the compiler doesn't know that. */ + if (sum > 255 * 1048576 * tjPixelSize[pf]) + goto bailout; + } + +bailout: + free(dstBuf); + free(yuvBuf); + if (handle) tjDestroy(handle); + return 0; +} diff --git a/fuzz/transform.cc b/fuzz/transform.cc new file mode 100644 index 000000000..b8a7516d9 --- /dev/null +++ b/fuzz/transform.cc @@ -0,0 +1,135 @@ +/* + * Copyright (C)2021 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + + +#define NUMXFORMS 3 + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + tjhandle handle = NULL; + unsigned char *dstBufs[NUMXFORMS] = { NULL, NULL, NULL }; + unsigned long dstSizes[NUMXFORMS] = { 0, 0, 0 }, maxBufSize; + int width = 0, height = 0, jpegSubsamp, jpegColorspace, i, t; + tjtransform transforms[NUMXFORMS]; +#if defined(__has_feature) && __has_feature(memory_sanitizer) + char env[18] = "JSIMD_FORCENONE=1"; + + /* The libjpeg-turbo SIMD extensions produce false positives with + MemorySanitizer. */ + putenv(env); +#endif + + if ((handle = tjInitTransform()) == NULL) + goto bailout; + + /* We ignore the return value of tjDecompressHeader3(), because some JPEG + images may have unusual subsampling configurations that the TurboJPEG API + cannot identify but can still transform. */ + tjDecompressHeader3(handle, data, size, &width, &height, &jpegSubsamp, + &jpegColorspace); + + /* Ignore 0-pixel images and images larger than 1 Megapixel. Casting width + to (uint64_t) prevents integer overflow if width * height > INT_MAX. */ + if (width < 1 || height < 1 || (uint64_t)width * height > 1048576) + goto bailout; + + if (jpegSubsamp < 0 || jpegSubsamp >= TJ_NUMSAMP) + jpegSubsamp = TJSAMP_444; + + for (t = 0; t < NUMXFORMS; t++) + memset(&transforms[t], 0, sizeof(tjtransform)); + + transforms[0].op = TJXOP_NONE; + transforms[0].options = TJXOPT_PROGRESSIVE | TJXOPT_COPYNONE; + dstBufs[0] = (unsigned char *)malloc(tjBufSize(width, height, jpegSubsamp)); + if (!dstBufs[0]) + goto bailout; + + transforms[1].r.w = (width + 1) / 2; + transforms[1].r.h = (height + 1) / 2; + transforms[1].op = TJXOP_TRANSPOSE; + transforms[1].options = TJXOPT_GRAY | TJXOPT_CROP | TJXOPT_COPYNONE; + dstBufs[1] = + (unsigned char *)malloc(tjBufSize((width + 1) / 2, (height + 1) / 2, + TJSAMP_GRAY)); + if (!dstBufs[1]) + goto bailout; + + transforms[2].op = TJXOP_ROT90; + transforms[2].options = TJXOPT_TRIM | TJXOPT_COPYNONE; + dstBufs[2] = (unsigned char *)malloc(tjBufSize(height, width, jpegSubsamp)); + if (!dstBufs[2]) + goto bailout; + + maxBufSize = tjBufSize(width, height, jpegSubsamp); + + if (tjTransform(handle, data, size, NUMXFORMS, dstBufs, dstSizes, transforms, + TJFLAG_LIMITSCANS | TJFLAG_NOREALLOC) == 0) { + /* Touch all of the output pixels in order to catch uninitialized reads + when using MemorySanitizer. */ + for (t = 0; t < NUMXFORMS; t++) { + int sum = 0; + + for (i = 0; i < dstSizes[t]; i++) + sum += dstBufs[t][i]; + + /* Prevent the code above from being optimized out. This test should + never be true, but the compiler doesn't know that. */ + if (sum > 255 * maxBufSize) + goto bailout; + } + } + + transforms[0].options &= ~TJXOPT_COPYNONE; + free(dstBufs[0]); + dstBufs[0] = NULL; + dstSizes[0] = 0; + + if (tjTransform(handle, data, size, 1, dstBufs, dstSizes, transforms, + TJFLAG_LIMITSCANS) == 0) { + int sum = 0; + + for (i = 0; i < dstSizes[0]; i++) + sum += dstBufs[0][i]; + + if (sum > 255 * maxBufSize) + goto bailout; + } + +bailout: + for (t = 0; t < NUMXFORMS; t++) + free(dstBufs[t]); + if (handle) tjDestroy(handle); + return 0; +} diff --git a/java/TJBench.java b/java/TJBench.java index e43645eaf..0fadab141 100644 --- a/java/TJBench.java +++ b/java/TJBench.java @@ -1,5 +1,6 @@ /* - * Copyright (C)2009-2014, 2016-2019 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2014, 2016-2019, 2021 D. R. Commander. + * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -752,6 +753,8 @@ else if (nsf > 2) { System.out.println("-componly = Stop after running compression tests. Do not test decompression."); System.out.println("-nowrite = Do not write reference or output images (improves consistency"); System.out.println(" of performance measurements.)"); + System.out.println("-limitscans = Refuse to decompress or transform progressive JPEG images that"); + System.out.println(" have an unreasonably large number of scans"); System.out.println("-stoponwarning = Immediately discontinue the current"); System.out.println(" compression/decompression/transform operation if the underlying codec"); System.out.println(" throws a warning (non-fatal error)\n"); @@ -929,6 +932,8 @@ else if (argv[i].equals("411")) compOnly = true; else if (argv[i].equalsIgnoreCase("-nowrite")) write = false; + else if (argv[i].equalsIgnoreCase("-limitscans")) + flags |= TJ.FLAG_LIMITSCANS; else if (argv[i].equalsIgnoreCase("-stoponwarning")) flags |= TJ.FLAG_STOPONWARNING; else usage(); diff --git a/java/doc/constant-values.html b/java/doc/constant-values.html index fb33327f4..07ba05270 100644 --- a/java/doc/constant-values.html +++ b/java/doc/constant-values.html @@ -189,167 +189,174 @@

org.libjpegturbo.*

128 + + +public static final int +FLAG_LIMITSCANS +32768 + + public static final int FLAG_PROGRESSIVE 16384 - + public static final int FLAG_STOPONWARNING 8192 - + public static final int NUMCS 5 - + public static final int NUMERR 2 - + public static final int NUMPF 12 - + public static final int NUMSAMP 6 - + public static final int PF_ABGR 9 - + public static final int PF_ARGB 10 - + public static final int PF_BGR 1 - + public static final int PF_BGRA 8 - + public static final int PF_BGRX 3 - + public static final int PF_CMYK 11 - + public static final int PF_GRAY 6 - + public static final int PF_RGB 0 - + public static final int PF_RGBA 7 - + public static final int PF_RGBX 2 - + public static final int PF_XBGR 4 - + public static final int PF_XRGB 5 - + public static final int SAMP_411 5 - + public static final int SAMP_420 2 - + public static final int SAMP_422 1 - + public static final int SAMP_440 4 - + public static final int SAMP_444 0 - + public static final int diff --git a/java/doc/index-all.html b/java/doc/index-all.html index 366c7ea1f..3a49818e5 100644 --- a/java/doc/index-all.html +++ b/java/doc/index-all.html @@ -337,6 +337,11 @@

F

Deprecated.
+
FLAG_LIMITSCANS - Static variable in class org.libjpegturbo.turbojpeg.TJ
+
+
Limit the number of progressive JPEG scans that the decompression and + transform operations will process.
+
FLAG_PROGRESSIVE - Static variable in class org.libjpegturbo.turbojpeg.TJ
Use progressive entropy coding in JPEG images generated by compression and diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html index 5ca5cc8ca..2a3de371c 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJ.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html @@ -214,145 +214,152 @@

Field Summary

static int +FLAG_LIMITSCANS +
Limit the number of progressive JPEG scans that the decompression and + transform operations will process.
+ + + +static int FLAG_PROGRESSIVE
Use progressive entropy coding in JPEG images generated by compression and transform operations.
- + static int FLAG_STOPONWARNING
Immediately discontinue the current compression/decompression/transform operation if the underlying codec throws a warning (non-fatal error).
- + static int NUMCS
The number of JPEG colorspaces
- + static int NUMERR
The number of error codes
- + static int NUMPF
The number of pixel formats
- + static int NUMSAMP
The number of chrominance subsampling options
- + static int PF_ABGR
ABGR pixel format.
- + static int PF_ARGB
ARGB pixel format.
- + static int PF_BGR
BGR pixel format.
- + static int PF_BGRA
BGRA pixel format.
- + static int PF_BGRX
BGRX pixel format.
- + static int PF_CMYK
CMYK pixel format.
- + static int PF_GRAY
Grayscale pixel format.
- + static int PF_RGB
RGB pixel format.
- + static int PF_RGBA
RGBA pixel format.
- + static int PF_RGBX
RGBX pixel format.
- + static int PF_XBGR
XBGR pixel format.
- + static int PF_XRGB
XRGB pixel format.
- + static int SAMP_411
4:1:1 chrominance subsampling.
- + static int SAMP_420
4:2:0 chrominance subsampling.
- + static int SAMP_422
4:2:2 chrominance subsampling.
- + static int SAMP_440
4:4:0 chrominance subsampling.
- + static int SAMP_444
4:4:4 chrominance subsampling (no chrominance subsampling).
- + static int SAMP_GRAY
Grayscale.
@@ -1013,6 +1020,23 @@

FLAG_PROGRESSIVE

See Also:
Constant Field Values
+ + + +
    +
  • +

    FLAG_LIMITSCANS

    +
    public static final int FLAG_LIMITSCANS
    +
    Limit the number of progressive JPEG scans that the decompression and + transform operations will process. If a progressive JPEG image contains + an unreasonably large number of scans, then this flag will cause the + decompression and transform operations to throw an error. The primary + purpose of this is to allow security-critical applications to guard + against an exploit of the progressive JPEG format described in + this report.
    +
    See Also:
    Constant Field Values
    +
  • +
diff --git a/java/org/libjpegturbo/turbojpeg/TJ.java b/java/org/libjpegturbo/turbojpeg/TJ.java index 63e464b8e..d791e001d 100644 --- a/java/org/libjpegturbo/turbojpeg/TJ.java +++ b/java/org/libjpegturbo/turbojpeg/TJ.java @@ -1,6 +1,6 @@ /* - * Copyright (C)2011-2013, 2017-2018, 2020 D. R. Commander. - * All Rights Reserved. + * Copyright (C)2011-2013, 2017-2018, 2020-2021 D. R. Commander. + * All Rights Reserved. * Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -438,6 +438,16 @@ public static int getAlphaOffset(int pixelFormat) { * reduce compression and decompression performance considerably. */ public static final int FLAG_PROGRESSIVE = 16384; + /** + * Limit the number of progressive JPEG scans that the decompression and + * transform operations will process. If a progressive JPEG image contains + * an unreasonably large number of scans, then this flag will cause the + * decompression and transform operations to throw an error. The primary + * purpose of this is to allow security-critical applications to guard + * against an exploit of the progressive JPEG format described in + * this report. + */ + public static final int FLAG_LIMITSCANS = 32768; /** diff --git a/java/org_libjpegturbo_turbojpeg_TJ.h b/java/org_libjpegturbo_turbojpeg_TJ.h index 84ee87113..8ec4ecd62 100644 --- a/java/org_libjpegturbo_turbojpeg_TJ.h +++ b/java/org_libjpegturbo_turbojpeg_TJ.h @@ -61,12 +61,32 @@ extern "C" { #define org_libjpegturbo_turbojpeg_TJ_CS_YCCK 4L #undef org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP #define org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP 2L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX +#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX 8L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE +#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE 16L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE2 +#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE2 32L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE3 +#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE3 128L #undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE #define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE 256L #undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTDCT #define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTDCT 2048L #undef org_libjpegturbo_turbojpeg_TJ_FLAG_ACCURATEDCT #define org_libjpegturbo_turbojpeg_TJ_FLAG_ACCURATEDCT 4096L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_STOPONWARNING +#define org_libjpegturbo_turbojpeg_TJ_FLAG_STOPONWARNING 8192L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_PROGRESSIVE +#define org_libjpegturbo_turbojpeg_TJ_FLAG_PROGRESSIVE 16384L +#undef org_libjpegturbo_turbojpeg_TJ_FLAG_LIMITSCANS +#define org_libjpegturbo_turbojpeg_TJ_FLAG_LIMITSCANS 32768L +#undef org_libjpegturbo_turbojpeg_TJ_NUMERR +#define org_libjpegturbo_turbojpeg_TJ_NUMERR 2L +#undef org_libjpegturbo_turbojpeg_TJ_ERR_WARNING +#define org_libjpegturbo_turbojpeg_TJ_ERR_WARNING 0L +#undef org_libjpegturbo_turbojpeg_TJ_ERR_FATAL +#define org_libjpegturbo_turbojpeg_TJ_ERR_FATAL 1L /* * Class: org_libjpegturbo_turbojpeg_TJ * Method: bufSize diff --git a/jchuff.c b/jchuff.c index e2d57723c..2bce767eb 100644 --- a/jchuff.c +++ b/jchuff.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2014-2016, 2018-2020, D. R. Commander. + * Copyright (C) 2009-2011, 2014-2016, 2018-2021, D. R. Commander. * Copyright (C) 2015, Matthieu Darbois. * Copyright (C) 2018, Matthias Räncker. * Copyright (C) 2020, Arm Limited. @@ -314,6 +314,7 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno, * this lets us detect duplicate VAL entries here, and later * allows emit_bits to detect any attempt to emit such symbols. */ + MEMZERO(dtbl->ehufco, sizeof(dtbl->ehufco)); MEMZERO(dtbl->ehufsi, sizeof(dtbl->ehufsi)); /* This is also a convenient place to check for out-of-range diff --git a/jcphuff.c b/jcphuff.c index 38e8d02bf..e52114867 100644 --- a/jcphuff.c +++ b/jcphuff.c @@ -876,7 +876,7 @@ encode_mcu_AC_refine_prepare(const JCOEF *block, #define ENCODE_COEFS_AC_REFINE(label) { \ while (zerobits) { \ - int idx = count_zeroes(&zerobits); \ + idx = count_zeroes(&zerobits); \ r += idx; \ cabsvalue += idx; \ signbits >>= idx; \ @@ -933,7 +933,7 @@ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, r; + register int temp, r, idx; char *BR_buffer; unsigned int BR; int Sl = cinfo->Se - cinfo->Ss + 1; @@ -984,7 +984,7 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) if (zerobits) { int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue); - int idx = count_zeroes(&zerobits); + idx = count_zeroes(&zerobits); signbits >>= idx; idx += diff; r += idx; diff --git a/jdhuff.c b/jdhuff.c index b5665d56e..f786c1054 100644 --- a/jdhuff.c +++ b/jdhuff.c @@ -540,6 +540,12 @@ process_restart(j_decompress_ptr cinfo) } +#if defined(__has_feature) +#if __has_feature(undefined_behavior_sanitizer) +__attribute__((no_sanitize("signed-integer-overflow"), + no_sanitize("unsigned-integer-overflow"))) +#endif +#endif LOCAL(boolean) decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -572,11 +578,15 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (entropy->dc_needed[blkn]) { /* Convert DC difference to actual value, update last_dc_val */ int ci = cinfo->MCU_membership[blkn]; - /* This is really just - * s += state.last_dc_val[ci]; - * It is written this way in order to shut up UBSan. + /* Certain malformed JPEG images produce repeated DC coefficient + * differences of 2047 or -2047, which causes state.last_dc_val[ci] to + * grow until it overflows or underflows a 32-bit signed integer. This + * behavior is, to the best of our understanding, innocuous, and it is + * unclear how to work around it without potentially affecting + * performance. Thus, we (hopefully temporarily) suppress UBSan integer + * overflow errors for this function. */ - s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]); + s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; if (block) { /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ @@ -671,7 +681,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (entropy->dc_needed[blkn]) { int ci = cinfo->MCU_membership[blkn]; - s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]); + s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; if (block) (*block)[0] = (JCOEF)s; @@ -778,7 +788,8 @@ decode_mcu(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) } /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; + if (cinfo->restart_interval) + entropy->restarts_to_go--; return TRUE; } diff --git a/jdhuff.h b/jdhuff.h index ac6e0e580..cfa0b7f55 100644 --- a/jdhuff.h +++ b/jdhuff.h @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010-2011, 2015-2016, D. R. Commander. + * Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander. * Copyright (C) 2018, Matthias Räncker. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -234,7 +234,10 @@ slowlabel: \ s |= GET_BITS(1); \ nb++; \ } \ - s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \ + if (nb > 16) \ + s = 0; \ + else \ + s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \ } /* Out-of-line case for Huffman code fetching */ diff --git a/jdphuff.c b/jdphuff.c index 0e981f2f5..c6d82ca14 100644 --- a/jdphuff.c +++ b/jdphuff.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015-2016, 2018-2020, D. R. Commander. + * Copyright (C) 2015-2016, 2018-2021, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -348,7 +348,8 @@ decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) } /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; + if (cinfo->restart_interval) + entropy->restarts_to_go--; return TRUE; } @@ -432,7 +433,8 @@ decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) } /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; + if (cinfo->restart_interval) + entropy->restarts_to_go--; return TRUE; } @@ -483,7 +485,8 @@ decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) BITREAD_SAVE_STATE(cinfo, entropy->bitstate); /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; + if (cinfo->restart_interval) + entropy->restarts_to_go--; return TRUE; } @@ -626,7 +629,8 @@ decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data) } /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; + if (cinfo->restart_interval) + entropy->restarts_to_go--; return TRUE; diff --git a/rdbmp.c b/rdbmp.c index 3f75c1d6e..44a5a88d9 100644 --- a/rdbmp.c +++ b/rdbmp.c @@ -6,7 +6,7 @@ * Modified 2009-2017 by Guido Vollbeding. * libjpeg-turbo Modifications: * Modified 2011 by Siarhei Siamashka. - * Copyright (C) 2015, 2017-2018, D. R. Commander. + * Copyright (C) 2015, 2017-2018, 2021, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -424,14 +424,14 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) (((unsigned int)UCH(array[offset + 2])) << 16) + \ (((unsigned int)UCH(array[offset + 3])) << 24)) - unsigned int bfOffBits; - unsigned int headerSize; + int bfOffBits; + int headerSize; int biWidth; int biHeight; unsigned short biPlanes; unsigned int biCompression; int biXPelsPerMeter, biYPelsPerMeter; - unsigned int biClrUsed = 0; + int biClrUsed = 0; int mapentrysize = 0; /* 0 indicates no colormap */ int bPad; JDIMENSION row_width = 0; @@ -450,7 +450,7 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) if (!ReadOK(source->pub.input_file, bmpinfoheader, 4)) ERREXIT(cinfo, JERR_INPUT_EOF); headerSize = GET_4B(bmpinfoheader, 0); - if (headerSize < 12 || headerSize > 64) + if (headerSize < 12 || headerSize > 64 || (headerSize + 14) > bfOffBits) ERREXIT(cinfo, JERR_BMP_BADHEADER); if (!ReadOK(source->pub.input_file, bmpinfoheader + 4, headerSize - 4)) ERREXIT(cinfo, JERR_INPUT_EOF); @@ -522,6 +522,11 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) if (biWidth <= 0 || biHeight <= 0 || biWidth > 0x7fffffffL || biHeight > 0x7fffffffL) ERREXIT(cinfo, JERR_BMP_EMPTY); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (sinfo->max_pixels && + (unsigned long long)biWidth * biHeight > sinfo->max_pixels) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); +#endif if (biPlanes != 1) ERREXIT(cinfo, JERR_BMP_BADPLANES); @@ -575,7 +580,9 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) cinfo->input_components = 4; else ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - row_width = (JDIMENSION)(biWidth * 3); + if ((unsigned long long)biWidth * 3ULL > 0xFFFFFFFFULL) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + row_width = (JDIMENSION)biWidth * 3; break; case 32: if (cinfo->in_color_space == JCS_UNKNOWN) @@ -586,7 +593,9 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) cinfo->input_components = 4; else ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - row_width = (JDIMENSION)(biWidth * 4); + if ((unsigned long long)biWidth * 4ULL > 0xFFFFFFFFULL) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + row_width = (JDIMENSION)biWidth * 4; break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); @@ -631,7 +640,7 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* Allocate one-row buffer for returned data */ source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(biWidth * cinfo->input_components), (JDIMENSION)1); + (JDIMENSION)biWidth * (JDIMENSION)cinfo->input_components, (JDIMENSION)1); source->pub.buffer_height = 1; cinfo->data_precision = 8; @@ -668,6 +677,9 @@ jinit_read_bmp(j_compress_ptr cinfo, boolean use_inversion_array) /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input_bmp; source->pub.finish_input = finish_input_bmp; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + source->pub.max_pixels = 0; +#endif source->use_inversion_array = use_inversion_array; diff --git a/rdgif.c b/rdgif.c index 8a379fe6d..c814c6b0f 100644 --- a/rdgif.c +++ b/rdgif.c @@ -408,6 +408,11 @@ start_input_gif(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) height = LM_to_uint(hdrbuf, 2); if (width == 0 || height == 0) ERREXIT(cinfo, JERR_GIF_EMPTY); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (sinfo->max_pixels && + (unsigned long long)width * height > sinfo->max_pixels) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); +#endif /* we ignore the color resolution, sort flag, and background color index */ aspectRatio = UCH(hdrbuf[6]); if (aspectRatio != 0 && aspectRatio != 49) @@ -452,6 +457,11 @@ start_input_gif(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) height = LM_to_uint(hdrbuf, 6); if (width == 0 || height == 0) ERREXIT(cinfo, JERR_GIF_EMPTY); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (sinfo->max_pixels && + (unsigned long long)width * height > sinfo->max_pixels) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); +#endif source->is_interlaced = (BitSet(hdrbuf[8], INTERLACE) != 0); /* Read local colormap if header indicates it is present */ @@ -675,6 +685,9 @@ jinit_read_gif(j_compress_ptr cinfo) /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input_gif; source->pub.finish_input = finish_input_gif; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + source->pub.max_pixels = 0; +#endif return (cjpeg_source_ptr)source; } diff --git a/rdppm.c b/rdppm.c index c4c937e8a..9699ca5ee 100644 --- a/rdppm.c +++ b/rdppm.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2009 by Bill Allombert, Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2015-2017, 2020, D. R. Commander. + * Copyright (C) 2015-2017, 2020-2021, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -112,11 +112,10 @@ read_pbm_integer(j_compress_ptr cinfo, FILE *infile, unsigned int maxval) while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { val *= 10; val += ch - '0'; + if (val > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); } - if (val > maxval) - ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); - return val; } @@ -516,6 +515,11 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) register JSAMPLE *rescale = source->rescale; JDIMENSION col; unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) ERREXIT(cinfo, JERR_INPUT_EOF); @@ -527,17 +531,20 @@ get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) temp |= UCH(*bufferptr++); if (temp > maxval) ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); - *ptr++ = rescale[temp]; + ptr[rindex] = rescale[temp]; temp = UCH(*bufferptr++) << 8; temp |= UCH(*bufferptr++); if (temp > maxval) ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); - *ptr++ = rescale[temp]; + ptr[gindex] = rescale[temp]; temp = UCH(*bufferptr++) << 8; temp |= UCH(*bufferptr++); if (temp > maxval) ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); - *ptr++ = rescale[temp]; + ptr[bindex] = rescale[temp]; + if (aindex >= 0) + ptr[aindex] = 0xFF; + ptr += ps; } return 1; } @@ -579,6 +586,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ ERREXIT(cinfo, JERR_PPM_NOT); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (sinfo->max_pixels && (unsigned long long)w * h > sinfo->max_pixels) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); +#endif cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ cinfo->image_width = (JDIMENSION)w; @@ -624,7 +635,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) cinfo->in_color_space = JCS_GRAYSCALE; TRACEMS2(cinfo, 1, JTRC_PGM, w, h); if (maxval > 255) { - source->pub.get_pixel_rows = get_word_gray_row; + if (cinfo->in_color_space == JCS_GRAYSCALE) + source->pub.get_pixel_rows = get_word_gray_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) && cinfo->in_color_space == JCS_GRAYSCALE) { source->pub.get_pixel_rows = get_raw_row; @@ -647,7 +661,10 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) cinfo->in_color_space = JCS_EXT_RGB; TRACEMS2(cinfo, 1, JTRC_PPM, w, h); if (maxval > 255) { - source->pub.get_pixel_rows = get_word_rgb_row; + if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_word_rgb_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) && #if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3 (cinfo->in_color_space == JCS_EXT_RGB || @@ -713,6 +730,8 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (size_t)(((long)MAX(maxval, 255) + 1L) * sizeof(JSAMPLE))); + MEMZERO(source->rescale, (size_t)(((long)MAX(maxval, 255) + 1L) * + sizeof(JSAMPLE))); half_maxval = maxval / 2; for (val = 0; val <= (long)maxval; val++) { /* The multiplication here must be done in 32 bits to avoid overflow */ @@ -750,6 +769,9 @@ jinit_read_ppm(j_compress_ptr cinfo) /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input_ppm; source->pub.finish_input = finish_input_ppm; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + source->pub.max_pixels = 0; +#endif return (cjpeg_source_ptr)source; } diff --git a/rdtarga.c b/rdtarga.c index c17073f5e..8f2d03162 100644 --- a/rdtarga.c +++ b/rdtarga.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2017 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2018, D. R. Commander. + * Copyright (C) 2018, 2021, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -363,6 +363,11 @@ start_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) interlace_type != 0 || /* currently don't allow interlaced image */ width == 0 || height == 0) /* image width/height must be non-zero */ ERREXIT(cinfo, JERR_TGA_BADPARMS); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (sinfo->max_pixels && + (unsigned long long)width * height > sinfo->max_pixels) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); +#endif if (subtype > 8) { /* It's an RLE-coded file */ @@ -493,6 +498,9 @@ jinit_read_targa(j_compress_ptr cinfo) /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input_tga; source->pub.finish_input = finish_input_tga; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + source->pub.max_pixels = 0; +#endif return (cjpeg_source_ptr)source; } diff --git a/simd/CMakeLists.txt b/simd/CMakeLists.txt index 52ae298a9..d08643745 100644 --- a/simd/CMakeLists.txt +++ b/simd/CMakeLists.txt @@ -52,9 +52,9 @@ endif() enable_language(ASM_NASM) message(STATUS "CMAKE_ASM_NASM_COMPILER = ${CMAKE_ASM_NASM_COMPILER}") -if(CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "macho*") +if(CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "^macho") set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DMACHO") -elseif(CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "elf*") +elseif(CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "^elf") set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DELF") set(CMAKE_ASM_NASM_DEBUG_FORMAT "dwarf2") endif() @@ -329,7 +329,7 @@ endif() # MIPS64 (Intrinsics) ############################################################################### -elseif(CPU_TYPE STREQUAL "loongson" OR CPU_TYPE MATCHES "mips64*") +elseif(CPU_TYPE STREQUAL "loongson" OR CPU_TYPE MATCHES "^mips64") set(CMAKE_REQUIRED_FLAGS -Wa,-mloongson-mmi,-mloongson-ext) diff --git a/simd/arm/jchuff.h b/simd/arm/jchuff.h index d30759f52..d4edd5ebc 100644 --- a/simd/arm/jchuff.h +++ b/simd/arm/jchuff.h @@ -6,7 +6,7 @@ * libjpeg-turbo Modifications: * Copyright (C) 2009, 2018, D. R. Commander. * Copyright (C) 2018, Matthias Räncker. - * Copyright (C) 2020, Arm Limited. + * Copyright (C) 2020-2021, Arm Limited. * For conditions of distribution and use, see the accompanying README.ijg * file. */ @@ -56,24 +56,6 @@ typedef struct { */ #if defined(__aarch64__) || defined(_M_ARM64) -#if defined(_MSC_VER) && !defined(__clang__) -#define SPLAT() { \ - buffer[0] = (JOCTET)(put_buffer >> 56); \ - buffer[1] = (JOCTET)(put_buffer >> 48); \ - buffer[2] = (JOCTET)(put_buffer >> 40); \ - buffer[3] = (JOCTET)(put_buffer >> 32); \ - buffer[4] = (JOCTET)(put_buffer >> 24); \ - buffer[5] = (JOCTET)(put_buffer >> 16); \ - buffer[6] = (JOCTET)(put_buffer >> 8); \ - buffer[7] = (JOCTET)(put_buffer ); \ -} -#else -#define SPLAT() { \ - __asm__("rev %x0, %x1" : "=r"(put_buffer) : "r"(put_buffer)); \ - *((uint64_t *)buffer) = put_buffer; \ -} -#endif - #define FLUSH() { \ if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \ EMIT_BYTE(put_buffer >> 56) \ @@ -85,27 +67,13 @@ typedef struct { EMIT_BYTE(put_buffer >> 8) \ EMIT_BYTE(put_buffer ) \ } else { \ - SPLAT() \ + *((uint64_t *)buffer) = BUILTIN_BSWAP64(put_buffer); \ buffer += 8; \ } \ } #else -#if defined(_MSC_VER) && !defined(__clang__) -#define SPLAT() { \ - buffer[0] = (JOCTET)(put_buffer >> 24); \ - buffer[1] = (JOCTET)(put_buffer >> 16); \ - buffer[2] = (JOCTET)(put_buffer >> 8); \ - buffer[3] = (JOCTET)(put_buffer ); \ -} -#else -#define SPLAT() { \ - __asm__("rev %0, %1" : "=r"(put_buffer) : "r"(put_buffer)); \ - *((uint32_t *)buffer) = put_buffer; \ -} -#endif - #define FLUSH() { \ if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \ EMIT_BYTE(put_buffer >> 24) \ @@ -113,7 +81,7 @@ typedef struct { EMIT_BYTE(put_buffer >> 8) \ EMIT_BYTE(put_buffer ) \ } else { \ - SPLAT() \ + *((uint32_t *)buffer) = BUILTIN_BSWAP32(put_buffer); \ buffer += 4; \ } \ } diff --git a/simd/arm/neon-compat.h.in b/simd/arm/neon-compat.h.in index 23d6d28cf..436c402a1 100644 --- a/simd/arm/neon-compat.h.in +++ b/simd/arm/neon-compat.h.in @@ -23,13 +23,17 @@ #cmakedefine HAVE_VLD1_U16_X2 #cmakedefine HAVE_VLD1Q_U8_X4 -/* Define compiler-independent count-leading-zeros macros */ +/* Define compiler-independent count-leading-zeros and byte-swap macros */ #if defined(_MSC_VER) && !defined(__clang__) #define BUILTIN_CLZ(x) _CountLeadingZeros(x) #define BUILTIN_CLZLL(x) _CountLeadingZeros64(x) +#define BUILTIN_BSWAP32(x) _byteswap_ulong(x) +#define BUILTIN_BSWAP64(x) _byteswap_uint64(x) #elif defined(__clang__) || defined(__GNUC__) #define BUILTIN_CLZ(x) __builtin_clz(x) #define BUILTIN_CLZLL(x) __builtin_clzll(x) +#define BUILTIN_BSWAP32(x) __builtin_bswap32(x) +#define BUILTIN_BSWAP64(x) __builtin_bswap64(x) #else #error "Unknown compiler" #endif diff --git a/simd/i386/jcphuff-sse2.asm b/simd/i386/jcphuff-sse2.asm index 8b7317837..c26b48a47 100644 --- a/simd/i386/jcphuff-sse2.asm +++ b/simd/i386/jcphuff-sse2.asm @@ -523,6 +523,8 @@ EXTN(jsimd_encode_mcu_AC_refine_prepare_sse2): add KK, 2 dec K jnz .BLOOPR16 + test LEN, 15 + je .PADDINGR .ELOOPR16: mov LENEND, LEN diff --git a/simd/x86_64/jcphuff-sse2.asm b/simd/x86_64/jcphuff-sse2.asm index 8ed44728f..01b5c0235 100644 --- a/simd/x86_64/jcphuff-sse2.asm +++ b/simd/x86_64/jcphuff-sse2.asm @@ -504,6 +504,8 @@ EXTN(jsimd_encode_mcu_AC_refine_prepare_sse2): add KK, 16 dec K jnz .BLOOPR16 + test LEN, 15 + je .PADDINGR .ELOOPR16: test LEN, 8 jz .TRYR7 diff --git a/testimages/test.scan b/testimages/test.scan index 563446da3..2a8ea7f2e 100644 --- a/testimages/test.scan +++ b/testimages/test.scan @@ -1,5 +1,8 @@ 0 1 2: 0 0 0 0; -0: 1 16 0 0; -0: 17 63 0 0; +0: 1 9 0 0; +0: 10 41 0 2; +0: 10 41 2 1; +0: 10 41 1 0; +0: 42 63 0 0; 1: 1 63 0 0; 2: 1 63 0 0; diff --git a/tjbench.c b/tjbench.c index faad9784b..156c9061d 100644 --- a/tjbench.c +++ b/tjbench.c @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2019 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2019, 2021 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -800,6 +800,8 @@ static void usage(char *progName) printf("-componly = Stop after running compression tests. Do not test decompression.\n"); printf("-nowrite = Do not write reference or output images (improves consistency of\n"); printf(" performance measurements.)\n"); + printf("-limitscans = Refuse to decompress or transform progressive JPEG images that\n"); + printf(" have an unreasonably large number of scans\n"); printf("-stoponwarning = Immediately discontinue the current\n"); printf(" compression/decompression/transform operation if the underlying codec\n"); printf(" throws a warning (non-fatal error)\n\n"); @@ -955,6 +957,8 @@ int main(int argc, char *argv[]) compOnly = 1; else if (!strcasecmp(argv[i], "-nowrite")) doWrite = 0; + else if (!strcasecmp(argv[i], "-limitscans")) + flags |= TJFLAG_LIMITSCANS; else if (!strcasecmp(argv[i], "-stoponwarning")) flags |= TJFLAG_STOPONWARNING; else usage(argv[0]); diff --git a/turbojpeg.c b/turbojpeg.c index 2b97c68be..224107b1c 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2020 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2021 D. R. Commander. All Rights Reserved. * mozjpeg Modifications: * Copyright (C) 2014, Mozilla Corporation. * @@ -114,6 +114,32 @@ typedef struct _tjinstance { boolean isInstanceError; } tjinstance; +struct my_progress_mgr { + struct jpeg_progress_mgr pub; + tjinstance *this; +}; +typedef struct my_progress_mgr *my_progress_ptr; + +static void my_progress_monitor(j_common_ptr dinfo) +{ + my_error_ptr myerr = (my_error_ptr)dinfo->err; + my_progress_ptr myprog = (my_progress_ptr)dinfo->progress; + + if (dinfo->is_decompressor) { + int scan_no = ((j_decompress_ptr)dinfo)->input_scan_number; + + if (scan_no > 500) { + snprintf(myprog->this->errStr, JMSG_LENGTH_MAX, + "Progressive JPEG image has more than 500 scans"); + snprintf(errStr, JMSG_LENGTH_MAX, + "Progressive JPEG image has more than 500 scans"); + myprog->this->isInstanceError = TRUE; + myerr->warning = FALSE; + longjmp(myerr->setjmp_buffer, 1); + } + } +} + static const int pixelsize[TJ_NUMSAMP] = { 3, 3, 3, 1, 3, 3 }; static const JXFORM_CODE xformtypes[TJ_NUMXOP] = { @@ -180,6 +206,11 @@ static int cs2pf[JPEG_NUMCS] = { this->isInstanceError = TRUE; THROWG(m) \ } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +/* Private flag that triggers different TurboJPEG API behavior when fuzzing */ +#define TJFLAG_FUZZING (1 << 30) +#endif + #define GET_INSTANCE(handle) \ tjinstance *this = (tjinstance *)handle; \ j_compress_ptr cinfo = NULL; \ @@ -386,9 +417,9 @@ static int getSubsamp(j_decompress_ptr dinfo) retval = i; break; } } + } } } - } return retval; } @@ -707,7 +738,10 @@ DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, jpeg_finish_compress(cinfo); bailout: - if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo); + if (cinfo->global_state > CSTATE_START) { + if (alloc) (*cinfo->dest->term_destination) (cinfo); + jpeg_abort_compress(cinfo); + } free(row_pointer); if (this->jerr.warning) retval = -1; this->jerr.stopOnWarning = FALSE; @@ -1075,7 +1109,10 @@ DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, jpeg_finish_compress(cinfo); bailout: - if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo); + if (cinfo->global_state > CSTATE_START) { + if (alloc) (*cinfo->dest->term_destination) (cinfo); + jpeg_abort_compress(cinfo); + } for (i = 0; i < MAX_COMPONENTS; i++) { free(tmpbuf[i]); free(inbuf[i]); @@ -1263,6 +1300,7 @@ DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, { JSAMPROW *row_pointer = NULL; int i, retval = 0, jpegwidth, jpegheight, scaledw, scaledh; + struct my_progress_mgr progress; GET_DINSTANCE(handle); this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE; @@ -1279,6 +1317,14 @@ DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); #endif + if (flags & TJFLAG_LIMITSCANS) { + MEMZERO(&progress, sizeof(struct my_progress_mgr)); + progress.pub.progress_monitor = my_progress_monitor; + progress.this = this; + dinfo->progress = &progress.pub; + } else + dinfo->progress = NULL; + if (setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ retval = -1; goto bailout; @@ -1597,6 +1643,7 @@ DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, JSAMPLE *_tmpbuf = NULL, *ptr; JSAMPROW *outbuf[MAX_COMPONENTS], *tmpbuf[MAX_COMPONENTS]; int dctsize; + struct my_progress_mgr progress; GET_DINSTANCE(handle); this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE; @@ -1618,6 +1665,14 @@ DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); #endif + if (flags & TJFLAG_LIMITSCANS) { + MEMZERO(&progress, sizeof(struct my_progress_mgr)); + progress.pub.progress_monitor = my_progress_monitor; + progress.this = this; + dinfo->progress = &progress.pub; + } else + dinfo->progress = NULL; + if (setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ retval = -1; goto bailout; @@ -1855,7 +1910,8 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, { jpeg_transform_info *xinfo = NULL; jvirt_barray_ptr *srccoefs, *dstcoefs; - int retval = 0, i, jpegSubsamp, saveMarkers = 0; + int retval = 0, alloc = 1, i, jpegSubsamp, saveMarkers = 0; + struct my_progress_mgr progress; GET_INSTANCE(handle); this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE; @@ -1872,6 +1928,14 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); #endif + if (flags & TJFLAG_LIMITSCANS) { + MEMZERO(&progress, sizeof(struct my_progress_mgr)); + progress.pub.progress_monitor = my_progress_monitor; + progress.this = this; + dinfo->progress = &progress.pub; + } else + dinfo->progress = NULL; + if ((xinfo = (jpeg_transform_info *)malloc(sizeof(jpeg_transform_info) * n)) == NULL) THROW("tjTransform(): Memory allocation failure"); @@ -1934,7 +1998,7 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, srccoefs = jpeg_read_coefficients(dinfo); for (i = 0; i < n; i++) { - int w, h, alloc = 1; + int w, h; if (!xinfo[i].crop) { w = dinfo->image_width; h = dinfo->image_height; @@ -1992,7 +2056,10 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, jpeg_finish_decompress(dinfo); bailout: - if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo); + if (cinfo->global_state > CSTATE_START) { + if (alloc) (*cinfo->dest->term_destination) (cinfo); + jpeg_abort_compress(cinfo); + } if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); free(xinfo); if (this->jerr.warning) retval = -1; @@ -2052,6 +2119,11 @@ DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, THROWG("tjLoadImage(): Unsupported file type"); src->input_file = file; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Refuse to load images larger than 1 Megapixel when fuzzing. */ + if (flags & TJFLAG_FUZZING) + src->max_pixels = 1048576; +#endif (*src->start_input) (cinfo, src); (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo); diff --git a/turbojpeg.h b/turbojpeg.h index f3209dd34..c2f6b5141 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -1,5 +1,6 @@ /* - * Copyright (C)2009-2015, 2017, 2020 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2015, 2017, 2020-2021 D. R. Commander. + * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -418,6 +419,16 @@ enum TJCS { * reduce compression and decompression performance considerably. */ #define TJFLAG_PROGRESSIVE 16384 +/** + * Limit the number of progressive JPEG scans that the decompression and + * transform functions will process. If a progressive JPEG image contains an + * unreasonably large number of scans, then this flag will cause the + * decompression and transform functions to return an error. The primary + * purpose of this is to allow security-critical applications to guard against + * an exploit of the progressive JPEG format described in + * this report. + */ +#define TJFLAG_LIMITSCANS 32768 /**