IMG_tif.c
author Ozkan Sezer <sezeroz@gmail.com>
Tue, 16 Oct 2018 20:02:02 +0300
branchSDL-1.2
changeset 607 1a1189c2978f
parent 280 ec4ae96c100c
permissions -rw-r--r--
backports of multiple bug fixes from 2.0:

3999783e (r340): bug 1413 - Fix image corruption when using ImageIO framework
5bf0f0d6 (r343), 326a6025 (r361): fixes from VS code analysis and code review
2742fe58 (r355), 1e7a55d7 (r356). dd40be56 (r358): support for webp on big endian systems
ce8091ca (r365): bug 1801 - typo in the xcf decoder, condition is always false
35beff02 (r369): bug 1831 - Memory leak issue in SDL_image-1.2.12/IMG_xpm.c file
1700d607 (r415): bug 1991 - XCF and LBM image loading [only the memory leak parts.]
e108e122 (r419): bug 2010 - Memory leaks in do_layer_surface function in IMG_xcf.c
7a360f7d (r436): bug 2295 - Memory leak in IMG_LoadWEBP_RW
ee17b8eb (r443): bug 2454 - Crash when loading some XPM files
bca82f1c (r476): proper fix for Bugzilla #2965.
fd721465 (r490): crash if some initialization succeeded and some didn't
915de300 (r492): bug 3474 - IMG_tif leaks memory on errors
b6f8fbe5 (r493): bug 3475 - Remove unnecessary loop from IMG_tif.c
d3e819a0 (r499): bug 2318 - h->cm_map resource getting leak in read_xcf_header function
1e32e1f4 (r503): bug 3008 - Compiler warnings: "warning: initialization discards 'const'
318484db (r513): security vulnerability in XCF image loader
181ef57f (r530): failing to reset the file pointer when detecting file types with ImageIO
16772bbb (r555): lbm: use correct variable to check color planes.
97f7f01e (r556): lbm: Fail to load images with unsupported/bogus color depth.
bfa08dc0 (r557): lbm: Don't overflow static colormap buffer.
a1e9b624 (r558): ico: reject obviously incorrect image sizes.
37445f61 (r559): bmp: don't overflow palette buffer with bogus biClrUsed values.
7df1580f (r560): xcf: deal with bogus data in rle tile decoding.
45e750f9 (r563): gif: report error on bogus LWZ data, instead of overflowing a buffer.
2938fc80 (r567): pcx: don't overflow buffer if bytes-per-line is less than image width.
c5f9cbb5 (r568): xcf: Prevent infinite loop and/or buffer overflow on bogus data.
fb643e37 (r569): xcf: check for some potential integer overflows.
170d7d32 (r585): potential buffer overflow on corrupt or maliciously-crafted XCF file.
19beb4a1 (r586): Don't get into infinite loops on truncated GIF files.
32a18ca0 (r587): Don't get into infinite loops on truncated PNM files.
8b4ee1d7 (r590): memory leak in IMG_xcf.c
90a531f2 (r591): PNM: Improve checks when loading a file
31263a04 (r592): XCF: check if there's sufficient data in the stream before allocating
cec9b759 (r593): More error checking, and null terminate strings...
slouken@0
     1
/*
slouken@280
     2
  SDL_image:  An example image loading library for use with SDL
slouken@280
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@280
     5
  This software is provided 'as-is', without any express or implied
slouken@280
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@280
     7
  arising from the use of this software.
slouken@0
     8
slouken@280
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@280
    10
  including commercial applications, and to alter it and redistribute it
slouken@280
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@280
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@280
    14
     claim that you wrote the original software. If you use this software
slouken@280
    15
     in a product, an acknowledgment in the product documentation would be
slouken@280
    16
     appreciated but is not required.
slouken@280
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@280
    18
     misrepresented as being the original software.
slouken@280
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@53
    20
*/
slouken@0
    21
slouken@237
    22
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
slouken@237
    23
slouken@0
    24
/* This is a TIFF image file loading framework */
slouken@0
    25
slouken@0
    26
#include <stdio.h>
slouken@0
    27
slouken@0
    28
#include "SDL_image.h"
slouken@0
    29
slouken@0
    30
#ifdef LOAD_TIF
slouken@0
    31
slouken@0
    32
#include <tiffio.h>
slouken@0
    33
slouken@143
    34
static struct {
slouken@143
    35
	int loaded;
slouken@143
    36
	void *handle;
slouken@143
    37
	TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
slouken@143
    38
	void (*TIFFClose)(TIFF*);
slouken@143
    39
	int (*TIFFGetField)(TIFF*, ttag_t, ...);
sezeroz@607
    40
	int (*TIFFReadRGBAImageOriented)(TIFF*, uint32, uint32, uint32*, int, int);
slouken@143
    41
	TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
slouken@143
    42
} lib;
slouken@143
    43
slouken@143
    44
#ifdef LOAD_TIF_DYNAMIC
slouken@205
    45
int IMG_InitTIF()
slouken@143
    46
{
slouken@143
    47
	if ( lib.loaded == 0 ) {
slouken@143
    48
		lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
slouken@143
    49
		if ( lib.handle == NULL ) {
slouken@143
    50
			return -1;
slouken@143
    51
		}
slouken@143
    52
		lib.TIFFClientOpen =
slouken@143
    53
			(TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
slouken@143
    54
			SDL_LoadFunction(lib.handle, "TIFFClientOpen");
slouken@143
    55
		if ( lib.TIFFClientOpen == NULL ) {
slouken@143
    56
			SDL_UnloadObject(lib.handle);
slouken@143
    57
			return -1;
slouken@143
    58
		}
slouken@143
    59
		lib.TIFFClose =
slouken@143
    60
			(void (*)(TIFF*))
slouken@143
    61
			SDL_LoadFunction(lib.handle, "TIFFClose");
slouken@143
    62
		if ( lib.TIFFClose == NULL ) {
slouken@143
    63
			SDL_UnloadObject(lib.handle);
slouken@143
    64
			return -1;
slouken@143
    65
		}
slouken@143
    66
		lib.TIFFGetField =
slouken@143
    67
			(int (*)(TIFF*, ttag_t, ...))
slouken@143
    68
			SDL_LoadFunction(lib.handle, "TIFFGetField");
slouken@143
    69
		if ( lib.TIFFGetField == NULL ) {
slouken@143
    70
			SDL_UnloadObject(lib.handle);
slouken@143
    71
			return -1;
slouken@143
    72
		}
sezeroz@607
    73
		lib.TIFFReadRGBAImageOriented =
sezeroz@607
    74
			(int (*)(TIFF*, uint32, uint32, uint32*, int, int))
sezeroz@607
    75
			SDL_LoadFunction(lib.handle, "TIFFReadRGBAImageOriented");
sezeroz@607
    76
		if ( lib.TIFFReadRGBAImageOriented == NULL ) {
slouken@143
    77
			SDL_UnloadObject(lib.handle);
slouken@143
    78
			return -1;
slouken@143
    79
		}
slouken@143
    80
		lib.TIFFSetErrorHandler =
slouken@143
    81
			(TIFFErrorHandler (*)(TIFFErrorHandler))
slouken@143
    82
			SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
slouken@143
    83
		if ( lib.TIFFSetErrorHandler == NULL ) {
slouken@143
    84
			SDL_UnloadObject(lib.handle);
slouken@143
    85
			return -1;
slouken@143
    86
		}
slouken@143
    87
	}
slouken@143
    88
	++lib.loaded;
slouken@143
    89
slouken@143
    90
	return 0;
slouken@143
    91
}
slouken@205
    92
void IMG_QuitTIF()
slouken@143
    93
{
slouken@143
    94
	if ( lib.loaded == 0 ) {
slouken@143
    95
		return;
slouken@143
    96
	}
slouken@143
    97
	if ( lib.loaded == 1 ) {
slouken@143
    98
		SDL_UnloadObject(lib.handle);
slouken@143
    99
	}
slouken@143
   100
	--lib.loaded;
slouken@143
   101
}
slouken@143
   102
#else
slouken@205
   103
int IMG_InitTIF()
slouken@143
   104
{
slouken@143
   105
	if ( lib.loaded == 0 ) {
slouken@143
   106
		lib.TIFFClientOpen = TIFFClientOpen;
slouken@143
   107
		lib.TIFFClose = TIFFClose;
slouken@143
   108
		lib.TIFFGetField = TIFFGetField;
sezeroz@607
   109
		lib.TIFFReadRGBAImageOriented = TIFFReadRGBAImageOriented;
slouken@143
   110
		lib.TIFFSetErrorHandler = TIFFSetErrorHandler;
slouken@143
   111
	}
slouken@143
   112
	++lib.loaded;
slouken@146
   113
slouken@146
   114
	return 0;
slouken@143
   115
}
slouken@205
   116
void IMG_QuitTIF()
slouken@143
   117
{
slouken@143
   118
	if ( lib.loaded == 0 ) {
slouken@143
   119
		return;
slouken@143
   120
	}
slouken@143
   121
	if ( lib.loaded == 1 ) {
slouken@143
   122
	}
slouken@143
   123
	--lib.loaded;
slouken@143
   124
}
slouken@143
   125
#endif /* LOAD_TIF_DYNAMIC */
slouken@143
   126
slouken@0
   127
/*
slouken@0
   128
 * These are the thunking routine to use the SDL_RWops* routines from
slouken@0
   129
 * libtiff's internals.
slouken@0
   130
*/
slouken@0
   131
slouken@0
   132
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
   133
{
slouken@0
   134
	return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
slouken@0
   135
}
slouken@0
   136
slouken@0
   137
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
slouken@0
   138
{
slouken@0
   139
	return SDL_RWseek((SDL_RWops*)fd, offset, origin);
slouken@0
   140
}
slouken@0
   141
slouken@0
   142
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
   143
{
slouken@0
   144
	return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
slouken@0
   145
}
slouken@0
   146
slouken@0
   147
static int tiff_close(thandle_t fd)
slouken@0
   148
{
slouken@0
   149
	/*
slouken@0
   150
	 * We don't want libtiff closing our SDL_RWops*, but if it's not given
slouken@0
   151
         * a routine to try, and if the image isn't a TIFF, it'll segfault.
slouken@0
   152
	 */
slouken@0
   153
	return 0;
slouken@0
   154
}
slouken@0
   155
slouken@167
   156
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
slouken@167
   157
{
slouken@167
   158
	return (0);
slouken@167
   159
}
slouken@167
   160
slouken@167
   161
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
slouken@167
   162
{
slouken@167
   163
	return;
slouken@167
   164
}
slouken@167
   165
slouken@0
   166
static toff_t tiff_size(thandle_t fd)
slouken@0
   167
{
sezeroz@607
   168
	Sint32 save_pos;
slouken@0
   169
	toff_t size;
slouken@0
   170
slouken@0
   171
	save_pos = SDL_RWtell((SDL_RWops*)fd);
slouken@236
   172
	SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
slouken@0
   173
        size = SDL_RWtell((SDL_RWops*)fd);
slouken@236
   174
	SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
slouken@0
   175
	return size;
slouken@0
   176
}
slouken@0
   177
slouken@0
   178
int IMG_isTIF(SDL_RWops* src)
slouken@0
   179
{
slouken@117
   180
	int start;
slouken@117
   181
	int is_TIF;
slouken@167
   182
	Uint8 magic[4];
slouken@0
   183
icculus@154
   184
	if ( !src )
icculus@154
   185
		return 0;
slouken@117
   186
	start = SDL_RWtell(src);
slouken@117
   187
	is_TIF = 0;
slouken@167
   188
	if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
slouken@167
   189
		if ( (magic[0] == 'I' &&
slouken@167
   190
                      magic[1] == 'I' &&
slouken@167
   191
		      magic[2] == 0x2a &&
slouken@167
   192
                      magic[3] == 0x00) ||
slouken@167
   193
		     (magic[0] == 'M' &&
slouken@167
   194
                      magic[1] == 'M' &&
slouken@167
   195
		      magic[2] == 0x00 &&
slouken@167
   196
                      magic[3] == 0x2a) ) {
slouken@167
   197
			is_TIF = 1;
slouken@167
   198
		}
slouken@117
   199
	}
slouken@236
   200
	SDL_RWseek(src, start, RW_SEEK_SET);
slouken@117
   201
	return(is_TIF);
slouken@0
   202
}
slouken@0
   203
slouken@0
   204
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
slouken@0
   205
{
slouken@118
   206
	int start;
sezeroz@607
   207
	TIFF* tiff = NULL;
slouken@0
   208
	SDL_Surface* surface = NULL;
slouken@0
   209
	Uint32 img_width, img_height;
slouken@145
   210
	Uint32 Rmask, Gmask, Bmask, Amask;
slouken@0
   211
	Uint32 x, y;
slouken@0
   212
	Uint32 half;
slouken@0
   213
slouken@98
   214
	if ( !src ) {
slouken@98
   215
		/* The error message has been set in SDL_RWFromFile */
slouken@98
   216
		return NULL;
slouken@98
   217
	}
slouken@118
   218
	start = SDL_RWtell(src);
slouken@0
   219
sezeroz@607
   220
	if ( (IMG_Init(IMG_INIT_TIF) & IMG_INIT_TIF) == 0 ) {
slouken@143
   221
		return NULL;
slouken@143
   222
	}
slouken@143
   223
slouken@0
   224
	/* turn off memory mapped access with the m flag */
slouken@143
   225
	tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src, 
slouken@167
   226
		tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
slouken@0
   227
	if(!tiff)
slouken@118
   228
		goto error;
slouken@0
   229
slouken@0
   230
	/* Retrieve the dimensions of the image from the TIFF tags */
slouken@143
   231
	lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
slouken@143
   232
	lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
slouken@0
   233
slouken@4
   234
	Rmask = 0x000000FF;
slouken@4
   235
	Gmask = 0x0000FF00;
slouken@4
   236
	Bmask = 0x00FF0000;
slouken@4
   237
	Amask = 0xFF000000;
slouken@0
   238
	surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32,
slouken@0
   239
		Rmask, Gmask, Bmask, Amask);
slouken@0
   240
	if(!surface)
slouken@118
   241
		goto error;
slouken@0
   242
	
sezeroz@607
   243
	if(!lib.TIFFReadRGBAImageOriented(tiff, img_width, img_height, (uint32 *)surface->pixels, ORIENTATION_TOPLEFT, 0))
slouken@118
   244
		goto error;
slouken@0
   245
slouken@143
   246
	lib.TIFFClose(tiff);
slouken@0
   247
	
slouken@0
   248
	return surface;
slouken@118
   249
slouken@118
   250
error:
slouken@236
   251
	SDL_RWseek(src, start, RW_SEEK_SET);
sezeroz@607
   252
	if (surface) {
slouken@118
   253
		SDL_FreeSurface(surface);
slouken@118
   254
	}
sezeroz@607
   255
	if (tiff) {
sezeroz@607
   256
		lib.TIFFClose(tiff);
sezeroz@607
   257
	}
slouken@118
   258
	return NULL;
slouken@0
   259
}
slouken@0
   260
slouken@0
   261
#else
slouken@0
   262
slouken@205
   263
int IMG_InitTIF()
slouken@205
   264
{
slouken@205
   265
	IMG_SetError("TIFF images are not supported");
slouken@205
   266
	return(-1);
slouken@205
   267
}
slouken@205
   268
slouken@205
   269
void IMG_QuitTIF()
slouken@205
   270
{
slouken@205
   271
}
slouken@205
   272
slouken@0
   273
/* See if an image is contained in a data source */
slouken@0
   274
int IMG_isTIF(SDL_RWops *src)
slouken@0
   275
{
slouken@0
   276
	return(0);
slouken@0
   277
}
slouken@0
   278
slouken@0
   279
/* Load a TIFF type image from an SDL datasource */
slouken@0
   280
SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
slouken@0
   281
{
slouken@0
   282
	return(NULL);
slouken@0
   283
}
slouken@0
   284
slouken@0
   285
#endif /* LOAD_TIF */
slouken@237
   286
slouken@237
   287
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */