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.
This commit is contained in:
DRC
2022-11-21 20:57:39 -06:00
parent b85b028d2b
commit 98ff1fd103
32 changed files with 481 additions and 283 deletions

View File

@@ -555,7 +555,8 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
{
tjhandle handle = 0;
unsigned char *jpegBuf = NULL;
int width = 0, height = 0, jpegSubsamp = -1, jpegColorspace = -1;
int width = 0, height = 0, jpegSubsamp = -1, jpegColorspace = -1,
jpegFlags = -1;
GET_HANDLE();
@@ -564,8 +565,9 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0));
if (tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, &width,
&height, &jpegSubsamp, &jpegColorspace) == -1) {
if (tjDecompressHeader4(handle, jpegBuf, (unsigned long)jpegSize, &width,
&height, &jpegSubsamp, &jpegColorspace,
&jpegFlags) == -1) {
SAFE_RELEASE(src, jpegBuf);
THROW_TJ();
}
@@ -578,6 +580,10 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
(*env)->ExceptionClear(env);
else
(*env)->SetIntField(env, obj, _fid, jpegColorspace);
if ((_fid = (*env)->GetFieldID(env, _cls, "jpegFlags", "I")) == 0)
(*env)->ExceptionClear(env);
else
(*env)->SetIntField(env, obj, _fid, jpegFlags);
BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
(*env)->SetIntField(env, obj, _fid, width);
BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "jpegHeight", "I"));