[Bf-committers] BUG: File handles closed multiple times (Patch attached)

Jacques Beaurain jbeaurain at istop.com
Tue Dec 7 12:31:30 CET 2004


Hi,

I found a minor bug in the image writing functions. The problem was that 
the file descriptor in the IMB_saveiff function was closed even one of 
the format specific image functions did a fclose on a stream that was 
opened  on the descriptor. The run-time library documentation has a note 
with fclose that states:

"When these functions are used to close a stream, the underlying file 
descriptor and OS file handle (or socket) are closed, as well as the 
stream. Thus, if the file was originally opened as a file handle or file 
descriptor and is closed with *fclose*, do not also call *close* to 
close the file descriptor."

The reason I needed to make this fix for my system is that I am trying 
the beta of Microsoft Visual Studio 2005 at the moment  and that the 
updated CRT libraries that ships with it asserts in both the release and 
debug  versions inside the close call because fclose has already been 
closed. This causes crashes every time I try to write an image.

They seem to have added a number of security and stability checks in 
various runtime functions. They do this through what they call an 
Invalid Parameter Handler routine. The default calls M$'s abort tool 
with some information about the invalid parameters (in this cased an 
invalid file handle). One can also install a default parameter handler 
of ones own to prevent this system from asserting
on every little thing. I do think this is a valid bug though and is not 
too sure if bad things like leaks or memory corruptions may happen in 
older versions of the CRT or on other platforms.

I will keep you posted on any other things I find.

Cheers,
Jacques
-------------- next part --------------
Index: source/blender/imbuf/intern/IMB_bmp.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/IMB_bmp.h,v
retrieving revision 1.8
diff -u -r1.8 IMB_bmp.h
--- source/blender/imbuf/intern/IMB_bmp.h	16 Jul 2004 14:45:06 -0000	1.8
+++ source/blender/imbuf/intern/IMB_bmp.h	7 Dec 2004 11:01:06 -0000
@@ -44,7 +44,7 @@
 
 int imb_is_a_bmp(void *buf);
 struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags);
-short imb_savebmp(struct ImBuf *ibuf, int outfile, int flags);
+short imb_savebmp(struct ImBuf *ibuf, int *outfile, int flags);
 
 #endif
 
Index: source/blender/imbuf/intern/IMB_iris.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/IMB_iris.h,v
retrieving revision 1.6
diff -u -r1.6 IMB_iris.h
--- source/blender/imbuf/intern/IMB_iris.h	30 May 2003 01:50:34 -0000	1.6
+++ source/blender/imbuf/intern/IMB_iris.h	7 Dec 2004 11:01:06 -0000
@@ -43,7 +43,7 @@
 struct ImBuf;
 
 struct ImBuf *imb_loadiris(unsigned char *mem, int flags);
-short imb_saveiris(struct ImBuf * ibuf, int file, int flags);
+short imb_saveiris(struct ImBuf * ibuf, int *file, int flags);
 
 #endif
 
Index: source/blender/imbuf/intern/IMB_png.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/IMB_png.h,v
retrieving revision 1.7
diff -u -r1.7 IMB_png.h
--- source/blender/imbuf/intern/IMB_png.h	4 Dec 2003 18:18:05 -0000	1.7
+++ source/blender/imbuf/intern/IMB_png.h	7 Dec 2004 11:01:06 -0000
@@ -45,7 +45,7 @@
 int imb_is_a_png(void *buf);
 struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags);
 
-short imb_savepng(struct ImBuf *ibuf, int file, int flags);
+short imb_savepng(struct ImBuf *ibuf, int *file, int flags);
 
 #endif
 
Index: source/blender/imbuf/intern/IMB_targa.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/IMB_targa.h,v
retrieving revision 1.6
diff -u -r1.6 IMB_targa.h
--- source/blender/imbuf/intern/IMB_targa.h	30 May 2003 01:50:34 -0000	1.6
+++ source/blender/imbuf/intern/IMB_targa.h	7 Dec 2004 11:01:06 -0000
@@ -45,7 +45,7 @@
 int imb_is_a_targa(void *buf);
 
 struct ImBuf *imb_loadtarga(unsigned char *mem, int flags);
-short imb_savetarga(struct ImBuf * ibuf, int file, int flags);
+short imb_savetarga(struct ImBuf * ibuf, int *file, int flags);
 
 #endif
 
Index: source/blender/imbuf/intern/bmp.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/bmp.c,v
retrieving revision 1.3
diff -u -r1.3 bmp.c
--- source/blender/imbuf/intern/bmp.c	9 Jun 2004 19:49:43 -0000	1.3
+++ source/blender/imbuf/intern/bmp.c	7 Dec 2004 11:01:06 -0000
@@ -199,7 +199,7 @@
 } 
 
 /* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
-short imb_savebmp(struct ImBuf *ibuf, int outfile, int flags) {
+short imb_savebmp(struct ImBuf *ibuf, int *outfile, int flags) {
 
    BMPINFOHEADER infoheader;
    int bytesize, extrabytes, x, y, t, ptr;
@@ -244,8 +244,10 @@
       for (t=0;t<extrabytes;t++) if (putc(0,ofile) == EOF) return 0;
    }
    if (ofile) {
-	fflush(ofile);
+		fflush(ofile);
         fclose(ofile);
+		/* The file descriptor needs to be set to -1 if it is closed to prevent the caller from attempting to close again */
+		*outfile = -1;
    }
    return 1;
 }
Index: source/blender/imbuf/intern/iris.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/iris.c,v
retrieving revision 1.7
diff -u -r1.7 iris.c
--- source/blender/imbuf/intern/iris.c	30 Mar 2004 14:33:02 -0000	1.7
+++ source/blender/imbuf/intern/iris.c	7 Dec 2004 11:01:06 -0000
@@ -532,7 +532,7 @@
  *  Added: zbuf write
  */
 
-static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, int file, int *zptr)
+static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, int *file, int *zptr)
 {
 	FILE *outf;
 	IMAGE *image;
@@ -612,6 +612,8 @@
 	free(rlebuf);
 	free(lumbuf);
 	fclose(outf);
+	/* The file descriptor needs to be set to -1 if it is closed to prevent the caller from attempting to close again */
+	*file = -1;
 	if(goodwrite)
 		return 1;
 	else {
@@ -690,7 +692,7 @@
 	return optr - (unsigned char *)rlebuf;
 }
 
-short imb_saveiris(struct ImBuf * ibuf, int file, int flags)
+short imb_saveiris(struct ImBuf * ibuf, int *file, int flags)
 {
 	short zsize;
 	int ret;
Index: source/blender/imbuf/intern/png.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/png.c,v
retrieving revision 1.1
diff -u -r1.1 png.c
--- source/blender/imbuf/intern/png.c	4 Dec 2003 18:18:05 -0000	1.1
+++ source/blender/imbuf/intern/png.c	7 Dec 2004 11:01:06 -0000
@@ -106,7 +106,7 @@
 	longjmp(png_jmpbuf(png_ptr), 1);
 }
 
-short imb_savepng(struct ImBuf *ibuf, int file, int flags)
+short imb_savepng(struct ImBuf *ibuf, int *file, int flags)
 {
 	png_structp png_ptr;
 	png_infop info_ptr;
@@ -198,7 +198,7 @@
 			 WriteData,
 			 Flush);
 	} else {
-		fp = fdopen(file, "wb");
+		fp = fdopen(*file, "wb");
 		png_init_io(png_ptr, fp);
 	}
 
@@ -255,6 +255,8 @@
 	if (fp) {
 		fflush(fp);
 		fclose(fp);
+		// The file descriptor needs to be set to -1 if it is closed to prevent the caller from attempting to close again
+		*file = -1;
 	}
 
 	return(1);
Index: source/blender/imbuf/intern/targa.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/targa.c,v
retrieving revision 1.7
diff -u -r1.7 targa.c
--- source/blender/imbuf/intern/targa.c	22 Jan 2004 12:59:46 -0000	1.7
+++ source/blender/imbuf/intern/targa.c	7 Dec 2004 11:01:06 -0000
@@ -242,7 +242,7 @@
 }
 
 
-short imb_savetarga(struct ImBuf * ibuf, int file, int flags)
+short imb_savetarga(struct ImBuf * ibuf, int *file, int flags)
 {
 	char buf[20];
 	FILE *fildes;
@@ -325,6 +325,8 @@
 	}
 	
 	fclose(fildes);
+	/* The file descriptor needs to be set to -1 if it is closed to prevent the caller from attempting to close again */
+	*file = -1;
 	return (ok);
 }
 
Index: source/blender/imbuf/intern/writeimage.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/imbuf/intern/writeimage.c,v
retrieving revision 1.8
diff -u -r1.8 writeimage.c
--- source/blender/imbuf/intern/writeimage.c	30 Aug 2004 18:43:00 -0000	1.8
+++ source/blender/imbuf/intern/writeimage.c	7 Dec 2004 11:01:06 -0000
@@ -70,12 +70,16 @@
 
 	/* Put formats that take a filename here */
 	if (IS_jpg(ibuf)) {
-		if(imb_savejpeg(ibuf, naam, flags)) return (0);
-		else return (TRUE);
+		/* The imb_savejpeg function returns TRUE on error */
+		ok = !imb_savejpeg(ibuf, naam, flags);
+		goto cleanup;
 	}
 
 	file = open(naam, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666);
-	if (file < 0) return (FALSE);
+	if (file < 0) {
+		ok = FALSE;
+		goto cleanup;
+	}
 
 	if (flags & IB_rect){
 		if (ibuf->cmap){
@@ -85,35 +89,23 @@
 
 	/* Put formats that take a filehandle here */
 	if (IS_png(ibuf)) {
-		ok = imb_savepng(ibuf,file,flags);
-		if (ok) {
-			close (file);
-			return (ok);
-		}
+		ok = imb_savepng(ibuf,&file,flags);
+		goto cleanup;
 	}
 
-        if (IS_bmp(ibuf)) {
-                ok = imb_savebmp(ibuf,file,flags);
-                if (ok) {
-                        close (file);
-                        return (ok);
-                }
-        }
+	if (IS_bmp(ibuf)) {
+		ok = imb_savebmp(ibuf,&file,flags);
+		goto cleanup;
+	}
 
 	if (IS_tga(ibuf)) {
-		ok = imb_savetarga(ibuf,file,flags);
-		if (ok) {
-			close (file);
-			return (ok);
-		}
+		ok = imb_savetarga(ibuf,&file,flags);
+		goto cleanup;
 	}
 	
 	if (IS_iris(ibuf)) {
-		ok = imb_saveiris(ibuf,file,flags);
-		if (ok) {
-			close (file);
-			return (ok);
-		}
+		ok = imb_saveiris(ibuf,&file,flags);
+		goto cleanup;
 	}
 	
 	if (ok) ok = imb_start_iff(ibuf,file);
@@ -144,11 +136,14 @@
 			if (ok) ok = imb_encodebodyh(ibuf,file);
 		}
 		if (ok) ok = imb_update_iff(file,BODY);
-	}else if (IS_anim(ibuf)) {
+	} else if (IS_anim(ibuf)) {
 		if (ok) ok = imb_enc_anim(ibuf, file);
 		if (ok) ok = imb_update_iff(file, BODY);
 	}
-	close(file);
+
+cleanup:
+	if (file!=-1)
+		close(file);
 
 	if (ok==FALSE) {
 		fprintf(stderr,"Couldn't save picture.\n");


More information about the Bf-committers mailing list