Skip to content

Commit f25e8cf

Browse files
committed
8212034: Potential memory leaks in jpegLoader.c in error case
Reviewed-by: jvos, kcr
1 parent b2ac76a commit f25e8cf

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

modules/javafx.graphics/src/main/native-iio/jpegloader.c

+44-26
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,11 @@ static void imageio_abort(JNIEnv *env, jobject this,
678678
data->abortFlag = JNI_TRUE;
679679
}
680680

681+
static void disposeIIO(JNIEnv *env, imageIODataPtr data) {
682+
j_common_ptr info = destroyImageioData(env, data);
683+
imageio_dispose(info);
684+
}
685+
681686
/*************** end of shared utility code ****************/
682687

683688
/********************** Loader Support **************************/
@@ -1267,9 +1272,7 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initJPEGMeth
12671272
JNIEXPORT void JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_disposeNative
12681273
(JNIEnv *env, jclass cls, jlong ptr) {
12691274
imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1270-
j_common_ptr info = destroyImageioData(env, data);
1271-
1272-
imageio_dispose(info);
1275+
disposeIIO(env, data);
12731276
}
12741277

12751278
#define JPEG_APP1 (JPEG_APP0 + 1) /* EXIF APP1 marker code */
@@ -1330,6 +1333,8 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
13301333
char buffer[JMSG_LENGTH_MAX];
13311334
(*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
13321335
buffer);
1336+
free(cinfo->err);
1337+
free(cinfo);
13331338
ThrowByName(env, "java/io/IOException", buffer);
13341339
return 0;
13351340
}
@@ -1347,6 +1352,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
13471352
cinfo->src =
13481353
(struct jpeg_source_mgr *) malloc(sizeof (struct jpeg_source_mgr));
13491354
if (cinfo->src == NULL) {
1355+
imageio_dispose((j_common_ptr) cinfo);
13501356
ThrowByName(env,
13511357
"java/lang/OutOfMemoryError",
13521358
"Initializing Reader");
@@ -1363,6 +1369,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
13631369
/* set up the association to persist for future calls */
13641370
data = initImageioData(env, (j_common_ptr) cinfo, this);
13651371
if (data == NULL) {
1372+
imageio_dispose((j_common_ptr) cinfo);
13661373
ThrowByName(env,
13671374
"java/lang/OutOfMemoryError",
13681375
"Initializing Reader");
@@ -1371,7 +1378,10 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
13711378

13721379
imageio_set_stream(env, (j_common_ptr) cinfo, data, stream);
13731380

1374-
if ((*env)->ExceptionCheck(env)) return 0;
1381+
if ((*env)->ExceptionCheck(env)) {
1382+
disposeIIO(env, data);
1383+
return 0;
1384+
}
13751385

13761386
imageio_init_source((j_decompress_ptr) cinfo);
13771387

@@ -1382,20 +1392,22 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
13821392
if (setjmp(jerr->setjmp_buffer)) {
13831393
/* If we get here, the JPEG code has signaled an error
13841394
while reading the header. */
1385-
RELEASE_ARRAYS(env, data, src->next_input_byte);
1395+
disposeIIO(env, data);
13861396
if (!(*env)->ExceptionOccurred(env)) {
13871397
char buffer[JMSG_LENGTH_MAX];
13881398
(*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
13891399
buffer);
13901400
ThrowByName(env, "java/io/IOException", buffer);
13911401
}
1402+
13921403
return 0;
13931404
}
13941405

13951406
if (GET_ARRAYS(env, data, &src->next_input_byte) == NOT_OK) {
13961407
ThrowByName(env,
13971408
"java/io/IOException",
13981409
"Array pin failed");
1410+
disposeIIO(env, data);
13991411
return 0;
14001412
}
14011413

@@ -1492,6 +1504,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
14921504
profileData = read_icc_profile(env, cinfo);
14931505

14941506
if ((*env)->ExceptionCheck(env)) {
1507+
disposeIIO(env, data);
14951508
return 0;
14961509
}
14971510

@@ -1504,6 +1517,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompr
15041517
cinfo->num_components,
15051518
profileData);
15061519
if ((*env)->ExceptionCheck(env)) {
1520+
disposeIIO(env, data);
15071521
return 0;
15081522
}
15091523
}
@@ -1598,8 +1612,8 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_decompre
15981612
struct jpeg_source_mgr *src = cinfo->src;
15991613
sun_jpeg_error_ptr jerr;
16001614
int bytes_per_row = cinfo->output_width * cinfo->output_components;
1601-
JSAMPROW scanline_ptr = (JSAMPROW) malloc(bytes_per_row * sizeof (JSAMPLE));
16021615
int offset = 0;
1616+
JSAMPROW scanline_ptr = NULL;
16031617

16041618
if (!SAFE_TO_MULT(cinfo->output_width, cinfo->output_components) ||
16051619
!SAFE_TO_MULT(bytes_per_row, cinfo->output_height) ||
@@ -1619,14 +1633,6 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_decompre
16191633
return JNI_FALSE;
16201634
}
16211635

1622-
if (scanline_ptr == NULL) {
1623-
ThrowByName(env,
1624-
"java/lang/OutOfMemoryError",
1625-
"Reading JPEG Stream");
1626-
RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1627-
return JNI_FALSE;
1628-
}
1629-
16301636
/* Establish the setjmp return context for sun_jpeg_error_exit to use. */
16311637
jerr = (sun_jpeg_error_ptr) cinfo->err;
16321638

@@ -1639,26 +1645,35 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_decompre
16391645
buffer);
16401646
ThrowByName(env, "java/io/IOException", buffer);
16411647
}
1642-
if (scanline_ptr != NULL) {
1643-
free(scanline_ptr);
1644-
}
16451648
RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
16461649
return JNI_FALSE;
16471650
}
16481651

1652+
scanline_ptr = (JSAMPROW) malloc(bytes_per_row * sizeof(JSAMPLE));
1653+
if (scanline_ptr == NULL) {
1654+
ThrowByName(env,
1655+
"java/lang/OutOfMemoryError",
1656+
"Reading JPEG Stream");
1657+
return JNI_FALSE;
1658+
}
1659+
16491660
while (cinfo->output_scanline < cinfo->output_height) {
16501661
int num_scanlines;
16511662
if (report_progress == JNI_TRUE) {
16521663
RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
16531664
(*env)->CallVoidMethod(env, this,
16541665
JPEGImageLoader_updateImageProgressID,
16551666
cinfo->output_scanline);
1656-
if ((*env)->ExceptionCheck(env)) return JNI_FALSE;
1667+
if ((*env)->ExceptionCheck(env)) {
1668+
free(scanline_ptr);
1669+
return JNI_FALSE;
1670+
}
16571671
if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1658-
ThrowByName(env,
1672+
free(scanline_ptr);
1673+
ThrowByName(env,
16591674
"java/io/IOException",
16601675
"Array pin failed");
1661-
return JNI_FALSE;
1676+
return JNI_FALSE;
16621677
}
16631678
}
16641679

@@ -1667,30 +1682,33 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_decompre
16671682
jbyte *body = (*env)->GetPrimitiveArrayCritical(env, barray, NULL);
16681683
if (body == NULL) {
16691684
fprintf(stderr, "decompressIndirect: GetPrimitiveArrayCritical returns NULL: out of memory\n");
1685+
free(scanline_ptr);
16701686
return JNI_FALSE;
16711687
}
16721688
memcpy(body+offset,scanline_ptr, bytes_per_row);
16731689
(*env)->ReleasePrimitiveArrayCritical(env, barray, body, JNI_ABORT);
16741690
offset += bytes_per_row;
16751691
}
16761692
}
1693+
free(scanline_ptr);
16771694

16781695
if (report_progress == JNI_TRUE) {
16791696
RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
16801697
(*env)->CallVoidMethod(env, this,
16811698
JPEGImageLoader_updateImageProgressID,
16821699
cinfo->output_height);
1683-
if ((*env)->ExceptionCheck(env)) return JNI_FALSE;
1684-
if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1685-
ThrowByName(env,
1700+
if ((*env)->ExceptionCheck(env)) {
1701+
return JNI_FALSE;
1702+
}
1703+
if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1704+
ThrowByName(env,
16861705
"java/io/IOException",
16871706
"Array pin failed");
1688-
return JNI_FALSE;
1689-
}
1707+
return JNI_FALSE;
1708+
}
16901709
}
16911710

16921711
jpeg_finish_decompress(cinfo);
1693-
free(scanline_ptr);
16941712

16951713
RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
16961714
return JNI_TRUE;

0 commit comments

Comments
 (0)