Java: Don't allow int overflow in buf size methods

This is similar to the fix that 2a9e3bd743
applied to the C API.  We have to apply it separately at the JNI level
because the Java API always stores buffer sizes in 32-bit integers, and
the C buffer size functions could overflow an int when using 64-bit
code.  (NOTE: The Java API stores buffer sizes in 32-bit integers
because Java itself always uses 32-bit integers for array sizes.)  Since
Java don't allow no buffer overruns 'round here, this commit doesn't
change the ultimate outcome.  It just makes the inevitable exception
easier to diagnose.
This commit is contained in:
DRC
2023-01-16 15:32:49 -06:00
parent 94a2b95342
commit 22a6636852
2 changed files with 54 additions and 10 deletions

View File

@@ -837,6 +837,43 @@ final class TJUnitTest {
if (tjd != null) tjd.close();
}
static void overflowTest() throws Exception {
/* Ensure that the various buffer size methods don't overflow */
int size = 0;
boolean exception = false;
try {
exception = false;
size = TJ.bufSize(26755, 26755, TJ.SAMP_444);
} catch (Exception e) { exception = true; }
if (!exception || size != 0)
throw new Exception("TJ.bufSize() overflow");
try {
exception = false;
size = TJ.bufSizeYUV(37838, 1, 37838, TJ.SAMP_444);
} catch (Exception e) { exception = true; }
if (!exception || size != 0)
throw new Exception("TJ.bufSizeYUV() overflow");
try {
exception = false;
size = TJ.bufSizeYUV(37837, 3, 37837, TJ.SAMP_444);
} catch (Exception e) { exception = true; }
if (!exception || size != 0)
throw new Exception("TJ.bufSizeYUV() overflow");
try {
exception = false;
size = TJ.bufSizeYUV(37837, -1, 37837, TJ.SAMP_444);
} catch (Exception e) { exception = true; }
if (!exception || size != 0)
throw new Exception("TJ.bufSizeYUV() overflow");
try {
exception = false;
size = TJ.planeSizeYUV(0, 65536, 0, 65536, TJ.SAMP_444);
} catch (Exception e) { exception = true; }
if (!exception || size != 0)
throw new Exception("TJ.planeSizeYUV() overflow");
}
static void bufSizeTest() throws Exception {
int w, h, i, subsamp;
byte[] srcBuf, dstBuf = null;
@@ -912,6 +949,7 @@ final class TJUnitTest {
}
if (doYUV)
FORMATS_4BYTE[4] = -1;
overflowTest();
doTest(35, 39, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_444,
testName);
doTest(39, 41, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_444,

View File

@@ -132,24 +132,28 @@ bailout:
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
(JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
{
jint retval = (jint)tjBufSize(width, height, jpegSubsamp);
unsigned long retval = tjBufSize(width, height, jpegSubsamp);
if (retval == -1) THROW_ARG(tjGetErrorStr());
if (retval == (unsigned long)-1) THROW_ARG(tjGetErrorStr());
if (retval > (unsigned long)((unsigned int)-1))
THROW_ARG("Image is too large");
bailout:
return retval;
return (jint)retval;
}
/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
(JNIEnv *env, jclass cls, jint width, jint align, jint height, jint subsamp)
{
jint retval = (jint)tjBufSizeYUV2(width, align, height, subsamp);
unsigned long retval = tjBufSizeYUV2(width, align, height, subsamp);
if (retval == -1) THROW_ARG(tjGetErrorStr());
if (retval == (unsigned long)-1) THROW_ARG(tjGetErrorStr());
if (retval > (unsigned long)((unsigned int)-1))
THROW_ARG("Image is too large");
bailout:
return retval;
return (jint)retval;
}
/* TurboJPEG 1.2.x: TJ::bufSizeYUV() */
@@ -166,13 +170,15 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
(JNIEnv *env, jclass cls, jint componentID, jint width, jint stride,
jint height, jint subsamp)
{
jint retval = (jint)tjPlaneSizeYUV(componentID, width, stride, height,
unsigned long retval = tjPlaneSizeYUV(componentID, width, stride, height,
subsamp);
if (retval == -1) THROW_ARG(tjGetErrorStr());
if (retval == (unsigned long)-1) THROW_ARG(tjGetErrorStr());
if (retval > (unsigned long)((unsigned int)-1))
THROW_ARG("Image is too large");
bailout:
return retval;
return (jint)retval;
}
/* TurboJPEG 1.4.x: TJ::planeWidth() */