ChangeLog.md


Log

Author Commit Date CI Message
DRC bb3ab531 2024-06-19T17:27:01 cjpeg: Don't enable lossless until precision known jpeg_enable_lossless() checks the point transform value against the data precision, so we need to defer calling jpeg_enable_lossless() until after all command-line options have been parsed.
DRC 94c64ead 2024-06-17T20:27:57 Various doc tweaks - "bits per component" = "bits per sample" Describing the data precision of a JPEG image using "bits per component" is technically correct, but "bits per sample" is the terminology that the JPEG-1 spec uses. Also, "bits per component" is more commonly used to describe the precision of packed-pixel formats (as opposed to "bits per pixel") rather than planar formats, in which all components are grouped together. - Unmention legacy display technologies. Colormapped and monochrome displays aren't a thing anymore, and even when they were still a thing, it was possible to display full-color images to them. In 1991, when JPEG decompression time was measured in minutes per megapixel, it made sense to keep a decompressed copy of JPEG images on disk, in a format that could be displayed without further color conversion (since color conversion was slow and memory-intensive.) In 2024, JPEG decompression time is measured in milliseconds per megapixel, and color conversion is even faster. Thus, JPEG images can be decompressed, displayed, and color-converted (if necessary) "on the fly" at speeds too fast for human vision to perceive. (In fact, your TV performs much more complicated decompression algorithms at least 60 times per second.) - Document that color quantization (and associated features), GIF input/output, Targa input/output, and OS/2 BMP input/output are legacy features. Legacy status doesn't necessarily mean that the features are deprecated. Rather, it is meant to discourage users from using features that may be of little or no benefit on modern machines (such as low-quality modes that had significant performance advantages in the early 1990s but no longer do) and that are maintained on a break/fix basis only. - General wordsmithing, grammar/punctuation policing, and formatting tweaks - Clarify which data precisions each cjpeg input format and each djpeg output format supports. - cjpeg.1: Remove unnecessary and impolitic statement about the -targa switch. - Adjust or remove performance claims to reflect the fact that: * On modern machines, the djpeg "-fast" switch has a negligible effect on performance. * There is a measurable difference between the performance of Floyd- Steinberg dithering and no dithering, but it is not likely perceptible to most users. * There is a measurable difference between the performance of 1-pass and 2-pass color quantization, but it is not likely perceptible to most users. * There is a measurable difference between the performance of full-color and grayscale output when decompressing a full-color JPEG image, but it is not likely perceptible to most users. * IDCT scaling does not necessarily improve performance. (It generally does if the scaling factor is <= 1/2 and generally doesn't if the scaling factor is > 1/2, at least on my machine. The performance claim made in jpeg-6b was probably invalidated when we merged the additional scaling factors from jpeg-7.) - Clarify which djpeg switches/output formats cannot be used when decompressing lossless JPEG images. - Remove djpeg hints, since those involve quality vs. speed tradeoffs that are no longer relevant for modern machines. - Remove documentation regarding using color quantization with 16-bit data precision. (Color quantization requires lossy mode.) - Java: Fix typos in TJDecompressor.decompress12() and TJDecompressor.decompress16() documentation. - jpegtran.1: Fix truncated paragraph In a man page, a single quote at the start of a line is interpreted as a macro. Closes #775 - libjpeg.txt: * Mention J16SAMPLE data type (oversight.) * Remove statement about extending jdcolor.c. (libjpeg-turbo is not quite as DIY as libjpeg once was.) * Remove paragraph about tweaking the various typedefs in jmorecfg.h. It is no longer relevant for modern machines. * Remove caveat regarding systems with ints less than 16 bits wide. (ANSI/ISO C requires an int to be at least 16 bits wide, and libjpeg-turbo has never supported non-ANSI compilers.) - usage.txt: * Add copyright header. * Document cjpeg -icc, -memdst, -report, -strict, and -version switches. * Document djpeg -icc, -maxscans, -memsrc, -report, -skip, -crop, -strict, and -version switches. * Document jpegtran -icc, -maxscans, -report, -strict, and -version switches.
DRC 3c17063e 2024-05-27T11:41:35 Guard against dupe SOF w/ incorrect source manager Referring to https://bugzilla.mozilla.org/show_bug.cgi?id=1898606, attempting to decompress a specially-crafted malformed JPEG image (specifically an image with a complete 12-bit Start Of Frame segment followed by an incomplete 8-bit Start Of Frame segment) using the default marker processor, buffered-image mode, and input prefetching triggered the following sequence of events: - When the 12-bit SOF segment was encountered (in the body of jpeg_read_header()), the marker processor's read_markers() method called the get_sof() function, which processed the 12-bit SOF segment and set cinfo->data_precision to 12. - If the application subsequently called jpeg_consume_input() in a loop to prefetch input data, and it didn't stop calling jpeg_consume_input() when the function returned JPEG_REACHED_SOS, then the 8-bit SOF segment was encountered in the body of jpeg_consume_input(). As a result, the marker processor's read_markers() method called get_sof(), which started to process the 8-bit SOF segment and set cinfo->data_precision to 8. - Since the 8-bit SOF segment was incomplete, the end of the JPEG data stream was encountered when get_sof() attempted to read the image height, width, and number of components. - If the fill_input_buffer() method in the application's custom source manager incorrectly returned FALSE in response to a prematurely- terminated JPEG data stream, then get_sof() returned FALSE while attempting to read the image height, width, and number of components (before the duplicate SOF check was reached.) That caused the default marker processor's read_markers() method, and subsequently jpeg_consume_input(), to return JPEG_SUSPENDED. - If the application failed to respond to the JPEG_SUSPENDED return value and subsequently attempted to call jpeg_read_scanlines(), then the data precision check in jpeg_read_scanlines() succeeded (because cinfo->data_precision was now 8.) However, because cinfo->data_precision had been 12 during the previous call to jpeg_start_decompress(), only the 12-bit version of the main controller was initialized, and the cinfo->main->process_data() method was undefined. Thus, a segfault occurred when jpeg_read_scanlines() attempted to invoke that method. Scenarios in which the issue was thwarted: 1. The default source managers handle a prematurely-terminated JPEG data stream by inserting a fake EOI marker into the data stream. Thus, when using one of those source managers, the INPUT_2BYTES() and INPUT_BYTE() macros (which get_sof() invokes to read the image height, width, and number of components) succeeded-- albeit with bogus data, since the fake EOI marker was read into those fields. The duplicate SOF check in get_sof() then failed, generating a fatal libjpeg error. 2. When using a custom source manager that correctly returns TRUE in response to a prematurely-terminated JPEG data stream, the aforementioned INPUT_2BYTES() and INPUT_BYTE() macros also succeeded (albeit with bogus data read from the previous bytes of the data stream), and the duplicate SOF check failed. 3. If the application did not prefetch input data, or if it stopped invoking jpeg_consume_input() when the function returned JPEG_REACHED_SOS, then the duplicate SOF segment was not read prior to the first call to jpeg_read_scanlines(). Thus, the data precision check in jpeg_read_scanlines() failed. If the application instead called jpeg12_read_scanlines() (that is, if it properly supported multiple data precisions), then the duplicate SOF segment was not read until the body of jpeg_finish_decompress(). At that point, its only negative effect was to cause jpeg_finish_decompress() to return FALSE before the duplicate SOF check was reached. In other words, this issue depended not only upon an incorrectly-written source manager but also upon a very specific sequence of API calls. It also depended upon the multi-precision feature introduced in libjpeg-turbo 3.0.x. When using an 8-bit-per-sample build of libjpeg-turbo 2.1.x, jpeg_read_header() failed with "Unsupported JPEG data precision 12" after the 12-bit SOF segment was processed. When using a 12-bit-per-sample build of libjpeg-turbo 2.1.x, the behavior was the same as if the application called jpeg12_read_scanlines() in Scenario 3 above. This commit simply moves the duplicate SOF check to the top of get_sof() so the check will fail before the marker processor attempts to read the duplicate SOF. It should be noted that this issue isn't a libjpeg-turbo bug per se, because it occurs only when the calling application does something it shouldn't. It is, rather, an issue of API hardening/caller-proofing.
DRC bc491b16 2024-05-16T17:32:02 ChangeLog.md: Document previous commit
DRC 6a522fcd 2024-05-02T14:07:45 jpegtran -drop: Ensure all quant tables defined It is possible to craft a malformed JPEG image in which all of the scans contain fewer components than the number of components specified in the Start Of Frame (SOF) segment. Attempting to use such an image as either an input image or a drop image with 'jpegtran -drop' caused a NULL dereference and subsequent segfault in transupp.c:adjust_quant(), so this commit adds appropriate checks to guard against that. Since the issue involved an interface that is only exposed on the jpegtran command line, it did not represent a security risk. 'jpegtran -drop' could not ever be used successfully with images such as the ones described above. This commit simply makes jpegtran fail gracefully rather than crash. Fixes #758
DRC 7bb958b7 2024-03-04T12:12:03 12-bit: Don't gen opt Huff tbls if tbls supplied (regression introduced by e8b40f3c2ba187ba95c13c3e8ce21c8534256df7) The documented behavior of the libjpeg API is to compute optimal Huffman tables when generating 12-bit lossy Huffman-coded JPEG images, unless the calling application supplies its own Huffman tables. However, e8b40f3c2ba187ba95c13c3e8ce21c8534256df7 and 96bc40c1b36775afdbad4ae05a6b3f48e2eebeb9 modified jinit_c_master_control() so that it always set cinfo->optimize_coding to TRUE when generarating 12-bit lossy Huffman-coded JPEG images, which prevented calling applications from supplying custom Huffman tables for such images. This commit modifies jinit_c_master_control() so that it only overrides cinfo->optimize_coding when generating 12-bit lossy Huffman-coded JPEG images if all Huffman table slots are empty or all slots contain default Huffman tables. Determining whether the latter is true requires using memcmp() to compare the allocated Huffman tables with the default Huffman tables, because: - The documented behavior of jpeg_set_defaults() is to initialize any empty Huffman table slot with the default Huffman table corresponding to that slot, regardless of the data precision. There is also no requirement that the data precision be specified prior to calling jpeg_set_defaults(). Thus, there is no reliable way to prevent jpeg_set_defaults() from initializing empty Huffman table slots with default Huffman tables, which are useless for 12-bit data precision. - There is no requirement that custom Huffman tables be defined prior to calling jpeg_set_defaults(). A calling application could call jpeg_set_defaults() and modify the values in the default Huffman tables rather than allocating new tables. Thus, there is no reliable way to detect whether the allocated Huffman tables contain default values without comparing the tables with the default Huffman tables. Fortunately, comparing the allocated Huffman tables with the default Huffman tables is the last stop on the logic train, so it won't happen unless cinfo->data_precision == 12, cinfo->arith_code == FALSE, cinfo->optimize_coding == FALSE, and one or more Huffman tables are allocated. (If the compressor object is reused, this ensures that the full comparison will be performed at most once.) Custom Huffman tables will be flagged as non-default when the first non-default value is encountered, and the worst case (comparing 400 bytes) is very fast on modern CPUs anyhow. Fixes #751
DRC 3202feb0 2024-02-29T16:10:20 x86-64 SIMD: Support CET if C compiler enables it - Detect at configure time, via the __CET__ C preprocessor macro, whether the C compiler will include either indirect branch tracking (IBT) or shadow stack support, and define a NASM macro (__CET__) if so. - Modify the x86-64 SIMD code so that it includes appropriate endbr64 instructions (to support IBT) and an appropriate .note.gnu.property section (to support both IBT and shadow stack) when __CET__ is defined. Closes #350
DRC 17df25f9 2024-01-25T13:52:58 Build/Win: Eliminate MSVC run-time DLL dependency (regression introduced by 1644bdb7d2fac66cd0ce25adef7754e008b5bc1e) Setting a maximum version in cmake_minimum_required() effectively sets the behavior to NEW for all policies introduced in all CMake versions up to and including that maximum version. The NEW behavior for CMP0091, introduced in CMake 3.15, uses CMake variables to specify the MSVC runtime library against which to link, rather than placing the relevant flags in CMAKE_C_FLAGS*. Thus, replacing /MD with /MT in CMAKE_C_FLAGS* no longer has any effect when using CMake 3.15+.
DRC 335ed793 2024-01-19T12:58:13 Assume 3-comp lossls JPEG w/o Adobe marker is RGB libjpeg-turbo always includes Adobe APP14 markers in the lossless JPEG images that it generates, but some compressors (e.g. accusoft PICTools Medical) do not. Fixes #743
DRC 3eee0dd7 2023-11-29T10:03:49 ChangeLog.md: "since" = "relative to"
DRC 55d342c7 2023-11-16T15:36:47 TurboJPEG: Expose/extend hidden "max pixels" param TJPARAM_MAXPIXELS was previously hidden and used only for fuzz testing, but it is potentially useful for calling applications as well, particularly if they want to guard against excessive memory consumption by the tj3LoadImage*() functions. The parameter has also been extended to decompression and lossless transformation functions/methods, mainly as a convenience. (It was already possible for calling applications to impose their own JPEG image size limits by reading the JPEG header prior to decompressing or transforming the image.)
DRC df9dbff8 2023-11-11T12:25:03 TurboJPEG: New param to limit virt array mem usage This corresponds to max_memory_to_use in the jpeg_memory_mgr struct in the libjpeg API, except that the TurboJPEG parameter is specified in megabytes. Because this is 2023 and computers with less than 1 MB of memory are not a thing (at least not within the scope of libjpeg-turbo support), it isn't useful to allow a limit less than 1 MB to be specified. Furthermore, because TurboJPEG parameters are signed integers, if we allowed the memory limit to be specified in bytes, then it would be impossible to specify a limit larger than 2 GB on 64-bit machines. Because max_memory_to_use is a long signed integer, effectively we can specify a limit of up to 2 petabytes on 64-bit machines if the TurboJPEG parameter is specified in megabytes. (2 PB should be enough for anybody, right?) This commit also bumps the TurboJPEG API version to 3.0.1. Since the TurboJPEG API version no longer tracks the libjpeg-turbo version, it makes sense to increment the API revision number when adding constants, to increment the minor version number when adding functions, and to increment the major version number for a complete overhaul. This commit also removes the vestigial TJ_NUMPARAM macro, which was never defined because it proved unnecessary. Partially implements #735
DRC 78eaf0d4 2023-11-07T13:44:40 tj3*YUV8(): Fix int overflow w/ huge row alignment If the align parameter was set to an unreasonably large value, such as 0x2000000, strides[0] * ph0 and strides[1] * ph1 could have overflowed the int datatype and wrapped around when computing (src|dst)Planes[1] and (src|dst)Planes[2] (respectively.) This would have caused (src|dst)Planes[1] and (src|dst)Planes[2] to point to lower addresses in the YUV buffer than expected, so the worst case would have been a visually incorrect output image, not a buffer overrun or other exploitable issue.
DRC da48edfc 2023-10-09T14:13:55 jchuff.c: Fix uninit read w/ AArch64, WITH_SIMD=0 Because of bf01ed2fbc02c15e86f414ff4946b66b4e5a00f1, the simd field in huff_entropy_encoder (and, by extension, the simd field in savable_state) is only initialized if WITH_SIMD is defined. Due to an oversight, the simd field in savable_state was queried in flush_bits() regardless of whether WITH_SIMD was defined. In most cases, both branches of the query have identical code, and the optimizer removes the branch. However, because the legacy Neon GAS Huffman encoder uses the older bit buffer logic from libjpeg-turbo 2.0.x and prior (refer to 087c29e07f7533ec82fd7eb1dafc84c29e7870ec), the branches do not have identical code when building for AArch64 with NEON_INTRINSICS undefined (which will be the case if WITH_SIMD is undefined.) Thus, if libjpeg-turbo was built for AArch64 with the SIMD extensions disabled at build time, it was possible for the Neon GAS branch in flush_bits() to be taken, which would have set put_bits to a value that is incorrect for the C Huffman encoder. Referring to #728, a user reported that this issue sometimes caused libjpeg-turbo to generate bogus JPEG images if it was built for AArch64 without SIMD extensions and subsequently used through the Qt framework. (It should be noted, however, that disabling the SIMD extensions in AArch64 builds of libjpeg-turbo is inadvisable for performance reasons.) I was unable to reproduce the issue on Linux/AArch64 using libjpeg-turbo alone, despite testing various versions of GCC and Clang and various optimization levels. However, the issue is reproducible using MSan with -O0, so this commit also modifies the GitHub Actions workflow so that compiler optimization is disabled in the linux-msan job. That should prevent the issue or similar issues from re-emerging. Fixes #728
DRC c0412b56 2023-09-14T17:19:36 ChangeLog.md: List CVE ID fixed by ccaba5d7 Closes #724
DRC 9b704f96 2023-08-15T11:03:57 Fix block smoothing w/vert.-subsampled prog. JPEGs The 5x5 interblock smoothing implementation, introduced in libjpeg-turbo 2.1, improperly extended the logic from the traditional 3x3 smoothing implementation. Both implementations point prev_block_row and next_block_row to the current block row when processing, respectively, the first and the last block row in the image: if (block_row > 0 || cinfo->output_iMCU_row > 0) prev_block_row = buffer[block_row - 1] + cinfo->master->first_MCU_col[ci]; else prev_block_row = buffer_ptr; if (block_row < block_rows - 1 || cinfo->output_iMCU_row < last_iMCU_row) next_block_row = buffer[block_row + 1] + cinfo->master->first_MCU_col[ci]; else next_block_row = buffer_ptr; 6d91e950c871103a11bac2f10c63bf998796c719 naively extended that logic to accommodate a 5x5 smoothing window: if (block_row > 1 || cinfo->output_iMCU_row > 1) prev_prev_block_row = buffer[block_row - 2] + cinfo->master->first_MCU_col[ci]; else prev_prev_block_row = prev_block_row; if (block_row < block_rows - 2 || cinfo->output_iMCU_row + 1 < last_iMCU_row) next_next_block_row = buffer[block_row + 2] + cinfo->master->first_MCU_col[ci]; else next_next_block_row = next_block_row; However, this new logic was only correct if block_rows == 1, so the values of prev_prev_block_row and next_next_block_row were incorrect when processing, respectively, the second and second to last iMCU rows in a vertically-subsampled progressive JPEG image. The intent was to: - point prev_block_row to the current block row when processing the first block row in the image, - point prev_prev_block_row to prev_block_row when processing the first two block rows in the image, - point next_block_row to the current block row when processing the last block row in the image, and - point next_next_block_row to next_block_row when processing the last two block rows in the image. This commit modifies decompress_smooth_data() so that it computes the current block row's position relative to the whole image and sets the block row pointers based on that value. This commit also restores a line of code that was accidentally deleted by 6d91e950c871103a11bac2f10c63bf998796c719: access_rows += compptr->v_samp_factor; /* prior iMCU row too */ access_rows is merely a sanity check that tells the access_virt_barray() method to generate an error if accessing the specified number of rows would cause a buffer overrun. Essentially, it is a belt-and-suspenders measure to ensure that j*init_d_coef_controller() allocated enough rows for the full-image virtual array. Thus, excluding that line of code did not cause an observable issue. This commit also documents dbae59281fdc6b3a6304a40134e8576d50d662c0 in the change log. Fixes #721
DRC 7b844bfd 2023-07-28T11:46:10 x86-64 SIMD: Use std stack frame/prologue/epilogue This allows debuggers and profilers to reliably capture backtraces from within the x86-64 SIMD functions. In places where rbp was previously used to access temporary variables (after stack alignment), we now use r15 and save/restore it accordingly. The total amount of work is approximately the same, because the previous code pushed the pre-alignment stack pointer to the aligned stack. The new prologue and epilogue actually have fewer instructions. Also note that the {un}collect_args macros now use rbp instead of rax to access arguments passed on the stack, so we save a few instructions there as well. Based on: https://github.com/alk/libjpeg-turbo/commit/debcc7c3b436467aea8d02c66a514c5099d0ad37 Closes #707 Closes #708
DRC e0c53aa3 2023-06-30T17:58:45 jchuff.c: Test for out-of-range coefficients Restore two coefficient range checks from libjpeg to the C baseline Huffman encoder. This fixes an issue (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60253) whereby the encoder could read from uninitialized memory when attempting to transform a specially-crafted malformed arithmetic-coded JPEG source image into a baseline Huffman-coded JPEG destination image with default Huffman tables. More specifically, the out-of-range coefficients caused r to equal 256, which overflowed the actbl->ehufsi[] array. Because the overflow was contained within the huff_entropy_encoder structure, this issue was not exploitable (nor was it observable at all on x86 or Arm CPUs unless JSIMD_NOHUFFENC=1 or JSIMD_FORCENONE=1 was set in the environment or unless libjpeg-turbo was built with WITH_SIMD=0.) The fix is performance-neutral (+/- 1-2%) for x86-64 code and causes a 0-4% (avg. 1-2%, +/- 1-2%) compression regression for i386 code on Intel CPUs when the C baseline Huffman encoder is used (JSIMD_NOHUFFENC=1). The fix is performance-neutral (+/- 1-2%) on Intel CPUs when all of the libjpeg-turbo SIMD extensions are disabled (JSIMD_FORCENONE=1). The fix causes a 0-2% (avg. <1%, +/- 1%) compression regression for PowerPC code.
DRC 240a5a5c 2023-06-29T17:45:07 ChangeLog.md: Fix typo
DRC 71738892 2023-06-29T16:31:37 djpeg: Fix -map option with 12-bit data precision
DRC bf9f319c 2023-06-29T16:07:42 Disallow color quantization with lossless decomp Color quantization is a legacy feature that serves little or no purpose with lossless JPEG images. 9f756bc67a84d4566bf74a0c2432aa55da404021 eliminated interaction issues between the lossless decompressor and the color quantizers related to out-of-range 12-bit samples, but referring to #701, other interaction issues apparently still exist. Such issues are likely, given the fact that the color quantizers were not designed with lossless decompression in mind. This commit reverts 9f756bc67a84d4566bf74a0c2432aa55da404021, since the issues it fixed are no longer relevant because of this commit and 2192560d74e6e6cf99dd05928885573be00a8208. Fixed #672 Fixes #673 Fixes #674 Fixes #676 Fixes #677 Fixes #678 Fixes #679 Fixes #681 Fixes #683 Fixes #701
DRC c8d52f1c 2023-06-26T11:53:03 tj3Transform: Calc dst buf size from xformed dims When used with TJPARAM_NOREALLOC and with TJXOP_TRANSPOSE, TJXOP_TRANSVERSE, TJXOP_ROT90, or TJXOP_ROT270, tj3Transform() incorrectly based the destination buffer size for a transform on the source image dimensions rather than the transformed image dimensions. This was apparently a long-standing bug that had existed in the tj*Transform() function since its inception. As initially implemented in the evolving libjpeg-turbo v1.2 code base, tjTransform() required dstSizes[i] to be set regardless of whether TJFLAG_NOREALLOC (the predecessor to TJPARAM_NOREALLOC) was set. ff78e37595c8462f64fd100f928aa1d08539527e, which was introduced later in the evolving libjpeg-turbo v1.2 code base, removed that requirement and planted the seed for the bug. However, the bug was not activated until 9b49f0e4c77c727648c6d3a4915eefdf5436de4a was introduced still later in the evolving libjpeg-turbo v1.2 code base, adding a subsampling type argument to the (new at the time) tjBufSize() function and thus making the width and height arguments no longer commutative. The bug opened up the possibility that a JPEG source image could cause tj3Transform() to overflow the destination buffer for a transform if all of the following were true: - The JPEG source image used 4:2:2, 4:4:0, 4:1:1, or 4:4:1 subsampling. (These are the only subsampling types for which the width and height arguments to tj3JPEGBufSize() are not commutative.) - The width and height of the JPEG source image were such that tj3JPEGBufSize(height, width, subsamplingType) returned a smaller value than tj3JPEGBufSize(width, height, subsamplingType). - The JPEG source image contained enough metadata that the size of the transformed image was larger than tj3JPEGBufSize(height, width, subsamplingType). - TJPARAM_NOREALLOC was set. - TJXOP_TRANSPOSE, TJXOP_TRANSVERSE, TJXOP_ROT90, or TJXOP_ROT270 was used. - TJXOPT_COPYNONE was not set. - TJXOPT_CROP was not set. - The calling program allocated tj3JPEGBufSize(height, width, subsamplingType) bytes for the destination buffer, as the API documentation instructs. The API documentation cautions that JPEG source images containing a large amount of extraneous metadata (EXIF, IPTC, ICC, etc.) cannot reliably be transformed if TJPARAM_NOREALLOC is set and TJXOPT_COPYNONE is not set. Irrespective of the bug, there are still cases in which a JPEG source image with a large amount of metadata can, when transformed, exceed the worst-case transformed JPEG image size. For instance, if you try to losslessly crop a JPEG image with 3 kB of EXIF data to 16x16 pixels, then you are guaranteed to exceed the worst-case 16x16 JPEG image size unless you discard the EXIF data. Even without the bug, tj3Transform() will still fail with "Buffer passed to JPEG library is too small" when attempting to transform JPEG source images that meet the aforementioned criteria. The bug is that the function segfaults rather than failing gracefully, but the chances of that occurring in a real-world application are very slim. Any real-world application developers who attempted to transform arbitrary JPEG source images with TJPARAM_NOREALLOC set would very quickly realize that they cannot reliably do that without also setting TJXOPT_COPYNONE. Thus, I posit that the actual risk posed by this bug is low. Applications such as web browsers that are the most exposed to security risks from arbitrary JPEG source images do not use the TurboJPEG lossless transform feature. (None of those applications even use the TurboJPEG API, to the best of my knowledge, and the public libjpeg API has no equivalent transform function.) Our only command-line interface to the tj3Transform() function, TJBench, was not exposed to the bug because it had a compatible bug whereby it allocated the JPEG destination buffer to the same size that tj3Transform() erroneously expected. The TurboJPEG Java API was also not exposed to the bug because of a similar compatible bug in the Java_org_libjpegturbo_turbojpeg_TJTransformer_transform() JNI function. (This commit fixes both compatible bugs.) In short, best practices for tj3Transform() are to use TJPARAM_NOREALLOC only with JPEG source images that are known to be free of metadata (such as images generated by tj3Compress*()) or to use TJXOPT_COPYNONE along with TJPARAM_NOREALLOC. Still, however, the function shouldn't segfault as long as the calling program allocates the suggested amount of space for the JPEG destination buffer. Usability notes: tj3Transform() could hypothetically require dstSizes[i] to be set regardless of the value of TJPARAM_NOREALLOC, but there are usability pitfalls either way. The main pitfall I sought to avoid with ff78e37595c8462f64fd100f928aa1d08539527e was a calling program failing to set dstSizes[i] at all, thus leaving its value undefined. It could be argued that requiring dstSizes[i] to be set in all cases is more consistent, but it could also be argued that not requiring it to be set when TJPARAM_NOREALLOC is set is more user-proof. tj3Transform() could also hypothetically set TJXOPT_COPYNONE automatically when TJPARAM_NOREALLOC is set, but that could lead to user confusion. Ultimately, I would like to address these issues in TurboJPEG v4 by using managed buffer objects, but that would be an extensive overhaul.
DRC 36aaeebb 2023-05-30T17:46:58 ChangeLog.md: List CVE ID fixed by 9f756bc6
DRC 3a536273 2023-04-06T18:33:41 jpeg_crop_scanline: Fix calc w/sclg + 2x4,4x2 samp When computing the downsampled width for a particular component, jpeg_crop_scanline() needs to take into account the fact that the libjpeg code uses a combination of IDCT scaling and upsampling to implement 4x2 and 2x4 upsampling with certain decompression scaling factors. Failing to account for that led to incomplete upsampling of 4x2- or 2x4-subsampled components, which caused the color converter to read from uninitialized memory. With 12-bit data precision, this caused a buffer overrun or underrun and subsequent segfault if the uninitialized memory contained a value that was outside of the valid sample range (because the color converter uses the value as an array index.) Fixes #669
DRC 62590d42 2023-04-04T19:06:20 Decomp: Don't enable 2-pass color quant w/ RGB565 The 2-pass color quantization algorithm assumes 3-sample pixels. RGB565 is the only 3-component colorspace that doesn't have 3-sample pixels, so we need to treat it as a special case when determining whether to enable 2-pass color quantization. Otherwise, attempting to initialize 2-pass color quantization with an RGB565 output buffer could cause prescan_quantize() to read from uninitialized memory and subsequently underflow/overflow the histogram array. djpeg is supposed to fail gracefully if both -rgb565 and -colors are specified, because none of its destination managers (image writers) support color quantization with RGB565. However, prescan_quantize() was called before that could occur. It is possible but very unlikely that these issues could have been reproduced in applications other than djpeg. The issues involve the use of two features (12-bit precision and RGB565) that are incompatible, and they also involve the use of two rarely-used legacy features (RGB565 and color quantization) that don't make much sense when combined. Fixes #668 Fixes #671 Fixes #680
DRC 9f756bc6 2023-04-04T13:53:21 Lossless decomp: Range-limit 12-bit samples 12-bit is the only data precision for which the range of the sample data type exceeds the valid sample range, so it is possible to craft a 12-bit lossless JPEG image that contains out-of-range 12-bit samples. Attempting to decompress such an image using color quantization or merged upsampling (NOTE: libjpeg-turbo cannot generate YCbCr or subsampled lossless JPEG images, but it can decompress them) caused segfaults or buffer overruns when those algorithms attempted to use the out-of-range sample values as array indices. This commit modifies the lossless decompressor so that it range-limits the output of the scaler when using 12-bit samples. Fixes #670 Fixes #672 Fixes #673 Fixes #674 Fixes #675 Fixes #676 Fixes #677 Fixes #678 Fixes #679 Fixes #681 Fixes #683
DRC fc881ebb 2023-03-09T20:55:43 TurboJPEG: Implement 4:4:1 chrominance subsampling This allows losslessly transposed or rotated 4:1:1 JPEG images to be losslessly cropped, partially decompressed, or decompressed to planar YUV images. Because tj3Transform() allows multiple lossless transformations to be chained together, all subsampling options need to have a corresponding transposed subsampling option. (This is why 4:4:0 was originally implemented as well.) Otherwise, the documentation would be technically incorrect. It says that images with unknown subsampling types cannot be losslessly cropped, partially decompressed, or decompressed to planar YUV images, but it doesn't say anything about images with known subsampling types whose subsampling type becomes unknown if the image is rotated or transposed. This is one of those situations in which it is easier to implement a feature that works around the problem than to document the problem. Closes #659
DRC 0827eaff 2023-03-09T21:04:40 ChangeLog.md: Add literal vers # to 3.0 beta2 hdr (per our convention)
DRC 6c610333 2023-02-08T09:23:51 ChangeLog.md: Document 4e028ecd + bump version to 3.0 beta2
DRC fd8c4da0 2023-01-27T14:05:07 Bump revision to 2.1.90 to prepare for beta + acknowledge upcoming 2.1.5 release
DRC db9f297f 2023-01-27T07:10:49 ChangeLog.md: Document TurboJPEG 3 API overhaul
DRC 7ab6222c 2023-01-20T14:09:25 Merge branch 'main' into dev
DRC 98a64558 2023-01-20T13:14:11 TJBench: Set TJ*OPT_PROGRESSIVE with -progressive The documented behavior of the -progressive option is to use progressive entropy coding in JPEG images generated by compression and transform operations. However, setting TJFLAG_PROGRESSIVE was insufficient to accomplish that, because TJBench doesn't enable lossless transformation if xformOpt == 0.
DRC b99e7590 2023-01-20T10:50:21 TJBench/Java: Fix parsing of quality ranges
DRC c7c02d92 2023-01-17T18:31:31 Merge branch 'main' into dev
DRC 08cbc233 2023-01-17T11:04:38 12-bit: Set alpha channel to 4095 rather than 255
DRC d4589f4f 2023-01-14T18:07:53 Merge branch 'main' into dev
DRC 94a2b953 2023-01-11T15:01:35 tjDecompressToYUV2: Use scaled dims for plane calc The documented behavior of the function is to use decompression scaling to generate the largest possible image that will fit within the desired image dimensions. Thus, if the desired image dimensions are larger than the scaled image dimensions, then tjDecompressToYUV2() should use the scaled image dimensions when computing the plane pointers and strides to pass to tjDecompressToYUVPlanes(). Note that this bug was not previously detected, because tjunittest and tjbench always passed the scaled image dimensions to tjDecompressToYUV2().
DRC 9a146f0f 2023-01-06T10:29:10 TurboJPEG: Numerous documentation improvements - Wordsmithing, formatting, and grammar tweaks - Various clarifications and corrections, including specifying whether a particular buffer or image is used as a source or destination - Accommodate/mention features that were introduced since the API documentation was created. - For clarity, use "packed-pixel" to describe uncompressed source/destination images that are not planar YUV. - Use "row" rather than "line" to refer to a single horizontal group of pixels or component values, for consistency with the libjpeg API documentation. (libjpeg also uses "scanline", which is a more archaic term.) - Use "alignment" rather than "padding" to refer to the number of bytes by which a row's width is evenly divisible. This consistifies the documention of the YUV functions and tjLoadImage(). ("Padding" typically refers to the number of bytes added to each row, which is not the same thing.) - Remove all references to "the underlying codec." Although the TurboJPEG API originated as a cross-platform wrapper for the Intel Integrated Performance Primitives, Sun mediaLib, QuickTime, and libjpeg, none of those TurboJPEG implementations has been maintained since 2009. Nothing would prevent someone from implementing the TurboJPEG API without libjpeg-turbo, but such an implementation would not necessarily have an "underlying codec." (It could be fully self-contained.) - Use "destination image" rather than "output image", for consistency, or describe the type of image that will be output. - Avoid the term "image buffer" and instead use "byte buffer" to refer to buffers that will hold JPEG images, or describe the type of image that will be contained in the buffer. (The Java documentation doesn't use "byte buffer", because the buffer arrays literally have "byte" in front of them, and since Java doesn't have pointers, it is not possible for mere mortals to store any other type of data in those arrays.) - C: Use "unified" to describe YUV images stored in a single buffer, for consistency with the Java documentation. - Use "planar YUV" rather than "YUV planar". Is is our convention to describe images using {component layout} {colorspace/pixel format} {image function}, e.g. "packed-pixel RGB source image" or "planar YUV destination image." - C: Document the TurboJPEG API version in which a particular function or macro was introduced, and reorder the backward compatibility function stubs in turbojpeg.h alphabetically by API version. - C: Use Markdown rather than HTML tags, where possible, in the Doxygen comments.
DRC d2608583 2023-01-05T10:51:12 TurboJPEG: Ensure 'pad' arg is a power of 2 Because the PAD() macro can only handle powers of 2, this is a necessary restriction (and a documented one, except in the case of tjCompressFromYUV()-- oops.) Failing to check the 'pad' argument caused tjBufSizeYUV2() to return bogus results if 'pad' was less than 1 or otherwise not a power of 2. tjEncodeYUV3() and tjDecodeYUV() effectively treated a 'pad' value of 0 as unpadded, but that was subtle and undocumented behavior. tjCompressFromYUV() did not check whether 'pad' was a power of 2, so the strides passed to tjCompressFromYUVPlanes() would have been incorrect if 'pad' was not a power of 2. That would not have caused tjCompressFromYUV() to overrun the source buffer, as long as the calling application allocated the buffer based on the return value of tjBufSizeYUV2() (which computes the strides in the same manner as tjCompressFromYUV().) However, if the calling application attempted to initialize the source buffer using correctly-computed strides, then it could have overrun its own buffer in certain cases or produced incorrect JPEG images in others. Realistically, there is no reason why an application would want to pass a non-power-of-2 'pad' value to a TurboJPEG API function, so this commit is about user-proofing the API rather than fixing any known issue.
DRC 2241434e 2022-12-15T12:20:50 16-bit lossless JPEG support
DRC 80352340 2022-12-07T14:11:37 Merge branch 'main' into dev
DRC dc4a93fa 2022-12-07T13:37:16 jpegtran: Fix FPE w/ -drop & -trim on corrupt JPEG requant_comp() in transupp.c, a function that supports the jpegtran -drop option, borrows code from the C quantization function in order to re-quantize the coefficients from the dropped image. However, the function does not guard against the possibility that a corrupt source image could inject quantization table values equal to 0, thus causing a divide-by-zero error. Since this error affected only jpegtran and not any of the libraries (the tjTransform() function in the TurboJPEG API does not expose the image drop feature), it did not represent a security risk. In fact, this commit does not change the output of jpegtran when attempting to transform the aforementioned corrupt source image. It merely eliminates the floating point exception. Like most issues of this type, however, eliminating the error prevents it from hiding legitimate security issues that may later be introduced. Fixes #635 Fixes #636
DRC 5da86f74 2022-12-07T09:45:33 ChangeLog.md: List CVE ID fixed by 9120a247
DRC 7bb5cb56 2022-12-07T09:39:03 ChangeLog.md: List CVE ID fixed by f35fd27e
DRC e7a248eb 2022-11-29T01:08:27 Merge branch 'main' into dev
DRC 45cd2ded 2022-11-28T21:02:42 12-bit: Prevent RGB-to-YCC table overrun/underrun cjpeg relies on the various file I/O modules to range-limit the input samples, but no range limiting is performed by the jpeg_write_scanlines() function itself. With 8-bit samples, that isn't a problem, because sample values > MAXJSAMPLE will overflow the data type and wrap around to 0. With 12-bit samples, however, it is possible to pass sample values < 0 or > 4095 to jpeg_write_scanlines(), which would cause the RGB-to-YCbCr color converter to underflow or overflow the RGB-to-YCbCr conversion tables. That issue has existed in libjpeg all along. This commit mitigates the issue by masking off all but the lowest 12 bits of each 12-bit input sample prior to using the input sample value to index the RGB-to-YCbCr conversion tables. Fixes #633
DRC 98ff1fd1 2022-11-21T20:57:39 TurboJPEG: Add lossless JPEG detection capability Add a new TurboJPEG C API function (tjDecompressHeader4()) and Java API method (TJDecompressor.getFlags()) that return the bitwise OR of any flags that are relevant to the JPEG image being decompressed (currently TJFLAG_PROGRESSIVE, TJFLAG_ARITHMETIC, TJFLAG_LOSSLESS, and their Java equivalents.) This allows a calling program to determine whether the image being decompressed is a lossless JPEG image, which means that the decompression scaling feature will not be available and that a full-sized destination buffer should be allocated. More specifically, this fixes a buffer overrun in TJBench, TJExample, and the decompress* fuzz targets that occurred when attempting (in vain) to decompress a lossless JPEG image with decompression scaling enabled.
DRC 25ccad99 2022-11-16T15:57:25 TurboJPEG: 8-bit lossless JPEG support
DRC 6002720c 2022-11-15T23:10:35 TurboJPEG: Opt. enable arithmetic entropy coding
DRC ed73fdc9 2022-11-15T21:28:01 Merge branch 'main' into dev
DRC 78a36f6d 2022-11-15T17:01:17 Fix buffer overrun in 12-bit prog Huffman encoder Regression introduced by 16bd984557fa2c490be0b9665e2ea0d4274528a8 and 5b177b3cab5cfb661256c1e74df160158ec6c34e The pre-computed absolute values used in encode_mcu_AC_first() and encode_mcu_AC_refine() were stored in a JCOEF (signed short) array. When attempting to losslessly transform a specially-crafted malformed 12-bit JPEG image with a coefficient value of -32768 into a progressive 12-bit JPEG image, the progressive Huffman encoder attempted to store the absolute value of -32768 in the JCOEF array, thus overflowing the 16-bit signed data type. Therefore, at this point in the code: https://github.com/libjpeg-turbo/libjpeg-turbo/blob/8c5e78ce292c1642057102eac42f12ab57964293/jcphuff.c#L889 the absolute value was read as -32768, which caused the test at https://github.com/libjpeg-turbo/libjpeg-turbo/blob/8c5e78ce292c1642057102eac42f12ab57964293/jcphuff.c#L896 to fail, falling through to https://github.com/libjpeg-turbo/libjpeg-turbo/blob/8c5e78ce292c1642057102eac42f12ab57964293/jcphuff.c#L908 with an overly large value of r (46) that, when shifted left four places, incremented, and passed to emit_symbol(), exceeded the maximum index (255) for the derived code tables. Fortunately, the buffer overrun was fully contained within phuff_entropy_encoder, so the issue did not generate a segfault or other user-visible errant behavior, but it did cause a UBSan failure that was detected by OSS-Fuzz. This commit introduces an unsigned JCOEF (UJCOEF) data type and uses it to store the absolute values of DCT coefficients computed by the AC_first_prepare() and AC_refine_prepare() methods. Note that the changes to the Arm Neon progressive Huffman encoder extensions cause signed 16-bit instructions to be replaced with equivalent unsigned 16-bit instructions, so the changes should be performance-neutral. Based on: https://github.com/mayeut/libjpeg-turbo/commit/bbf61c0382c4f8bd1f1cfc666467581496c2fb7c Closes #628
DRC 1926ab41 2022-11-14T16:31:41 ChangeLog.md: Multi-precision feature wordsmithing - Because of b5a9ef64ea299423b7fb46c47f4a70697a442dd4, "by default" is no longer applicable. (12-bit-per-component JPEG support is now part of the core libjpeg-turbo functionality and cannot be disabled.) - Change awkward "can be used to enable the creation of" to less awkward "can be used to create".
DRC 97772cba 2022-11-14T15:36:25 Merge branch 'ijg.lossless' into dev Refer to #402
DRC b5a9ef64 2022-11-13T13:00:26 Don't allow 12-bit JPEG support to be disabled In libjpeg-turbo 2.1.x and prior, the WITH_12BIT CMake variable was used to enable 12-bit JPEG support at compile time, because the libjpeg API library could not handle multiple JPEG data precisions at run time. The initial approach to handling multiple JPEG data precisions at run time (7fec5074f962b20ed00b4f5da4533e1e8d4ed8ac) created a whole new API, library, and applications for 12-bit data precision, so it made sense to repurpose WITH_12BIT to allow 12-bit data precision to be disabled. e8b40f3c2ba187ba95c13c3e8ce21c8534256df7 made it so that the libjpeg API library can handle multiple JPEG data precisions at run time via a handful of straightforward API extensions. Referring to 6c2bc901e27b047440ed46920c4d3f0480b48268, it hasn't been possible to build libjpeg-turbo with both forward and backward libjpeg API/ABI compatibility since libjpeg-turbo 1.4.x. Thus, whereas we retain full backward API/ABI compatibility with libjpeg v6b-v8, forward libjpeg API/ABI compatibility ceased being realistic years ago, so it no longer makes sense to provide compile-time options that give a false sense of forward API/ABI compatibility by allowing some (but not all) of our libjpeg API extensions to be disabled. Such options are difficult to maintain and clutter the code with #ifdefs.
DRC e8b40f3c 2022-11-01T21:45:39 Vastly improve 12-bit JPEG integration The Gordian knot that 7fec5074f962b20ed00b4f5da4533e1e8d4ed8ac attempted to unravel was caused by the fact that there are several data-precision-dependent (JSAMPLE-dependent) fields and methods in the exposed libjpeg API structures, and if you change the exposed libjpeg API structures, then you have to change the whole API. If you change the whole API, then you have to provide a whole new library to support the new API, and that makes it difficult to support multiple data precisions in the same application. (It is not impossible, as example.c demonstrated, but using data-precision-dependent libjpeg API structures would have made the cjpeg, djpeg, and jpegtran source code hard to read, so it made more sense to build, install, and package 12-bit-specific versions of those applications.) Unfortunately, the result of that initial integration effort was an unreadable and unmaintainable mess, which is a problem for a library that is an ISO/ITU-T reference implementation. Also, as I dug into the problem of lossless JPEG support, I realized that 16-bit lossless JPEG images are a thing, and supporting yet another version of the libjpeg API just for those images is untenable. In fact, however, the touch points for JSAMPLE in the exposed libjpeg API structures are minimal: - The colormap and sample_range_limit fields in jpeg_decompress_struct - The alloc_sarray() and access_virt_sarray() methods in jpeg_memory_mgr - jpeg_write_scanlines() and jpeg_write_raw_data() - jpeg_read_scanlines() and jpeg_read_raw_data() - jpeg_skip_scanlines() and jpeg_crop_scanline() (This is subtle, but both of those functions use JSAMPLE-dependent opaque structures behind the scenes.) It is much more readable and maintainable to provide 12-bit-specific versions of those six top-level API functions and to document that the aforementioned methods and fields must be type-cast when using 12-bit samples. Since that eliminates the need to provide a 12-bit-specific version of the exposed libjpeg API structures, we can: - Compile only the precision-dependent libjpeg modules (the coefficient buffer controllers, the colorspace converters, the DCT/IDCT managers, the main buffer controllers, the preprocessing and postprocessing controller, the downsampler and upsamplers, the quantizers, the integer DCT methods, and the IDCT methods) for multiple data precisions. - Introduce 12-bit-specific methods into the various internal structures defined in jpegint.h. - Create precision-independent data type, macro, method, field, and function names that are prefixed by an underscore, and use an internal header to convert those into precision-dependent data type, macro, method, field, and function names, based on the value of BITS_IN_JSAMPLE, when compiling the precision-dependent libjpeg modules. - Expose precision-dependent jinit*() functions for each of the precision-dependent libjpeg modules. - Abstract the precision-dependent libjpeg modules by calling the appropriate precision-dependent jinit*() function, based on the value of cinfo->data_precision, from top-level libjpeg API functions.
DRC 664b64a9 2022-11-03T14:25:35 Merge branch 'main' into dev
DRC 4f7a8afb 2022-11-03T13:37:55 Build: Fix issues w/ Ninja Multi-Config generator - Fix an issue whereby a build with ENABLE_SHARED=0 could not be installed when using the Ninja Multi-Config CMake generator. - Fix an issue whereby a Windows installer could not be built when using the Ninja Multi-Config CMake generator. - Fix an issue whereby the Java regression tests failed when using the Ninja Multi-Config CMake generator. Based on: https://github.com/stilllman/libjpeg-turbo/commit/4f169deeb092a0513472b04f05f57bfe42b31ceb Closes #626
DRC 8917c548 2022-11-03T14:20:22 ChangeLog.md: Add colons to sub-headers For some reason, I failed to add a colon to the "Significant changes relative to 2.1 beta1" sub-header, and the mistake propagated from there.
DRC 513f9e66 2022-08-09T04:27:33 Merge branch 'main' into dev
DRC 8162eddf 2022-08-08T16:02:34 Fix issues w/ partial img decompr + buf img mode Fixes #611
DRC 931884e7 2022-08-08T15:41:01 Java: Remove deprecated fields, ctors, and methods Most of these have been deprecated since libjpeg-turbo 1.4.x. It's time.
DRC 280784f7 2022-08-08T15:07:45 Merge branch 'main' into dev
DRC 2e136a71 2022-08-08T14:17:51 Re-fix buf img mode decompr err w/short prog JPEGs This commit reverts 4dbc293125b417f97e5b1ca9e7260c82ff199a06 and 9f8f683e745972720433406cff4b31e95bd6a33e (the previous two commits) and fixes #613 the correct way. The crux of the issue wasn't the size of the whole_image virtual array but rather that, since last_iMCU_row is unsigned, (last_iMCU_row - 1) wrapped around to 0xFFFFFFFF when last_iMCU_row was 0. This caused the interblock smoothing algorithm introduced in 6d91e950c871103a11bac2f10c63bf998796c719 to erroneously try to access the next two iMCU rows, neither of which existed. The first attempt at a fix (4dbc293125b417f97e5b1ca9e7260c82ff199a06) exposed a NULL dereference, detected by OSS-Fuzz, that occurred when attempting to decompress a specially-crafted malformed JPEG image to a YUV buffer using tjDecompressToYUV*() with 1/4 IDCT scaling. Fixes #613 (again) Also fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=49898
DRC 9a60181b 2022-08-07T13:48:31 Merge branch 'main' into dev
DRC 4dbc2931 2022-08-07T09:24:57 Fix buf image mode decompr err w/ short prog JPEGs Regression introduced by 6d91e950c871103a11bac2f10c63bf998796c719 Because we're now using a 5x5 smoothing window when decompressing progressive JPEG images, we need to ensure that the whole_image virtual array contains at least five rows. Previously that was not always the case unless the progressive JPEG image being decompressed had at least five iMCU rows. Since an iMCU has a height of (8 * the vertical sampling factor), attempting to decompress 4:2:2 and 4:4:4 images <= 32 pixels in height or 4:2:0 images <= 64 pixels in height triggered a JERR_BAD_VIRTUAL_ACCESS error in decompress_smooth_data(), because access_rows exceeded the number of rows in the virtual array. Fixes #613
DRC fc224c48 2022-07-07T13:11:05 Merge branch 'main' into dev
Donovan Watteau 59337a67 2022-07-06T12:11:50 PowerPC: Detect AltiVec support on OS X libjpeg-turbo's AltiVec SIMD extensions previously assumed that AltiVec instructions were available on all Power Macs that supported OS X 10.4 "Tiger" (the earliest version of OS X that libjpeg-turbo has ever supported), but Tiger can actually run on PowerPC G3 processors, which lack AltiVec instructions. This commit enables run-time detection of AltiVec instructions on OS X/PowerPC systems if AltiVec instructions are not force-enabled at compile time (using -maltivec). This allows the same build of libjpeg-turbo to support G3, G4, and G5 Power Macs. Closes #609
DRC aa5a3599 2022-06-24T14:21:33 Merge branch 'main' into dev
DRC ba22c0f7 2022-06-24T14:03:03 tjDecompressHeader3(): Accept tables-only streams Inspired by: https://github.com/amyspark/libjpeg-turbo/commit/b3b15cfe74cf07914122e26cf1e408a9a9cf3135 Closes #604 Closes #605
DRC faa7c74a 2022-05-31T13:07:00 ChangeLog.md: Acknowledge 2.1.4 release
Felix Hanau aadd60ae 2022-05-25T19:51:52 Speed up computation of optimal Huffman tables Closes #602
DRC 263386c2 2022-03-11T17:35:59 Merge branch 'main' into dev
DRC a0148454 2022-03-11T10:50:47 Win: Fix build with Visual Studio 2010 (broken by 607b668ff96e40fdc749de9b1bb98e7f40c86d93) - Visual Studio 2010 apparently doesn't have the snprintf() inline function, so restore the macro that emulates that function using _snprintf_s(). - Explicitly include errno.h in strtest.c, since jinclude.h doesn't include it when building with Visual Studio.
DRC 7fec5074 2022-03-08T12:34:11 Support 8-bit & 12-bit JPEGs using the same build Partially implements #199 This commit also implements a request from #178 (the ability to compile the libjpeg example as a standalone program.)
DRC 6d2d6d3b 2022-02-11T09:34:01 "YASM" = "Yasm" The assembler name was initially spelled "YASM", but it has been "Yasm" for the entirety of libjpeg-turbo's existence.
DRC d7d16df6 2022-02-01T09:11:19 Fix segv w/ h2v2 merged upsamp, jpeg_crop_scanline The h2v2 (4:2:0) merged upsampler uses a spare row buffer so that it can upsample two rows at a time but return only one row to the application, if necessary. merged_2v_upsample() copies from this spare row buffer into the application-supplied output buffer, using the out_row_width field in the my_merged_upsampler struct to determine how many samples to copy. out_row_width is set in jinit_merged_upsampler(), which is called within the body of jpeg_start_decompress(). Since jpeg_crop_scanline() must be called after jpeg_start_decompress(), jpeg_crop_scanline() must modify the value of out_row_width if the h2v2 merged upsampler will be used. Otherwise, merged_2v_upsample() can overflow the output buffer if the number of bytes between the current output buffer position and the end of the buffer is less than the number of bytes required to represent an uncropped scanline of the output image. All of the destination managers used by djpeg allocate either a whole image buffer or a scanline buffer based on the uncropped output image width, so this issue is not reproducible using djpeg. Fixes #574
DRC 57ba02a4 2021-10-01T16:28:54 Build: Improve Neon capability detection - Use check_c_source_compiles() rather than check_symbol_exists() to detect the presence of vld1_s16_x3(), vld1_u16_x2(), and vld1q_u8_x4(). check_symbol_exists() is unreliable for detecting intrinsics, and in practice, it did not detect the presence of the aforementioned intrinsics in versions of GCC that support them. - Set DEFAULT_NEON_INTRINSICS=0 for GCC < 12, even if the aforementioned intrinsics are available. The AArch64 back end in GCC 10 and 11 supports the necessary intrinsics, but the GAS implementation is still faster when using those compilers. Fixes #547
DRC 73eff6ef 2021-11-30T15:06:54 cjpeg: auto. compr. gray BMP/GIF-->grayscale JPEG aa7459050d7a50e1d8a99488902d41fbc118a50f was supposed to enable this for BMP input images but didn't, due to a similar oversight to the one fixed in the previous commit.
DRC 2ce32e0f 2021-11-30T10:54:24 cjpeg: automatically compress PGM-->grayscale JPEG (regression introduced by aa7459050d7a50e1d8a99488902d41fbc118a50f) cjpeg sets cinfo.in_color_space to JCS_RGB as an "arbitrary guess." Since tjLoadImage() never uses JCS_RGB, the PGM reader should treat JCS_RGB the same as JCS_UNKNOWN. Fixes #566
DRC ecf021bc 2021-11-18T21:04:35 cjpeg: Add -strict arg to treat warnings as fatal This adds fault tolerance to the LZW-compressed GIF reader, which is the only compression-side code that can throw warnings.
Piotr Kubaj d401d625 2021-10-27T03:39:09 PowerPC: Detect AltiVec support on FreeBSD Recent FreeBSD/PowerPC compilers, such as Clang 11.0.x on FreeBSD 13, do the equivalent of passing -maltivec to the compiler by default, so run-time AltiVec detection is unnecessary. However, it becomes necessary when using other compilers or when passing -mno-altivec to the compiler. Closes #552
DRC a9c41fbc 2021-10-03T12:43:15 Build: Don't enable Neon SIMD exts with Armv6- When building for 32-bit Arm platforms, test whether basic Neon intrinsics will compile with the specified compiler and C flags. This prevents the build system from enabling the Neon SIMD extensions when targetting Armv6 and other legacy architectures that do not support Neon instructions. Regression introduced by bbd8089297862efb6c39a22b5623f04567ff6443. (Checking whether gas-preprocessor.pl was needed for 32-bit Arm builds had the effect of checking whether Neon instructions were supported.) Fixes #553
DRC 739ecbc5 2021-09-30T16:28:51 ChangeLog.md: List CVE ID fixed by 2849d86a
DRC 173900b1 2021-09-02T12:48:50 tjTrans: Allow 8x8 crop alignmnt w/odd 4:4:4 JPEGs Fixes #549
DRC 5d2430f4 2021-09-02T13:17:32 ChangeLog.md: Add missing sub-header for 2.1.2
DRC 129f0cb7 2021-08-25T12:07:58 Neon/AArch64: Don't put GAS functions in .rodata Regression introduced by 240ba417aa4b3174850d05ea0d22dbe5f80553c1 Closes #546
DRC 2849d86a 2021-08-06T13:41:15 SSE2/64-bit: Fix trans. segfault w/ malformed JPEG Attempting to losslessly transform certain malformed JPEG images can cause the nbits table index in the Huffman encoder to exceed 32768, so we need to pad the SSE2 implementation of that table to 65536 entries as we do with the C implementation. Regression introduced by 087c29e07f7533ec82fd7eb1dafc84c29e7870ec Fixes #543
Alex Richardson a72816ed 2021-07-16T09:37:06 Use uintptr_t, if avail, for pointer-to-int casts Although sizeof(void *) == sizeof(size_t) for all architectures that are currently supported by libjpeg-turbo, such is not guaranteed by the C standard. Specifically, CHERI-enabled architectures (e.g. CHERI-RISC-V or Arm's Morello) use capability pointers that are twice the size of size_t (128 bits for Morello and RV64), so casting to size_t strips the upper bits of the pointer (including the validity bit) and makes it non-deferenceable, as indicated by the following compiler warning: warning: cast from provenance-free integer type to pointer type will give pointer that can not be dereferenced [-Werror,-Wcheri-capability-misuse] cvalue = values = (JCOEF *)PAD((size_t)values_unaligned, 16); Ignoring this warning results in a run-time crash. Casting pointers to uintptr_t, if it is available, avoids this problem, since uintptr_t is defined as an unsigned integer type that can hold a pointer value. Since C89 compatibility is still necessary in libjpeg-turbo, this commit introduces a new typedef for pointer-to-integer casts that uses a GNU-specific extension available in GCC 4.6+ and Clang 3.0+ and falls back to using size_t if the extension is unavailable. The only other options would require C99 or Clang-specific builtins. Closes #538
DRC 4d9f256b 2021-07-13T11:52:49 jpegtran: Add option to copy only ICC markers Closes #533
DRC 2a2970af 2021-07-09T15:35:56 Neon/AArch32: Work around Clang T32 miscompilation Referring to the C standard (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf, J.2 Undefined behavior), the behavior of the compiler is undefined if "conversion between two pointer types produces a result that is incorrectly aligned." Thus, the behavior of this code *((uint32_t *)buffer) = BUILTIN_BSWAP32(put_buffer); in the AArch32 version of the FLUSH() macro is undefined unless 'buffer' is 32-bit-aligned. Referring to https://bugs.llvm.org/show_bug.cgi?id=50785, certain versions of Clang, when generating Thumb (T32) instructions, miscompile that code into an assembly instruction (stm) that requires the destination to be 32-bit-aligned. Since such alignment cannot be guaranteed within the Huffman encoder, this reportedly led to crashes (SIGBUS: illegal alignment) with AArch32/Thumb builds of libjpeg-turbo running on Android devices, although thus far I have been unable to reproduce those crashes with a plain Linux/Arm system. The miscompilation is visible with the Compiler Explorer: https://godbolt.org/z/rv1ccx1Pb However, it goes away when removing the return statement from the function. Thus, it seems that Clang's behavior in this regard is somewhat variable, which may explain why the crashes are only reproducible on certain platforms. The suggested workaround is to use memcpy(), but whereas Clang and recent GCC releases are smart enough to compile a 4-byte memcpy() call into a str instruction, GCC < 6 is not. Referring to https://godbolt.org/z/ae7Wje3P6, the only way to consistently produce the desired str instruction across all supported compilers is to use inline assembly. Visual C++ presumably does not miscompile the code in question, since no issues have been reported with it, but since the code relies on undefined compiler behavior, prudence dictates that e4ec23d7ae051c1c73947f889818900362fdc52d should be reverted for Visual C++, which this commit does. The performance impact of e4ec23d7ae051c1c73947f889818900362fdc52d for Visual C++/Arm builds is unknown (I have no ability to test such builds), but regardless, this commit reverts the Visual C++/Arm performance to that of libjpeg-turbo 2.1 beta1. Closes #529
DRC 0081c2de 2021-07-07T10:12:46 Neon/AArch32: Fix build if 'soft' float ABI used Arm compilers have three floating point ABI options: 'soft' compiles floating point operations as function calls into a software floating point library, which emulates floating point operations using integer operations. Floating point function arguments are passed using integer registers. 'softfp' also compiles floating point operations as function calls into a floating point library and passes floating point function arguments using integer registers, but the floating point library functions can use FPU instructions if the CPU supports them. 'hard' compiles floating point operations into inline FPU instructions, similarly to x86 and other architectures, and passes floating point function arguments using FPU registers. Not all AArch32 CPUs have FPUs or support Neon instructions, so on Linux and Android platforms, the AArch32 SIMD dispatcher in libjpeg-turbo only enables the Neon SIMD extensions at run time if /proc/cpuinfo indicates that the CPU supports Neon instructions or if Neon instructions are explicitly enabled (e.g. by passing -mfpu=neon to the compiler.) In order to support all AArch32 CPUs using the same code base, i.e. to support run-time FPU and Neon auto-detection, it is necessary to compile the scalar C source code using -mfloat-abi=soft. However, the 'soft' floating point ABI cannot be used when compiling Neon intrinsics, so the intrinsics implementation of the Neon SIMD extensions must be compiled using -mfloat-abi=softfp if the scalar C source code is compiled using -mfloat-abi=soft. This commit modifies the build system so that it detects whether -mfloat-abi=softfp must be explicitly added to the compiler flags when building the intrinsics implementation of the Neon SIMD extensions. This will be necessary if the build is using the 'soft' floating point ABI along with run-time auto-detection of Neon instructions. Fixes #523
DRC 1a1fb615 2021-06-18T09:46:03 ChangeLog.md: List CVE ID fixed by c76f4a08 Referring to #527, the security community did not assign this CVE ID until more than 8 months after the fix for the issue was released. By the time they assigned the ID, libjpeg-turbo already had two production releases containing the fix. This calls into question the usefulness of assigning a CVE ID to the issue, particularly given that the buffer overrun in question was fully contained in the stack, not detectable with valgrind, and confined to lossless transformation (it did not affect JPEG compression or decompression.) https://vuldb.com/?id.176175 says that "the exploitability is told to be easy" but provides no clarification, and given that the author of that page does not seem to be aware that a fix for the issue has been available since early December of 2019, it calls into question the accuracy of everything else on the page. It would really be nice if the security community approached me about these things before wasting my time, but I guess it's my lot in life to modify a change log entry from 2019 to include a CVE ID from 2020. So it goes...
DRC 3932190c 2021-05-17T13:05:16 Fix build w/ non-GCC-compatible Un*x/Arm compilers Regression introduced by d2c407995992be1f128704ae2479adfd7906c158 Closes #519
DRC 4f51f36e 2021-04-23T11:42:40 Bump version to 2.1.0 to prepare for final release
DRC e0606daf 2021-04-21T14:49:06 TurboJPEG: Update JPEG buf ptrs on comp/xform err When using the in-memory destination manager, it is necessary to explicitly call the destination manager's term_destination() method if an error occurs. That method is called by jpeg_finish_compress() but not by jpeg_abort_compress(). This fixes a potential double free() that could occur if tjCompress*() or tjTransform() returned an error and the calling application tried to clean up a JPEG buffer that was dynamically re-allocated by one of those functions.
DRC f35fd27e 2021-04-06T12:51:03 tjLoadImage: Fix issues w/loading 16-bit PPMs/PGMs - The PPM reader now throws an error rather than segfaulting (due to a buffer overrun) if an application attempts to load a 16-bit PPM file into a grayscale uncompressed image buffer. No known applications allowed that (not even the test applications in libjpeg-turbo), because that mode of operation was never expected to work and did not work under any circumstances. (In fact, it was necessary to modify TJBench in order to reproduce the issue outside of a fuzzing environment.) This was purely a matter of making the library bow out gracefully rather than crash if an application tries to do something really stupid. - The PPM reader now throws an error rather than generating incorrect pixels if an application attempts to load a 16-bit PGM file into an RGB uncompressed image buffer. - The PPM reader now correctly loads 16-bit PPM files into extended RGB uncompressed image buffers. (Previously it generated incorrect pixels unless the input colorspace was JCS_RGB or JCS_EXT_RGB.) The only way that users could have potentially encountered these issues was through the tjLoadImage() function. cjpeg and TJBench were unaffected.
DRC c81e91e8 2021-04-05T16:08:22 TurboJPEG: New flag for limiting prog JPEG scans This also fixes timeouts reported by OSS-Fuzz.
DRC e795afc3 2021-03-25T22:36:15 SSE2: Fix prog Huff enc err if Sl%32==0 && Al!=0 (regression introduced by 16bd984557fa2c490be0b9665e2ea0d4274528a8) This implements the same fix for jsimd_encode_mcu_AC_refine_prepare_sse2() that a81a8c137b3f1c65082aa61f236aa88af61b3ad4 implemented for jsimd_encode_mcu_AC_first_prepare_sse2(). Based on: https://github.com/MegaByte/libjpeg-turbo/commit/1a59587397150c9ef9dffc5813cb3891db4bc0c8 https://github.com/MegaByte/libjpeg-turbo/commit/eb176a91d87a470bf8c987be786668aa944dd1dd Fixes #509 Closes #510
DRC ed70101d 2021-03-15T12:36:55 ChangeLog.md: List CVE ID fixed by 1719d12e Referring to https://bugzilla.redhat.com/show_bug.cgi?id=1937385#c2, it is my opinion that the severity of this bug was grossly overstated and that a CVE never should have been assigned to it, but since one was assigned, users need to know which version of libjpeg-turbo contains the fix. Dear security community, please learn what "DoS" actually means and stop misusing that term for dramatic effect. Thanks.