From 894cc0386c3d51735546e6835f5a6ac74ced4ce7 Mon Sep 17 00:00:00 2001 From: Thomas BERNARD Date: Fri, 30 Nov 2018 13:36:11 +0100 Subject: [PATCH] Add patches for SDL_image-1.2.12 for XCF loading see http://pulkomandy.tk/projects/GrafX2/ticket/88 --- 3rdparty/Makefile | 4 + .../SDL_image-1.2.12.XCF_infinite_loop.patch | 86 +++++++ ..._image-1.2.12.XCF_v11_64bits_offsets.patch | 235 ++++++++++++++++++ 3rdparty/SDL_image_XCF_v11_load_level.patch | 53 ++++ 4 files changed, 378 insertions(+) create mode 100644 3rdparty/SDL_image-1.2.12.XCF_infinite_loop.patch create mode 100644 3rdparty/SDL_image-1.2.12.XCF_v11_64bits_offsets.patch create mode 100644 3rdparty/SDL_image_XCF_v11_load_level.patch diff --git a/3rdparty/Makefile b/3rdparty/Makefile index b974c8c4..68ccf4df 100644 --- a/3rdparty/Makefile +++ b/3rdparty/Makefile @@ -4,6 +4,9 @@ SDLDEVELPATCH = SDL-1.2.15.patch SDLIMAGE = SDL_image-1.2.12 SDLIMAGEARCH = SDL_image-1.2.12.tar.gz SDLIMAGEURL = https://www.libsdl.org/projects/SDL_image/release/$(SDLIMAGEARCH) +SDLIMAGEPATCHES = SDL_image-1.2.12.XCF_infinite_loop.patch \ + SDL_image-1.2.12.XCF_v11_64bits_offsets.patch \ + SDL_image_XCF_v11_load_level.patch SDLTTF=SDL_ttf-2.0.11 SDLTTFARCH=$(SDLTTF).tar.gz SDLTTFURL=https://www.libsdl.org/projects/SDL_ttf/release/$(SDLTTFARCH) @@ -151,6 +154,7 @@ endif $(SDLIMAGE)/.ok: archives/$(SDLIMAGEARCH) $(TAR) xzf $< + cd $(SDLIMAGE) ; for p in $(SDLIMAGEPATCHES) ; do echo "applying $$p" ; patch -p1 < ../$$p ; done touch $@ $(PREFIX)/lib/libSDL_ttf.a: $(PREFIX)/lib/libfreetype.a diff --git a/3rdparty/SDL_image-1.2.12.XCF_infinite_loop.patch b/3rdparty/SDL_image-1.2.12.XCF_infinite_loop.patch new file mode 100644 index 00000000..f535d3ad --- /dev/null +++ b/3rdparty/SDL_image-1.2.12.XCF_infinite_loop.patch @@ -0,0 +1,86 @@ +# HG changeset patch +# User Thomas Bernard +# Date 1543572255 -3600 +# Fri Nov 30 11:04:15 2018 +0100 +# Branch SDL-1.2 +# Node ID 68f958f43339b1aa1ad61d470dc8a6b9ef670dcf +# Parent 89225c8816d6d487bee10642d0380442dc19490d +IMG_xcf.c: Avoid infinite loop in read_xcf_header() + +diff -r 89225c8816d6 -r 68f958f43339 IMG_xcf.c +--- a/IMG_xcf.c Tue Oct 23 23:00:02 2018 +0300 ++++ b/IMG_xcf.c Fri Nov 30 11:04:15 2018 +0100 +@@ -263,12 +263,12 @@ + | ((v & 0xFF000000)); + } + +-static void xcf_read_property (SDL_RWops * src, xcf_prop * prop) { ++static int xcf_read_property (SDL_RWops * src, xcf_prop * prop) { + prop->id = SDL_ReadBE32 (src); + prop->length = SDL_ReadBE32 (src); + + #if DEBUG +- printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length); ++ printf ("%.8X: %s(%u): %u\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->id, prop->length); + #endif + + switch (prop->id) { +@@ -301,8 +301,10 @@ + break; + default: + // SDL_RWread (src, &prop->data, prop->length, 1); +- SDL_RWseek (src, prop->length, RW_SEEK_CUR); ++ if (SDL_RWseek (src, prop->length, RW_SEEK_CUR) < 0) ++ return 0; // ERROR + } ++ return 1; // OK + } + + static void free_xcf_header (xcf_header * h) { +@@ -325,6 +327,10 @@ + h->width = SDL_ReadBE32 (src); + h->height = SDL_ReadBE32 (src); + h->image_type = SDL_ReadBE32 (src); ++#ifdef DEBUG ++ printf ("XCF signature : %.14s\n", h->sign); ++ printf (" (%u,%u) type=%u\n", h->width, h->height, h->image_type); ++#endif + + h->properties = NULL; + h->layer_file_offsets = NULL; +@@ -334,7 +340,10 @@ + + // Just read, don't save + do { +- xcf_read_property (src, &prop); ++ if (!xcf_read_property (src, &prop)) { ++ free_xcf_header (h); ++ return NULL; ++ } + if (prop.id == PROP_COMPRESSION) + h->compr = (xcf_compr_type)prop.data.compression; + else if (prop.id == PROP_COLORMAP) { +@@ -378,7 +387,10 @@ + l->name = read_string (src); + + do { +- xcf_read_property (src, &prop); ++ if (!xcf_read_property (src, &prop)) { ++ free_xcf_layer (l); ++ return NULL; ++ } + if (prop.id == PROP_OFFSETS) { + l->offset_x = prop.data.offset.x; + l->offset_y = prop.data.offset.y; +@@ -410,7 +422,10 @@ + + l->selection = 0; + do { +- xcf_read_property (src, &prop); ++ if (!xcf_read_property (src, &prop)) { ++ free_xcf_channel (l); ++ return NULL; ++ } + switch (prop.id) { + case PROP_OPACITY: + l->opacity = prop.data.opacity << 24; diff --git a/3rdparty/SDL_image-1.2.12.XCF_v11_64bits_offsets.patch b/3rdparty/SDL_image-1.2.12.XCF_v11_64bits_offsets.patch new file mode 100644 index 00000000..0ed9e34e --- /dev/null +++ b/3rdparty/SDL_image-1.2.12.XCF_v11_64bits_offsets.patch @@ -0,0 +1,235 @@ +--- SDL_image-1.2.12/IMG_xcf.c-orig 2018-12-03 11:36:47.264845000 +0100 ++++ SDL_image-1.2.12/IMG_xcf.c 2018-12-03 11:37:34.517796000 +0100 +@@ -143,9 +143,11 @@ + + typedef struct { + char sign [14]; ++ Uint32 file_version; + Uint32 width; + Uint32 height; + Sint32 image_type; ++ Uint32 precision; + xcf_prop * properties; + + Uint32 * layer_file_offsets; +@@ -241,6 +243,13 @@ + return data; + } + ++static Uint64 read_offset (SDL_RWops * src, const xcf_header * h) { ++ Uint64 offset; // starting with version 11, offsets are 64 bits ++ offset = (h->file_version >= 11) ? (Uint64)SDL_ReadBE32 (src) << 32 : 0; ++ offset |= SDL_ReadBE32 (src); ++ return offset; ++} ++ + + static Uint32 Swap32 (Uint32 v) { + return +@@ -303,10 +312,15 @@ + h->width = SDL_ReadBE32 (src); + h->height = SDL_ReadBE32 (src); + h->image_type = SDL_ReadBE32 (src); ++ h->file_version = (h->sign[10] - '0') * 100 + (h->sign[11] - '0') * 10 + (h->sign[12] - '0'); + #ifdef DEBUG +- printf ("XCF signature : %.14s\n", h->sign); ++ printf ("XCF signature : %.14s (version %u)\n", h->sign, h->file_version); + printf (" (%u,%u) type=%u\n", h->width, h->height, h->image_type); + #endif ++ if (h->file_version >= 4) ++ h->precision = SDL_ReadBE32 (src); ++ else ++ h->precision = 150; + + h->properties = NULL; + h->compr = COMPR_NONE; +@@ -339,7 +353,7 @@ + free (l); + } + +-static xcf_layer * read_xcf_layer (SDL_RWops * src) { ++static xcf_layer * read_xcf_layer (SDL_RWops * src, const xcf_header * h) { + xcf_layer * l; + xcf_prop prop; + +@@ -349,6 +363,9 @@ + l->layer_type = SDL_ReadBE32 (src); + + l->name = read_string (src); ++#ifdef DEBUG ++ printf ("layer (%d,%d) type=%d '%s'\n", l->width, l->height, l->layer_type, l->name); ++#endif + + do { + if (!xcf_read_property (src, &prop)) { +@@ -363,8 +380,8 @@ + } + } while (prop.id != PROP_END); + +- l->hierarchy_file_offset = SDL_ReadBE32 (src); +- l->layer_mask_offset = SDL_ReadBE32 (src); ++ l->hierarchy_file_offset = read_offset (src, h); ++ l->layer_mask_offset = read_offset (src, h); + + return l; + } +@@ -374,7 +391,7 @@ + free (c); + } + +-static xcf_channel * read_xcf_channel (SDL_RWops * src) { ++static xcf_channel * read_xcf_channel (SDL_RWops * src, const xcf_header * h) { + xcf_channel * l; + xcf_prop prop; + +@@ -383,6 +400,9 @@ + l->height = SDL_ReadBE32 (src); + + l->name = read_string (src); ++#ifdef DEBUG ++ printf ("channel (%u,%u) '%s'\n", l->width, l->height, l->name); ++#endif + + l->selection = 0; + do { +@@ -410,7 +430,7 @@ + } + } while (prop.id != PROP_END); + +- l->hierarchy_file_offset = SDL_ReadBE32 (src); ++ l->hierarchy_file_offset = read_offset (src, h); + + return l; + } +@@ -420,7 +440,7 @@ + free (h); + } + +-static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) { ++static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src, const xcf_header * head) { + xcf_hierarchy * h; + int i; + +@@ -433,7 +453,7 @@ + i = 0; + do { + h->level_file_offsets = (Uint32 *) realloc (h->level_file_offsets, sizeof (Uint32) * (i+1)); +- h->level_file_offsets [i] = SDL_ReadBE32 (src); ++ h->level_file_offsets [i] = read_offset (src, head); + } while (h->level_file_offsets [i++]); + + return h; +@@ -444,7 +464,7 @@ + free (l); + } + +-static xcf_level * read_xcf_level (SDL_RWops * src) { ++static xcf_level * read_xcf_level (SDL_RWops * src, const xcf_header * h) { + xcf_level * l; + int i; + +@@ -456,7 +476,7 @@ + i = 0; + do { + l->tile_file_offsets = (Uint32 *) realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1)); +- l->tile_file_offsets [i] = SDL_ReadBE32 (src); ++ l->tile_file_offsets [i] = read_offset (src, h); + } while (l->tile_file_offsets [i++]); + + return l; +@@ -470,7 +490,8 @@ + unsigned char * load; + + load = (unsigned char *) malloc (len); // expect this is okay +- SDL_RWread (src, load, len, 1); ++ if (load != NULL) ++ SDL_RWread (src, load, len, 1); + + return load; + } +@@ -568,12 +589,12 @@ + Uint32 *row; + + SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET); +- hierarchy = read_xcf_hierarchy (src); ++ hierarchy = read_xcf_hierarchy (src, head); + + level = NULL; + for (i = 0; hierarchy->level_file_offsets [i]; i++) { + SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET); +- level = read_xcf_level (src); ++ level = read_xcf_level (src, head); + + ty = tx = 0; + for (j = 0; level->tile_file_offsets [j]; j++) { +@@ -582,6 +603,8 @@ + oy = ty+64 > level->height ? level->height % 64 : 64; + + if (level->tile_file_offsets [j+1]) { ++ if (level->tile_file_offsets [j+1] <= level->tile_file_offsets [j]) ++ break; + tile = load_tile + (src, + level->tile_file_offsets [j+1] - level->tile_file_offsets [j], +@@ -735,7 +758,7 @@ + head->layer_file_offsets = NULL; + offsets = 0; + +- while ((offset = SDL_ReadBE32 (src))) { ++ while ((offset = read_offset (src, head))) { + head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1)); + head->layer_file_offsets [offsets] = offset; + offsets++; +@@ -755,20 +778,22 @@ + SDL_Rect rs, rd; + SDL_RWseek (src, head->layer_file_offsets [i-1], RW_SEEK_SET); + +- layer = read_xcf_layer (src); +- do_layer_surface (lays, src, head, layer, load_tile); +- rs.x = 0; +- rs.y = 0; +- rs.w = layer->width; +- rs.h = layer->height; +- rd.x = layer->offset_x; +- rd.y = layer->offset_y; +- rd.w = layer->width; +- rd.h = layer->height; +- +- if (layer->visible) +- SDL_BlitSurface (lays, &rs, surface, &rd); +- free_xcf_layer (layer); ++ layer = read_xcf_layer (src, head); ++ if (layer != NULL) { ++ do_layer_surface (lays, src, head, layer, load_tile); ++ rs.x = 0; ++ rs.y = 0; ++ rs.w = layer->width; ++ rs.h = layer->height; ++ rd.x = layer->offset_x; ++ rd.y = layer->offset_y; ++ rd.w = layer->width; ++ rd.h = layer->height; ++ ++ if (layer->visible) ++ SDL_BlitSurface (lays, &rs, surface, &rd); ++ free_xcf_layer (layer); ++ } + } + + SDL_FreeSurface (lays); +@@ -778,11 +803,13 @@ + // read channels + channel = NULL; + chnls = 0; +- while ((offset = SDL_ReadBE32 (src))) { ++ while ((offset = read_offset (src, head))) { + channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1)); + fp = SDL_RWtell (src); + SDL_RWseek (src, offset, RW_SEEK_SET); +- channel [chnls++] = (read_xcf_channel (src)); ++ channel [chnls] = (read_xcf_channel (src, head)); ++ if (channel [chnls] != NULL) ++ chnls++; + SDL_RWseek (src, fp, RW_SEEK_SET); + } + diff --git a/3rdparty/SDL_image_XCF_v11_load_level.patch b/3rdparty/SDL_image_XCF_v11_load_level.patch new file mode 100644 index 00000000..71b47fbe --- /dev/null +++ b/3rdparty/SDL_image_XCF_v11_load_level.patch @@ -0,0 +1,53 @@ +--- SDL_image-1.2.12/IMG_xcf.c 2018-12-03 11:28:32.953683000 +0100 ++++ SDL_image-1.2.12-me/IMG_xcf.c 2018-12-03 11:32:24.053793000 +0100 +@@ -587,13 +587,17 @@ + Uint32 * p; + int x, y, tx, ty, ox, oy, i, j; + Uint32 *row; ++ Uint32 length; + + SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET); + hierarchy = read_xcf_hierarchy (src, head); + + level = NULL; + for (i = 0; hierarchy->level_file_offsets [i]; i++) { +- SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET); ++ if (SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET) < 0) ++ break; ++ if (i > 0) // skip level except the 1st one, just like GIMP does ++ continue; + level = read_xcf_level (src, head); + + ty = tx = 0; +@@ -601,23 +605,16 @@ + SDL_RWseek (src, level->tile_file_offsets [j], RW_SEEK_SET); + ox = tx+64 > level->width ? level->width % 64 : 64; + oy = ty+64 > level->height ? level->height % 64 : 64; ++ length = ox*oy*6; + +- if (level->tile_file_offsets [j+1]) { +- if (level->tile_file_offsets [j+1] <= level->tile_file_offsets [j]) +- break; +- tile = load_tile +- (src, +- level->tile_file_offsets [j+1] - level->tile_file_offsets [j], +- hierarchy->bpp, +- ox, oy); +- } +- else { +- tile = load_tile +- (src, +- ox*oy*6, +- hierarchy->bpp, +- ox, oy); ++ if (level->tile_file_offsets [j+1] > level->tile_file_offsets [j]) { ++ length = level->tile_file_offsets [j+1] - level->tile_file_offsets [j]; + } ++ tile = load_tile ++ (src, ++ length, ++ hierarchy->bpp, ++ ox, oy); + + p8 = tile; + p16 = (Uint16 *) p8;