1313 * By Tim Gunn.
1414 *
1515 * RLE support added by Michal Mertl and Salvador Eduardo Tropea.
16- *
16+ *
1717 * Palette reading improved by Peter Wang.
1818 *
1919 * Big-endian support added by Eric Botcazou.
@@ -34,6 +34,7 @@ ALLEGRO_DEBUG_CHANNEL("image")
3434
3535/* raw_tga_read8:
3636 * Helper for reading 256-color raw data from TGA files.
37+ * Returns pointer past the end.
3738 */
3839static INLINE unsigned char * raw_tga_read8 (unsigned char * b , int w , ALLEGRO_FILE * f )
3940{
@@ -44,8 +45,9 @@ static INLINE unsigned char *raw_tga_read8(unsigned char *b, int w, ALLEGRO_FILE
4445
4546/* rle_tga_read8:
4647 * Helper for reading 256-color RLE data from TGA files.
48+ * Returns pointer past the end or NULL for error.
4749 */
48- static void rle_tga_read8 (unsigned char * b , int w , ALLEGRO_FILE * f )
50+ static unsigned char * rle_tga_read8 (unsigned char * b , int w , ALLEGRO_FILE * f )
4951{
5052 int value , count , c = 0 ;
5153
@@ -55,6 +57,10 @@ static void rle_tga_read8(unsigned char *b, int w, ALLEGRO_FILE *f)
5557 /* run-length packet */
5658 count = (count & 0x7F ) + 1 ;
5759 c += count ;
60+ if (c > w ) {
61+ /* Stepped past the end of the line, error */
62+ return NULL ;
63+ }
5864 value = al_fgetc (f );
5965 while (count -- )
6066 * b ++ = value ;
@@ -63,9 +69,14 @@ static void rle_tga_read8(unsigned char *b, int w, ALLEGRO_FILE *f)
6369 /* raw packet */
6470 count ++ ;
6571 c += count ;
72+ if (c > w ) {
73+ /* Stepped past the end of the line, error */
74+ return NULL ;
75+ }
6676 b = raw_tga_read8 (b , count , f );
6777 }
6878 } while (c < w );
79+ return b ;
6980}
7081
7182
@@ -82,6 +93,7 @@ static INLINE int32_t single_tga_read32(ALLEGRO_FILE *f)
8293
8394/* raw_tga_read32:
8495 * Helper for reading 32-bit raw data from TGA files.
96+ * Returns pointer past the end.
8597 */
8698static unsigned int * raw_tga_read32 (unsigned int * b , int w , ALLEGRO_FILE * f )
8799{
@@ -95,8 +107,9 @@ static unsigned int *raw_tga_read32(unsigned int *b, int w, ALLEGRO_FILE *f)
95107
96108/* rle_tga_read32:
97109 * Helper for reading 32-bit RLE data from TGA files.
110+ * Returns pointer past the end or NULL for error.
98111 */
99- static void rle_tga_read32 (unsigned int * b , int w , ALLEGRO_FILE * f )
112+ static unsigned int * rle_tga_read32 (unsigned int * b , int w , ALLEGRO_FILE * f )
100113{
101114 int color , count , c = 0 ;
102115
@@ -106,6 +119,10 @@ static void rle_tga_read32(unsigned int *b, int w, ALLEGRO_FILE *f)
106119 /* run-length packet */
107120 count = (count & 0x7F ) + 1 ;
108121 c += count ;
122+ if (c > w ) {
123+ /* Stepped past the end of the line, error */
124+ return NULL ;
125+ }
109126 color = single_tga_read32 (f );
110127 while (count -- )
111128 * b ++ = color ;
@@ -114,9 +131,14 @@ static void rle_tga_read32(unsigned int *b, int w, ALLEGRO_FILE *f)
114131 /* raw packet */
115132 count ++ ;
116133 c += count ;
134+ if (c > w ) {
135+ /* Stepped past the end of the line, error */
136+ return NULL ;
137+ }
117138 b = raw_tga_read32 (b , count , f );
118139 }
119140 } while (c < w );
141+ return b ;
120142}
121143
122144
@@ -132,6 +154,7 @@ static INLINE void single_tga_read24(ALLEGRO_FILE *f, unsigned char color[3])
132154
133155/* raw_tga_read24:
134156 * Helper for reading 24-bit raw data from TGA files.
157+ * Returns pointer past the end.
135158 */
136159static unsigned char * raw_tga_read24 (unsigned char * b , int w , ALLEGRO_FILE * f )
137160{
@@ -147,8 +170,9 @@ static unsigned char *raw_tga_read24(unsigned char *b, int w, ALLEGRO_FILE *f)
147170
148171/* rle_tga_read24:
149172 * Helper for reading 24-bit RLE data from TGA files.
173+ * Returns pointer past the end or NULL for error.
150174 */
151- static void rle_tga_read24 (unsigned char * b , int w , ALLEGRO_FILE * f )
175+ static unsigned char * rle_tga_read24 (unsigned char * b , int w , ALLEGRO_FILE * f )
152176{
153177 int count , c = 0 ;
154178 unsigned char color [3 ];
@@ -159,6 +183,10 @@ static void rle_tga_read24(unsigned char *b, int w, ALLEGRO_FILE *f)
159183 /* run-length packet */
160184 count = (count & 0x7F ) + 1 ;
161185 c += count ;
186+ if (c > w ) {
187+ /* Stepped past the end of the line, error */
188+ return NULL ;
189+ }
162190 single_tga_read24 (f , color );
163191 while (count -- ) {
164192 b [0 ] = color [0 ];
@@ -171,9 +199,14 @@ static void rle_tga_read24(unsigned char *b, int w, ALLEGRO_FILE *f)
171199 /* raw packet */
172200 count ++ ;
173201 c += count ;
202+ if (c > w ) {
203+ /* Stepped past the end of the line, error */
204+ return NULL ;
205+ }
174206 b = raw_tga_read24 (b , count , f );
175207 }
176208 } while (c < w );
209+ return b ;
177210}
178211
179212
@@ -190,6 +223,7 @@ static INLINE int single_tga_read16(ALLEGRO_FILE *f)
190223
191224/* raw_tga_read16:
192225 * Helper for reading 16-bit raw data from TGA files.
226+ * Returns pointer past the end.
193227 */
194228static unsigned short * raw_tga_read16 (unsigned short * b , int w , ALLEGRO_FILE * f )
195229{
@@ -203,8 +237,9 @@ static unsigned short *raw_tga_read16(unsigned short *b, int w, ALLEGRO_FILE *f)
203237
204238/* rle_tga_read16:
205239 * Helper for reading 16-bit RLE data from TGA files.
240+ * Returns pointer past the end or NULL for error.
206241 */
207- static void rle_tga_read16 (unsigned short * b , int w , ALLEGRO_FILE * f )
242+ static unsigned short * rle_tga_read16 (unsigned short * b , int w , ALLEGRO_FILE * f )
208243{
209244 int color , count , c = 0 ;
210245
@@ -214,6 +249,10 @@ static void rle_tga_read16(unsigned short *b, int w, ALLEGRO_FILE *f)
214249 /* run-length packet */
215250 count = (count & 0x7F ) + 1 ;
216251 c += count ;
252+ if (c > w ) {
253+ /* Stepped past the end of the line, error */
254+ return NULL ;
255+ }
217256 color = single_tga_read16 (f );
218257 while (count -- )
219258 * b ++ = color ;
@@ -222,9 +261,14 @@ static void rle_tga_read16(unsigned short *b, int w, ALLEGRO_FILE *f)
222261 /* raw packet */
223262 count ++ ;
224263 c += count ;
264+ if (c > w ) {
265+ /* Stepped past the end of the line, error */
266+ return NULL ;
267+ }
225268 b = raw_tga_read16 (b , count , f );
226269 }
227270 } while (c < w );
271+ return b ;
228272}
229273
230274
@@ -388,12 +432,20 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f, int flags)
388432 switch (image_type ) {
389433
390434 case 1 :
391- case 3 :
435+ case 3 : {
436+ unsigned char * ptr ;
392437 if (compressed )
393- rle_tga_read8 (buf , image_width , f );
438+ ptr = rle_tga_read8 (buf , image_width , f );
394439 else
395- raw_tga_read8 (buf , image_width , f );
396-
440+ ptr = raw_tga_read8 (buf , image_width , f );
441+ if (!ptr ) {
442+ al_free (buf );
443+ al_unlock_bitmap (bmp );
444+ al_destroy_bitmap (bmp );
445+ ALLEGRO_ERROR ("Invalid image data.\n" );
446+ return NULL ;
447+ }
448+ }
397449 for (i = 0 ; i < image_width ; i ++ ) {
398450 int true_x = (left_to_right ) ? i : (image_width - 1 - i );
399451 int pix = buf [i ];
@@ -410,11 +462,18 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f, int flags)
410462
411463 case 2 :
412464 if (bpp == 32 ) {
465+ unsigned int * ptr ;
413466 if (compressed )
414- rle_tga_read32 ((unsigned int * )buf , image_width , f );
467+ ptr = rle_tga_read32 ((unsigned int * )buf , image_width , f );
415468 else
416- raw_tga_read32 ((unsigned int * )buf , image_width , f );
417-
469+ ptr = raw_tga_read32 ((unsigned int * )buf , image_width , f );
470+ if (!ptr ) {
471+ al_free (buf );
472+ al_unlock_bitmap (bmp );
473+ al_destroy_bitmap (bmp );
474+ ALLEGRO_ERROR ("Invalid image data.\n" );
475+ return NULL ;
476+ }
418477 for (i = 0 ; i < image_width ; i ++ ) {
419478 int true_x = (left_to_right ) ? i : (image_width - 1 - i );
420479 unsigned char * dest = (unsigned char * )lr -> data +
@@ -425,12 +484,12 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f, int flags)
425484 int r = buf [i * 4 + 1 ];
426485 int g = buf [i * 4 + 2 ];
427486 int b = buf [i * 4 + 3 ];
428- #else
487+ #else
429488 int b = buf [i * 4 + 0 ];
430489 int g = buf [i * 4 + 1 ];
431490 int r = buf [i * 4 + 2 ];
432491 int a = buf [i * 4 + 3 ];
433- #endif
492+ #endif
434493 if (premul ) {
435494 r = r * a / 255 ;
436495 g = g * a / 255 ;
@@ -444,10 +503,18 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f, int flags)
444503 }
445504 }
446505 else if (bpp == 24 ) {
506+ unsigned char * ptr ;
447507 if (compressed )
448- rle_tga_read24 (buf , image_width , f );
508+ ptr = rle_tga_read24 (buf , image_width , f );
449509 else
450- raw_tga_read24 (buf , image_width , f );
510+ ptr = raw_tga_read24 (buf , image_width , f );
511+ if (!ptr ) {
512+ al_free (buf );
513+ al_unlock_bitmap (bmp );
514+ al_destroy_bitmap (bmp );
515+ ALLEGRO_ERROR ("Invalid image data.\n" );
516+ return NULL ;
517+ }
451518 for (i = 0 ; i < image_width ; i ++ ) {
452519 int true_x = (left_to_right ) ? i : (image_width - 1 - i );
453520 int b = buf [i * 3 + 0 ];
@@ -463,14 +530,23 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f, int flags)
463530 }
464531 }
465532 else {
533+ unsigned short * ptr ;
466534 if (compressed )
467- rle_tga_read16 ((unsigned short * )buf , image_width , f );
535+ ptr = rle_tga_read16 ((unsigned short * )buf , image_width , f );
468536 else
469- raw_tga_read16 ((unsigned short * )buf , image_width , f );
537+ ptr = raw_tga_read16 ((unsigned short * )buf , image_width , f );
538+ if (!ptr ) {
539+ al_free (buf );
540+ al_unlock_bitmap (bmp );
541+ al_destroy_bitmap (bmp );
542+ ALLEGRO_ERROR ("Invalid image data.\n" );
543+ return NULL ;
544+ }
470545 for (i = 0 ; i < image_width ; i ++ ) {
471546 int true_x = (left_to_right ) ? i : (image_width - 1 - i );
472547 int pix = * ((unsigned short * )(buf + i * 2 ));
473- int r = _al_rgb_scale_5 [(pix >> 10 )];
548+ /* TODO - do something with the 1-bit A value (alpha?) */
549+ int r = _al_rgb_scale_5 [(pix >> 10 ) & 0x1F ];
474550 int g = _al_rgb_scale_5 [(pix >> 5 ) & 0x1F ];
475551 int b = _al_rgb_scale_5 [(pix & 0x1F )];
476552
@@ -597,7 +673,7 @@ bool _al_identify_tga(ALLEGRO_FILE *f)
597673 uint8_t x [4 ];
598674 al_fgetc (f ); // skip id length
599675 al_fread (f , x , 4 );
600-
676+
601677 if (x [0 ] > 1 ) // TGA colormap must be 0 or 1
602678 return false;
603679 if ((x [1 ] & 0xf7 ) == 0 ) // type must be 1, 2, 3, 9, 10 or 11
0 commit comments