1
0
mirror of https://github.com/libjpeg-turbo/libjpeg-turbo.git synced 2026-10-23 11:48:53 +03:00

2987 Commits

Author SHA1 Message Date
DRC
174da652ef indexedcolortest: Test GIF, Targa, and OS/2 BMP 2026-03-26 15:45:53 -04:00
DRC
285744829a rdpng.c: Autodetect grayscale indexed PNG images 2026-03-26 15:45:53 -04:00
DRC
e8bc24b655 Merge branch 'main' into dev 2026-03-26 15:45:38 -04:00
DRC
e352b02f79 Pkg/RPM: Eliminate cmake-filesystem dependency 3.1.4 2026-03-26 15:34:19 -04:00
DRC
8ca57c82f6 rpm.spec.in: Fix RPM build errors/warnings
- Fix RPM build error if WITH_JAVA=0.

- Fix "File listed twice" RPM build warning.
2026-03-26 15:28:44 -04:00
DRC
5a55e5b6a0 spng.c: Silence warning about disabling SIMD opts
This could cause users of non-x86 and non-Arm systems to mistakenly
believe that libjpeg-turbo's SIMD optimizations are being disabled.
2026-03-26 12:33:26 -04:00
DRC
fb022461e4 rdpng.c: Use size_t for intermediate values
This is a similar issue to the one fixed by
e500e4c154.  On ILP32 systems, loading a
16-bit-per-component PNG with cinfo->data_precision==16 would cause the
intermediate rescale array calculations to overflow a signed long.
2026-03-26 12:08:19 -04:00
DRC
e24bc87a50 TJUnitTest.java: Fix code formatting issue
(detected by checkstyle.java)
2026-03-26 11:13:35 -04:00
DRC
57202c3b0a TJ: Don't expose TJSAMP_410/24 to TJ 3.1- callers
Otherwise the TurboJPEG 3.2 API would allow callers compiled against
TurboJPEG 3.1 and prior to set TJPARAM_SUBSAMP to a value that, from the
caller's point of view, is undefined.  tj3DecompressHeader() would also
potentially set TJPARAM_SUBSAMP to a value that would overflow the
caller's static tjMCUWidth[] and tjMCUHeight[] arrays.

The trick here is to redefine tj3Init() in the TurboJPEG header as a
macro that wraps a new undocumented function, tj3InitVersion(), and
passes it an API version constant (TURBOJPEG_VERSION_NUMBER = 3002000)
that is also defined in the header.  (This is a similar trick to the one
that the libjpeg v6a+ API uses for jpeg_create_*compress().)  The old
tj3Init() function is still exposed in the library, and it now calls
tj3InitVersion(..., 3001000) internally.  Based on the API version, the
API then sets and enforces an internal limit on the number of
chrominance subsampling options (TJ_NUMSAMP if the caller was compiled
against TurboJPEG 3.2+ or 7 otherwise.)

Thus, if an application is compiled against TurboJPEG 3.1-, it will
still call the old tj3Init() function, which sets the API version to
3.1 and doesn't expose TJSAMP_410 or TJSAMP_24.  If an application is
compiled against TurboJPEG 3.2+, then it will call the new
tj3InitVersion() function via the tj3Init() macro, which sets the API
version to 3.2 and exposes TJSAMP_410 and TJSAMP_24.

Ramifications:
- Applications compiled against TurboJPEG 3.2+ will not be able to use
  the TurboJPEG 3.1- API library at run time, because the
  tj3InitVersion() function will not be available.

- Applications compiled against TurboJPEG 3.1- will work the same
  regardless of whether they use the TurboJPEG 3.1- or 3.2+ API library
  at run time.

- Applications that weren't specifically developed for TurboJPEG 3.2+
  will not know about TJSAMP_410 or TJSAMP_24.  Thus, when decompressing
  or transforming without transposition, such applications will gain the
  ability to obtain the iMCU width/height of a 4:1:0 or 2:4 JPEG image,
  which is useful when adjusting the cropping region.  However, they
  will not gain any other abilities.
2026-03-26 11:07:19 -04:00
DRC
c3b9e94d48 Support reading indexed-color PNG files
+ create an automated test for both color quantization and indexed-color
packed-pixel image I/O
2026-03-25 16:09:44 -04:00
DRC
c35d29e6f0 Doc: "true color" = "truecolor"
The PNG spec says "truecolor."

Also use "uncompressed RGB" rather than "uncompressed true color" when
referring to TARGA images, to conform to that spec.
2026-03-25 08:58:02 -04:00
DRC
ff920a8404 WITH_PROFILE: Fix total decomp time calculation
54bd58cc30 (PNG image I/O) exposed an
issue whereby, if an application calls jpeg_read_header() and
jpeg_abort_decompress() (as tj3DecompressHeader() does), then the
total_start field will be 0 in jpeg_abort().  That meant that the
total_elapsed field computed in jpeg_abort() was near 0.  This commit
modifies jpeg_abort() so that it avoids incrementing total_elapsed
unless total_start is non-zero, thus ensuring that total_elapsed
reflects the time between
jinit_c_master_control()/jinit_master_decompress() and jpeg_abort().
2026-03-24 16:36:01 -04:00
DRC
b79f424c05 zlib: Don't include (unneeded) gzip code
This reduces the size of static executables built with the in-tree
implementation of libspng.
2026-03-24 13:30:52 -04:00
DRC
c5645885b2 Fuzz: Fix cjpeg fuzzer build
(broken by d8e1c47bb6)
2026-03-24 13:17:06 -04:00
DRC
f61af576f5 Merge branch 'main' into dev 2026-03-24 13:16:59 -04:00
DRC
f2bc738680 OSS-Fuzz: Reduce lossless scan limit to 50
If a malformed lossless JPEG image has close to, but not more than, 100
scans, then all iterations of the decompress fuzzers will run.  This
never takes more than 5 seconds on my machine, but apparently OSS-Fuzz
sometimes uses slower hardware (particularly for the ASan/i386 tests)
that sometimes exceeds the 25-second timeout when fuzz testing such a
malformed image.  As with the pixel limit, the goal of the scan limit is
to maximize the test throughput in order to maximize coverage.  100
scans was an arbitrary choice, and reducing it to 50 does not affect
default coverage (and may actually improve asymptotic coverage.)
2026-03-24 13:05:55 -04:00
DRC
2303b7c551 JNI: Guard against signed int overflow w/huge vals
fc324109d5 checked for unsigned int
overflow, but jsize is always a signed int, even when using a 64-bit
JVM.  (This reflects the fact that array sizes in Java are always signed
ints.)  Thus, array sizes should be checked against INT_MAX, not
UINT_MAX.

In almost all cases, this is a belt-and-suspenders measure.  With the
exception of TJCompressor.loadSourceImage(), the array size checks in
question are checking a Java array, which can never have more than
INT_MAX elements.  Thus, even if the previous unsigned int overflow
checks failed to catch signed int overflow, the error would have been
caught in a different place.  With TJCompressor.loadSourceImage(), it
was possible to load a packed-pixel image large enough that arraySize
overflowed a signed int and caused the NewByteArray() or NewShortArray()
JNI methods to crash the JVM.  However, this would have required a
multi-gigabyte packed-pixel image.

This commit also improves the array size checks in
TJCompressor.loadSourceImage() and TJDecompressor.saveImage() so that
they take into account row alignment/pitch.

Fixes #877
2026-03-24 11:59:35 -04:00
DRC
17c3c3061c wrpng.c: Use indexed PNG for quantized 8-bpc RGB
For quantized 8-bit-per-component RGB output, indexed-color PNG images
are smaller than true color PNG images.  (The same is not true for
grayscale.)
2026-03-23 19:01:01 -04:00
DRC
4346a6ce76 Fix quantized PNG output with JCS_EXT_BGR 2026-03-23 16:41:39 -04:00
DRC
e157624f26 CI: Test TurboJPEG/JNA in jpeg-7/jpeg-8 builds 2026-03-23 15:41:31 -04:00
DRC
c7da03c4c1 Merge branch 'main' into dev 2026-03-23 15:40:56 -04:00
DRC
572f1ee81c Fix quantized BMP/PPM output with JCS_EXT_BGR
(This code path is currently unused in djpeg and tj3SaveImage*(), so the
issue went unnoticed.)
2026-03-23 15:36:02 -04:00
DRC
d8e1c47bb6 Allow building against system's libspng &/or zlib 2026-03-23 12:14:55 -04:00
DRC
c39ea08d81 Build: Require CMake 3.15+
- This eliminates the need for any backward compatibility hacks in the
  build system.

- CMake 3.4- is no longer supported by CMake 4+.

- The only reason why we continued to support CMake 2.8.12 was that it
  was pre-installed on RHEL/CentOS 7, which was used by our official
  Docker image.  That was already a weak argument, since CMake 3.x
  binaries worked on systems with glibc 2.12 and later (RHEL 6+ and
  equivalents or Ubuntu 12.04+.)

  Our official Docker image now uses Rocky Linux 8 in order to support
  cross-compilation of the Arm Neon SIMD extensions with GCC 12, which
  was necessary in order to eliminate the GNU assembler (GAS) fallback
  code.

- CMake 3.15+ is pre-installed on RHEL 8+ and equivalents and Ubuntu
  20.04+, and on other platforms, it is no more difficult to install
  than CMake 2.8.12.  (In fact, newer CMake versions are easier to
  install on Mac systems.  CMake 3.18- did not provide Apple Silicon
  binaries, and CMake 3.15- was deployed as a pkg installer rather than
  a standalone app bundle.)
2026-03-23 10:57:03 -04:00
DRC
58d3f698b4 jerror.h: Fix -Wstringop-truncation warning
... when using ERREXITS().  This warning was innocuous, because
ERREXITS() immediately NULL-terminates (cinfo)->err->msg_parm.s[] after
copying to it with strncpy().  ERREXITS() was unused until PNG image I/O
support was added, so the warning didn't occur with prior versions of
libjpeg-turbo.
2026-03-21 06:52:15 -04:00
DRC
33ebdc5bcf Merge branch 'main' into dev 2026-03-21 06:45:25 -04:00
DRC
31448a81be j*lossls.c: Throw error if cinfo.Ss < 1 or > 7
In the decompressor, this does nothing except fix a -Wswitch-default
warning with Clang, because cinfo.Ss (the predictor selection value) is
already range-checked in start_pass_lossless().

In the compressor, this fixes an oversight whereby a calling application
could manually set cinfo.Ss to an invalid value after calling
jpeg_enable_lossless() and before calling jpeg_start_compress(), thus
causing an incorrect (all white) lossless JPEG image to be silently
generated.
2026-03-21 06:39:04 -04:00
DRC
f0e42e297a Build: "libjpeg-turbo" = "${CMAKE_PROJECT_NAME}"
It is our convention to use the generic CMake project name rather than
hard-coding "libjpeg-turbo" in error messages and option descriptions,
to facilitate downstream integration.
2026-03-21 05:55:16 -04:00
DRC
7c9d24dd82 PNG: Guard against double free in finish methods 2026-03-20 18:18:01 -04:00
DRC
42b75222d5 libspng: Use zlib v1.3.2 instead of miniz
miniz is buggy, and it keeps causing fuzzer failures.
2026-03-20 17:51:37 -04:00
DRC
f040191a94 testclean.cmake: Clean up 4:1:0 and 2:4 files 2026-03-20 13:25:05 -04:00
DRC
5b6a44a826 Bump revision to 3.1.90 to prepare for beta
+ acknowledge upcoming 3.1.4 release
2026-03-19 21:28:09 -04:00
DRC
58cb2a5183 jpegtran: Implement lossless roll transform
Based on
93554a0ea5

Closes #870
Closes #871
2026-03-19 21:26:30 -04:00
DRC
5bb352f91d TJ: Throw libjpeg errors as instance errors
This is mostly a code cleanliness thing.  It doesn't fix any known
issues.  (Hypothetically, a caller might call tj3GetErrorStr() in a
different thread from the thread in which the libjpeg error was thrown,
but that is not a supported use case.)
2026-03-19 15:28:57 -04:00
DRC
deb273b468 Merge branch 'main' into dev 2026-03-19 14:50:05 -04:00
DRC
c615a1adfa rdcolmap.c: Range-limit PPM values
Apply the same fixes from 6709e4a0cf,
dd830b3ffe, and
6c9fb7064a to the PPM reader in
read_color_map*().  This prevents two issues:

1. An invalid PPM file could be created with dimensions larger than
   UINT_MAX, which would cause 32-bit integer overflow and wraparound.
   The worst case for such an issue would be that djpeg produces an
   incorrect output file rather than throwing an error about the invalid
   PPM file.  (Note that UBSan did not catch the overflow.)

2. A valid PPM file with excessively large dimensions and fewer than N
   unique colors (where N = MAXJ*SAMPLE + 1) could cause djpeg to spin
   for an unreasonable amount of time as it continued reading until it
   processed w * h pixels or reached the end of the file.
   Hypothetically, a file with dimensions UINT_MAX * UINT_MAX could be
   created.  In reality, however, no one is going to create a 16-exabyte
   file, so the worst case is probably a file with tens or hundreds of
   gigabytes.

The issues were confined to the djpeg test program and did not represent
security vulnerabilities.  At the end of the day, if you ask djpeg to
read a colormap from a 16-exabyte PPM file, then that's on you.  This
commit merely user-proofs djpeg against such mistakes.

Closes #876
2026-03-19 14:35:43 -04:00
DRC
e7575e4015 Harden the TurboJPEG API against libjpeg errors
- For readability, wrap setjmp() calls with a macro.

- In tj3Destroy(), continue attempting to destroy the instance if
  jpeg_destroy_compress() or jpeg_destroy_decompress() throws a libjpeg
  error.  (That can never happen with the malloc()/free() memory manager
  used by libjpeg-turbo, but since tj3Destroy() handles libjpeg errors,
  it might as well handle them correctly.)

- Reset the marker processor if jpeg_read_header() throws a libjpeg
  error in tj3DecodeYUVPlanes8().  In general, it is a bad idea to
  continue using a TurboJPEG instance after a fatal error is thrown.
  However, in this case jpeg_read_header() isn't actually consuming
  input.  It is invoked with a dummy marker processor so that it can be
  used solely to validate and advance the API state.  (For example,
  jpeg_read_header() could throw JERR_IMAGE_TOO_BIG if the width or
  height passed to tj3DecodeYUVPlanes8() is greater than 65500.  That is
  essentially a recoverable argument error.)

  Failing to reset the marker processor prevented subsequent invocations
  of tj3DecompressHeader() from processing a JPEG image.  To put it
  another way, decode and decompress operations are supposed to be
  independent, even if they share the same API instance.  Thus, a
  failure in one operation should (ideally) not cause the other to fail.

Closes #875
2026-03-19 12:04:48 -04:00
DRC
3efd0f9e68 Merge branch 'main' into dev 2026-03-18 16:53:19 -04:00
DRC
bd77b2ddf0 Fix various issues if *_SUPPORTED macros undefined
NOTE: These fixes are mainly intended to facilitate downstream
integration.  libjpeg-turbo is not officially supported with any of
these macros undefined.  (That is, it is not guaranteed to work.  It is
expected that downstream integrators diagnose and report any issues that
may occur.  Those issues will not be fixed proactively.)

- bmpsizetest.c: Fix build if C_LOSSLESS_SUPPORTED or
  D_LOSSLESS_SUPPORTED is undefined.

- cjpeg.c, jpegtran.c: Fix compiler warnings if
  C_MULTISCAN_FILES_SUPPORTED or C_PROGRESSIVE_SUPPORTED is undefined.

- jcdctmgr.c, jcinit.c, jddctmgr.c, jdmaster.c, simdcoverage.c: Fix
  build if all DCT_*_SUPPORTED macros are undefined.  (This allows for
  building libjpeg-turbo with only lossless JPEG support.)

- jclhuff.c, jcmaster.c: Fix build if ENTROPY_OPT_SUPPORTED is
  undefined.

- jcmaster.c: Fix compiler warning if C_PROGRESSIVE_SUPPORTED is
  undefined.

- jcsample.c: Fix compiler warnings if INPUT_SMOOTHING_SUPPORTED is
  undefined.

- jdapistd.c: Fix build if UPSAMPLE_MERGING_SUPPORTED is undefined.

- jmorecfg.h:
  * Clarify that C_PROGRESSIVE_SUPPORTED requires
    C_MULTISCAN_FILES_SUPPORTED and ENTROPY_OPT_SUPPORTED.  (The
    progressive Huffman encoder won't even build without the latter.)
  * Clarify that D_PROGRESSIVE_SUPPORTED and D_LOSSLESS_SUPPORTED
    require D_MULTISCAN_FILES_SUPPORTED.  (The progressive huffman
    decoder and difference controller won't even build without it.)
  * Clarify that IDCT_SCALING_SUPPORTED requires DCT_ISLOW_SUPPORTED.
  * Remove vestigial UPSAMPLE_SCALING_SUPPORTED macro.  (I guess this
    was intended for a feature that was never implemented.)

- jpegtran.c: Fix compiler warning is TRANSFORMS_SUPPORTED is 0.

- turbojpeg.c:
  * Do not advertise any scaling factors other than {1, 1} if
    IDCT_SCALING_SUPPORTED is undefined.  Otherwise, calling
    applications may erroneously expect a scaled image when an unscaled
    image will be provided, which may cause them to provide too small of
    a buffer.
  * Fix build if SAVE_MARKERS_SUPPORTED is undefined.
  * Fix build if TRANSFORMS_SUPPORTED is 0.

- turbojpeg-mp.c: Fix compiler warning if C_LOSSLESS_SUPPORTED is
  undefined.
2026-03-18 16:08:32 -04:00
DRC
2468fdcbc0 Test: "420s-ifast-opt" --> "420s-islow-opt" 2026-03-18 14:45:57 -04:00
000TY
f0dab2d2e2 miniz: Fix CVE-2018-12913 (code_len==0 inf. loop)
Guard against code_len==0 infinite loop in tinfl_decompress().

DRC's note: This manifested as a timeout in OSS-Fuzz.
2026-03-17 18:34:20 -04:00
DRC
bb2be997e6 Merge branch 'main' into dev 2026-03-17 16:48:34 -04:00
DRC
c83ead3a11 Limit packed-pixel dimensions to 65500x65500 Pt. 2
Normally the packed-pixel image writers are guarded by the JPEG
decompressor's dimension checks, but that isn't the case when the
writers are invoked by tj3SaveImage*().  This commit also adds a unit
test to verify that both the readers and writers limit image dimensions
appropriately.
2026-03-17 14:08:19 -04:00
DRC
0908533a9d wrbmp.c: Use size_t for intermediate values
This is a similar issue to the one fixed by
fa5259da1d.  On ILP32 systems, writing a
24-bit BMP would cause the computation of bfSize to overflow a signed
long if width * height > INT_MAX / 3.
2026-03-17 13:18:43 -04:00
DRC
95ebc92dc6 rdpng.c: Work around libspng MSan false positives 2026-03-16 19:17:15 -04:00
DRC
7f42f35f8d Fix memory leak if PNG initialization fails
This wasn't an issue with other image readers, because their
finish_input() methods are no-ops.  With the PNG reader, however, we
need to make sure that the finish_input() method is called if
tj3LoadImage*() or the cjpeg fuzzer throws an error.  We also need to
advance the setjmp() pointer after calling jinit_read_*(), to ensure
that the source manager pointer remains initialized on the stack.
2026-03-16 19:15:20 -04:00
DRC
751b935ac9 Merge branch 'main' into dev 2026-03-16 16:34:44 -04:00
DRC
6c9fb7064a Limit packed-pixel image dimensions to 65500x65500
It doesn't make sense to allow packed-pixel images with dimensions
larger then JPEG_MAX_DIMENSION to be loaded, because the compressor will
eventually throw an error when attempting to compress those images.
It's better to catch that error in the image readers, so we don't have
to guard against 32-bit integer overflow.
2026-03-16 15:14:08 -04:00
DRC
e500e4c154 rdppm.c: Use size_t for intermediate values
This is a similar issue to the one fixed by the previous commit.  On
ILP32 systems, loading a 16-bit-per-component PPM with
cinfo->data_precision==16 would cause the intermediate rescale array
calculations to overflow a signed long.
2026-03-16 14:59:32 -04:00
Oblivionsage
fa5259da1d jmemmgr.c: Use size_t for intermediate values
On ILP32 systems, it is possible for the BMP writer to request an
inversion array large enough that the intermediate calculations in
realize_virt_arrays() would overflow a signed long.  (Specifically, this
would occur when writing a 24-bit BMP if width * height > INT_MAX / 3.)
The overflow was innocuous, because any values large enough to trigger
it would almost immediately cause the memory manager to exceed
MAX_ALLOC_CHUNK and throw a fatal error.  However, the issue caused
UBSan to complain.

Fixes #874
2026-03-16 11:46:55 -04:00