[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25053] trunk/blender/source/blender/imbuf /intern/jpeg.c: fix for [#19990] file browser crash

Andrea Weikert elubie at gmx.net
Tue Dec 1 21:38:02 CET 2009


Revision: 25053
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25053
Author:   elubie
Date:     2009-12-01 21:37:26 +0100 (Tue, 01 Dec 2009)

Log Message:
-----------
fix for [#19990] file browser crash

needed to fix jpg error handling to not return control to the library from jpg_error used as error exit. Needed to add structured exception handling (setjmp/longjmp) - not very nice but needed in this case. (Also recommended in example.c from libjpg and used in gimp ;) )

Modified Paths:
--------------
    trunk/blender/source/blender/imbuf/intern/jpeg.c

Modified: trunk/blender/source/blender/imbuf/intern/jpeg.c
===================================================================
--- trunk/blender/source/blender/imbuf/intern/jpeg.c	2009-12-01 19:43:09 UTC (rev 25052)
+++ trunk/blender/source/blender/imbuf/intern/jpeg.c	2009-12-01 20:37:26 UTC (rev 25053)
@@ -32,6 +32,8 @@
 
 /* This little block needed for linking to Blender... */
 #include <stdio.h>
+#include <setjmp.h>
+
 #include "BLI_blenlib.h"
 
 #include "imbuf.h"
@@ -41,6 +43,7 @@
 #include "IMB_imginfo.h"
 #include "IMB_jpeg.h"
 #include "jpeglib.h" 
+#include "jerror.h"
 
 /* the types are from the jpeg lib */
 static void jpeg_error (j_common_ptr cinfo);
@@ -66,7 +69,6 @@
  * 4. jmax - no scaling in the components
  */
 
-static int jpeg_failed = FALSE;
 static int jpeg_default_quality;
 static int ibuf_ftype;
 
@@ -76,15 +78,30 @@
 	return 0;
 }
 
+//----------------------------------------------------------
+//	JPG ERROR HANDLING
+//----------------------------------------------------------
+
+typedef struct my_error_mgr {
+  struct jpeg_error_mgr pub;	/* "public" fields */
+
+  jmp_buf setjmp_buffer;	/* for return to caller */
+} my_error_mgr;
+
+typedef my_error_mgr * my_error_ptr;
+
 static void jpeg_error (j_common_ptr cinfo)
 {
+	my_error_ptr err = (my_error_ptr)cinfo->err;
+
 	/* Always display the message */
 	(*cinfo->err->output_message) (cinfo);
 
 	/* Let the memory manager delete any temp files before we die */
 	jpeg_destroy(cinfo);
 
-	jpeg_failed = TRUE;
+	/* return control to the setjmp point */
+	longjmp(err->setjmp_buffer, 1);
 }
 
 //----------------------------------------------------------
@@ -255,7 +272,7 @@
 		x = cinfo->image_width;
 		y = cinfo->image_height;
 		depth = cinfo->num_components;
-		
+
 		if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK;
 
 		jpeg_start_decompress(cinfo);
@@ -407,15 +424,25 @@
 ImBuf * imb_ibJpegImageFromFilename (const char * filename, int flags)
 {
 	struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
-	struct jpeg_error_mgr jerr;
+	struct my_error_mgr jerr;
 	FILE * infile;
 	ImBuf * ibuf;
 	
 	if ((infile = fopen(filename, "rb")) == NULL) return 0;
 
-	cinfo->err = jpeg_std_error(&jerr);
-	jerr.error_exit = jpeg_error;
+	cinfo->err = jpeg_std_error(&jerr.pub);
+	jerr.pub.error_exit = jpeg_error;
 
+	/* Establish the setjmp return context for my_error_exit to use. */
+	if (setjmp(jerr.setjmp_buffer)) {
+		/* If we get here, the JPEG code has signaled an error.
+		 * We need to clean up the JPEG object, close the input file, and return.
+		 */
+		jpeg_destroy_decompress(cinfo);
+		fclose(infile);
+		return NULL;
+	}
+
 	jpeg_create_decompress(cinfo);
 	jpeg_stdio_src(cinfo, infile);
 
@@ -428,12 +455,21 @@
 ImBuf * imb_ibJpegImageFromMemory (unsigned char * buffer, int size, int flags)
 {
 	struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
-	struct jpeg_error_mgr jerr;
+	struct my_error_mgr jerr;
 	ImBuf * ibuf;
 	
-	cinfo->err = jpeg_std_error(&jerr);
-	jerr.error_exit = jpeg_error;
+	cinfo->err = jpeg_std_error(&jerr.pub);
+	jerr.pub.error_exit = jpeg_error;
 
+	/* Establish the setjmp return context for my_error_exit to use. */
+	if (setjmp(jerr.setjmp_buffer)) {
+		/* If we get here, the JPEG code has signaled an error.
+		 * We need to clean up the JPEG object, close the input file, and return.
+		 */
+		jpeg_destroy_decompress(cinfo);
+		return NULL;
+	}
+
 	jpeg_create_decompress(cinfo);
 	memory_source(cinfo, buffer, size);
 
@@ -521,11 +557,9 @@
 		}
 
 		jpeg_write_scanlines(cinfo, row_pointer, 1);
-
-		if (jpeg_failed) break;
 	}
 
-	if (jpeg_failed == FALSE) jpeg_finish_compress(cinfo);
+	jpeg_finish_compress(cinfo);
 	free(row_pointer[0]);
 }
 
@@ -577,14 +611,25 @@
 {
 	FILE * outfile;
 	struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
-	struct jpeg_error_mgr jerr;
+	struct my_error_mgr jerr;
 
 	if ((outfile = fopen(name, "wb")) == NULL) return 0;
 	jpeg_default_quality = 75;
 
-	cinfo->err = jpeg_std_error(&jerr);
-	jerr.error_exit = jpeg_error;
+	cinfo->err = jpeg_std_error(&jerr.pub);
+	jerr.pub.error_exit = jpeg_error;
 
+	/* Establish the setjmp return context for jpeg_error to use. */
+	if (setjmp(jerr.setjmp_buffer)) {
+		/* If we get here, the JPEG code has signaled an error.
+		 * We need to clean up the JPEG object, close the input file, and return.
+		 */
+		jpeg_destroy_compress(cinfo);
+		fclose(outfile);
+		remove(name);
+		return 0;
+	}
+
 	init_jpeg(outfile, cinfo, ibuf);
 
 	write_jpeg(cinfo, ibuf);
@@ -592,10 +637,6 @@
 	fclose(outfile);
 	jpeg_destroy_compress(cinfo);
 
-	if (jpeg_failed) {
-		remove(name);
-		return 0;
-	}
 	return 1;
 }
 
@@ -604,14 +645,25 @@
 {
 	FILE * outfile;
 	struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
-	struct jpeg_error_mgr jerr;
+	struct my_error_mgr jerr;
 
 	if ((outfile = fopen(name, "wb")) == NULL) return 0;
 	jpeg_default_quality = 90;
 
-	cinfo->err = jpeg_std_error(&jerr);
-	jerr.error_exit = jpeg_error;
+	cinfo->err = jpeg_std_error(&jerr.pub);
+	jerr.pub.error_exit = jpeg_error;
 
+	/* Establish the setjmp return context for jpeg_error to use. */
+	if (setjmp(jerr.setjmp_buffer)) {
+		/* If we get here, the JPEG code has signaled an error.
+		 * We need to clean up the JPEG object, close the input file, and return.
+		 */
+		jpeg_destroy_compress(cinfo);
+		fclose(outfile);
+		remove(name);
+		return 0;
+	}
+
 	init_jpeg(outfile, cinfo, ibuf);
 
 	/* adjust scaling factors */
@@ -625,10 +677,6 @@
 	fclose(outfile);
 	jpeg_destroy_compress(cinfo);
 
-	if (jpeg_failed) {
-		remove(name);
-		return 0;
-	}
 	return 1;
 }
 
@@ -667,14 +715,25 @@
 {
 	FILE * outfile;
 	struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
-	struct jpeg_error_mgr jerr;
+	struct my_error_mgr jerr;
 
 	if ((outfile = fopen(name, "wb")) == NULL) return 0;
 	jpeg_default_quality = 100;
 
-	cinfo->err = jpeg_std_error(&jerr);
-	jerr.error_exit = jpeg_error;
+	cinfo->err = jpeg_std_error(&jerr.pub);
+	jerr.pub.error_exit = jpeg_error;
 
+	/* Establish the setjmp return context for jpeg_error to use. */
+	if (setjmp(jerr.setjmp_buffer)) {
+		/* If we get here, the JPEG code has signaled an error.
+		 * We need to clean up the JPEG object, close the input file, and return.
+		 */
+		jpeg_destroy_compress(cinfo);
+		fclose(outfile);
+		remove(name);
+		return 0;
+	}
+
 	init_jpeg(outfile, cinfo, ibuf);
 
 	/* adjust scaling factors */
@@ -688,10 +747,6 @@
 	fclose(outfile);
 	jpeg_destroy_compress(cinfo);
 
-	if (jpeg_failed) {
-		remove(name);
-		return 0;
-	}
 	return 1;
 }
 





More information about the Bf-blender-cvs mailing list