fix #H5780 - file pointer freed twice

win/share/tileset.c seems only to be used by the MSDOS port, but it
compiles cleanly on OSX after these changes.

A file pointer was passed to fclose() twice, second time potentially
causing problems.  There were cases of potentially null pointers
being passed to free() too.  That should be safe these days, but it's
something we've tried to hard to avoid and would probably trigger
complaints from our own MONITOR_HEAP code if that ever got applied
here.
This commit is contained in:
PatR
2017-07-30 18:17:00 -07:00
parent e3c4ac730d
commit b4240e1772
+32 -29
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 tileset.c $NHDT-Date: 1457207053 2016/03/05 19:44:13 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */ /* NetHack 3.6 tileset.c $NHDT-Date: 1501463811 2017/07/31 01:16:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */
/* Copyright (c) Ray Chason, 2016. */ /* Copyright (c) Ray Chason, 2016. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -25,7 +25,7 @@ boolean true_color;
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
}; };
struct TileSetImage image; struct TileSetImage image;
FILE *fp = NULL; /* custodial */ FILE *fp;
char header[16]; char header[16];
boolean ok; boolean ok;
@@ -40,10 +40,11 @@ boolean true_color;
/* Identify the image type */ /* Identify the image type */
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if (fp == NULL) goto error; if (!fp)
goto error;
memset(header, 0, sizeof(header)); memset(header, 0, sizeof(header));
fread(header, 1, sizeof(header), fp); fread(header, 1, sizeof(header), fp);
fclose(fp); fclose(fp), fp = (FILE *) 0;
/* Call the loader appropriate for the image */ /* Call the loader appropriate for the image */
if (memcmp(header, "BM", 2) == 0) { if (memcmp(header, "BM", 2) == 0) {
@@ -56,11 +57,13 @@ boolean true_color;
} else { } else {
ok = FALSE; ok = FALSE;
} }
if (!ok) goto error; if (!ok)
goto error;
/* Reject if the interface cannot handle direct color and the image does /* Reject if the interface cannot handle direct color and the image does
not use a palette */ not use a palette */
if (!true_color && image.indexes == NULL) goto error; if (!true_color && image.indexes == NULL)
goto error;
/* Save the palette if present */ /* Save the palette if present */
have_palette = image.indexes != NULL; have_palette = image.indexes != NULL;
@@ -87,12 +90,12 @@ boolean true_color;
/* Split the image into tiles */ /* Split the image into tiles */
split_tiles(&image); split_tiles(&image);
fclose(fp);
free_image(&image); free_image(&image);
return TRUE; return TRUE;
error: error:
if (fp) fclose(fp); if (fp)
fclose(fp);
free_image(&image); free_image(&image);
return FALSE; return FALSE;
} }
@@ -108,6 +111,7 @@ static void
get_tile_map(image_desc) get_tile_map(image_desc)
const char *image_desc; const char *image_desc;
{ {
return;
} }
void void
@@ -115,43 +119,40 @@ free_tiles()
{ {
unsigned i; unsigned i;
if (tiles != NULL) { if (tiles) {
for (i = 0; i < num_tiles; ++i) { for (i = 0; i < num_tiles; ++i) {
free(tiles[i].pixels); free((genericptr_t) tiles[i].pixels);
free(tiles[i].indexes); free((genericptr_t) tiles[i].indexes);
} }
free((genericptr_t) tiles), tiles = NULL;
} }
free(tiles);
tiles = NULL;
num_tiles = 0; num_tiles = 0;
free(blank_tile.pixels); if (blank_tile.pixels)
blank_tile.pixels = NULL; free((genericptr_t) blank_tile.pixels), blank_tile.pixels = NULL;
free(blank_tile.indexes); if (blank_tile.indexes)
blank_tile.indexes = NULL; free((genericptr_t) blank_tile.indexes), blank_tile.indexes = NULL;
} }
static void static void
free_image(image) free_image(image)
struct TileSetImage *image; struct TileSetImage *image;
{ {
free(image->pixels); if (image->pixels)
image->pixels = NULL; free((genericptr_t) image->pixels), image->pixels = NULL;
free(image->indexes); if (image->indexes)
image->indexes = NULL; free((genericptr_t) image->indexes), image->indexes = NULL;
free(image->image_desc); if (image->image_desc)
image->image_desc = NULL; free((genericptr_t) image->image_desc), image->image_desc = NULL;
} }
const struct TileImage * const struct TileImage *
get_tile(tile_index) get_tile(tile_index)
unsigned tile_index; unsigned tile_index;
{ {
if (tile_index >= num_tiles) { if (tile_index >= num_tiles)
return &blank_tile; return &blank_tile;
} else { return &tiles[tile_index];
return &tiles[tile_index];
}
} }
static void static void
@@ -176,10 +177,11 @@ const struct TileSetImage *image;
for (y1 = 0; y1 < tile_rows; ++y1) { for (y1 = 0; y1 < tile_rows; ++y1) {
for (x1 = 0; x1 < tile_cols; ++x1) { for (x1 = 0; x1 < tile_cols; ++x1) {
struct TileImage *tile = &tiles[y1 * tile_cols + x1]; struct TileImage *tile = &tiles[y1 * tile_cols + x1];
tile->width = iflags.wc_tile_width; tile->width = iflags.wc_tile_width;
tile->height = iflags.wc_tile_height; tile->height = iflags.wc_tile_height;
tile->pixels = (struct Pixel *) tile->pixels = (struct Pixel *)
alloc(tile_size * sizeof(struct Pixel)); alloc(tile_size * sizeof (struct Pixel));
if (image->indexes != NULL) { if (image->indexes != NULL) {
tile->indexes = (unsigned char *) alloc(tile_size); tile->indexes = (unsigned char *) alloc(tile_size);
} }
@@ -187,6 +189,7 @@ const struct TileSetImage *image;
for (x2 = 0; x2 < iflags.wc_tile_width; ++x2) { for (x2 = 0; x2 < iflags.wc_tile_width; ++x2) {
unsigned x = x1 * iflags.wc_tile_width + x2; unsigned x = x1 * iflags.wc_tile_width + x2;
unsigned y = y1 * iflags.wc_tile_height + y2; unsigned y = y1 * iflags.wc_tile_height + y2;
i = y * image->width + x; i = y * image->width + x;
j = y2 * tile->width + x2; j = y2 * tile->width + x2;
tile->pixels[j] = image->pixels[i]; tile->pixels[j] = image->pixels[i];
@@ -202,7 +205,7 @@ const struct TileSetImage *image;
blank_tile.width = iflags.wc_tile_width; blank_tile.width = iflags.wc_tile_width;
blank_tile.height = iflags.wc_tile_height; blank_tile.height = iflags.wc_tile_height;
blank_tile.pixels = (struct Pixel *) blank_tile.pixels = (struct Pixel *)
alloc(tile_size * sizeof(struct Pixel)); alloc(tile_size * sizeof (struct Pixel));
for (i = 0; i < tile_size; ++i) { for (i = 0; i < tile_size; ++i) {
blank_tile.pixels[i].r = 0; blank_tile.pixels[i].r = 0;
blank_tile.pixels[i].g = 0; blank_tile.pixels[i].g = 0;