Remove static variable, fix gcc warning [-Wclobbered] (#203)

PR #203 "Multithread fix for PNG loading" includes a suggested fix
that moves the variable fp to the Fl_PNG_Image structure.

This commit fixes the threading issue by allocating the variable fp
with new, avoiding the [-Wclobbered] warning w/o using a static var.

The same issue is now also fixed in Fl_JPEG_Image.
This commit is contained in:
Albrecht Schlosser 2021-04-07 10:55:13 +02:00
parent 4e086a1cdf
commit 7f969b5496
2 changed files with 36 additions and 18 deletions

View File

@ -4,6 +4,8 @@
// Copyright 1997-2011 by Easy Software Products.
// Image support by Matthias Melcher, Copyright 2000-2009.
//
// Copyright 2013-2021 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
@ -212,15 +214,21 @@ static void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *data)
void Fl_JPEG_Image::load_jpg_(const char *filename, const char *sharename, const unsigned char *data)
{
#ifdef HAVE_LIBJPEG
FILE *fp = 0L; // File pointer
jpeg_decompress_struct dinfo; // Decompressor info
fl_jpeg_error_mgr jerr; // Error handler info
JSAMPROW row; // Sample row pointer
// the following variables are pointers allocating some private space that
// is not reset by 'setjmp()'
char* max_finish_decompress_err; // count errors and give up afer a while
char* max_destroy_decompress_err; // to avoid recusion and deadlock
char* max_finish_decompress_err; // count errors and give up after a while
char* max_destroy_decompress_err; // to avoid recursion and deadlock
// Note: The file pointer fp must not be an automatic (stack) variable
// to avoid potential clobbering by setjmp/longjmp (gcc: [-Wclobbered]).
// Hence the actual 'fp' is allocated with operator new.
FILE** fp = new FILE*; // always allocate file pointer
*fp = NULL;
// Clear data...
alloc_array = 0;
@ -228,13 +236,15 @@ void Fl_JPEG_Image::load_jpg_(const char *filename, const char *sharename, const
// Open the image file if we read from the file system
if (filename) {
if ((fp = fl_fopen(filename, "rb")) == NULL) {
if ((*fp = fl_fopen(filename, "rb")) == NULL) {
ld(ERR_FILE_ACCESS);
delete fp;
return;
}
} else {
if (data==0L) {
ld(ERR_FILE_ACCESS);
delete fp;
return;
}
}
@ -264,8 +274,8 @@ void Fl_JPEG_Image::load_jpg_(const char *filename, const char *sharename, const
if ( (*max_destroy_decompress_err)-- > 0)
jpeg_destroy_decompress(&dinfo);
if (fp)
fclose(fp);
if (*fp)
fclose(*fp);
w(0);
h(0);
@ -281,12 +291,13 @@ void Fl_JPEG_Image::load_jpg_(const char *filename, const char *sharename, const
free(max_finish_decompress_err);
ld(ERR_FORMAT);
delete fp;
return;
}
jpeg_create_decompress(&dinfo);
if (fp) {
jpeg_stdio_src(&dinfo, fp);
if (*fp) {
jpeg_stdio_src(&dinfo, *fp);
} else {
jpeg_mem_src(&dinfo, data);
}
@ -322,12 +333,13 @@ void Fl_JPEG_Image::load_jpg_(const char *filename, const char *sharename, const
free(max_destroy_decompress_err);
free(max_finish_decompress_err);
if (fp)
fclose(fp);
if (*fp)
fclose(*fp);
if (sharename && w() && h()) {
Fl_Shared_Image *si = new Fl_Shared_Image(sharename, this);
si->add();
}
delete fp;
#endif // HAVE_LIBJPEG
}

View File

@ -4,7 +4,7 @@
// Copyright 1997-2012 by Easy Software Products.
// Image support by Matthias Melcher, Copyright 2000-2009.
//
// Copyright 2013-2017 by Bill Spitzak and others.
// Copyright 2013-2021 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -123,12 +123,15 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
// Note: The file pointer fp must not be an automatic (stack) variable
// to avoid potential clobbering by setjmp/longjmp (gcc: [-Wclobbered]).
static FILE *fp; // intentionally initialized separately below
fp = NULL; // always initialize file pointer
// Hence the actual 'fp' is allocated with operator new.
FILE** fp = new FILE*; // always allocate file pointer
*fp = NULL;
if (!from_memory) {
if ((fp = fl_fopen(name_png, "rb")) == NULL) {
if ((*fp = fl_fopen(name_png, "rb")) == NULL) {
ld(ERR_FILE_ACCESS);
delete fp;
return;
}
}
@ -139,17 +142,19 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
if (pp) info = png_create_info_struct(pp);
if (!pp || !info) {
if (pp) png_destroy_read_struct(&pp, NULL, NULL);
if (!from_memory) fclose(fp);
if (!from_memory) fclose(*fp);
Fl::warning("Cannot allocate memory to read PNG file or data \"%s\".\n", display_name);
w(0); h(0); d(0); ld(ERR_FORMAT);
delete fp;
return;
}
if (setjmp(png_jmpbuf(pp))) {
png_destroy_read_struct(&pp, &info, NULL);
if (!from_memory) fclose(fp);
if (!from_memory) fclose(*fp);
Fl::warning("PNG file or data \"%s\" is too large or contains errors!\n", display_name);
w(0); h(0); d(0); ld(ERR_FORMAT);
delete fp;
return;
}
@ -160,7 +165,7 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
// Initialize the function pointer to the PNG read "engine"...
png_set_read_fn (pp, (png_voidp) &png_mem_data, png_read_data_from_mem);
} else {
png_init_io(pp, fp); // Initialize the PNG file read "engine"...
png_init_io(pp, *fp); // Initialize the PNG file read "engine"...
}
// Get the image dimensions and convert to grayscale or RGB...
@ -225,7 +230,8 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
si->add();
}
} else {
fclose(fp);
fclose(*fp);
}
delete fp;
#endif // HAVE_LIBPNG && HAVE_LIBZ
}