From 4f8e26f2a40ffaa3a5b77be6a49989a1a42e2b83 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 16 Aug 2016 14:27:23 +0200 Subject: [PATCH] Fix #290: TGA RLE decoding is broken We make it work only, for now. Actually, it doesn't make sense that `oTga::bitmap` is an `int *` as we're storing only bytes there. If this will be changed, we can even get rid of the `conversion_buffer` in `read_image_tga` altogether, and read the image data into the `decompression_buffer` (if RLE'd) or the `tga->bitmap` (if uncompressed) directly. Upstream-Status: Backport Signed-off-by: Catalin Enache --- src/gd_tga.c | 18 ++++++++++-------- tests/tga/CMakeLists.txt | 1 + tests/tga/Makemodule.am | 8 ++++++-- tests/tga/tga_read.c | 40 ++++++++++++++++++++++++++++++++++++++++ tests/tga/tga_read_rgb.png | Bin 0 -> 2349 bytes tests/tga/tga_read_rgb.tga | Bin 0 -> 90444 bytes tests/tga/tga_read_rgb_rle.tga | Bin 0 -> 9987 bytes 7 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 tests/tga/tga_read.c create mode 100644 tests/tga/tga_read_rgb.png create mode 100644 tests/tga/tga_read_rgb.tga create mode 100644 tests/tga/tga_read_rgb_rle.tga diff --git a/src/gd_tga.c b/src/gd_tga.c index ec6781f..8737b04 100644 --- a/src/gd_tga.c +++ b/src/gd_tga.c @@ -207,12 +207,13 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga ) { int pixel_block_size = (tga->bits / 8); int image_block_size = (tga->width * tga->height) * pixel_block_size; - uint8_t* decompression_buffer = NULL; + int* decompression_buffer = NULL; unsigned char* conversion_buffer = NULL; int buffer_caret = 0; int bitmap_caret = 0; int i = 0; int encoded_pixels; + int rle_size; if(overflow2(tga->width, tga->height)) { return -1; @@ -266,7 +267,7 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga ) /*! \brief Read in RLE compressed RGB TGA * Chunk load the pixel data from an RLE compressed RGB type TGA. */ - decompression_buffer = (uint8_t*) gdMalloc(image_block_size * sizeof(uint8_t)); + decompression_buffer = (int*) gdMalloc(image_block_size * sizeof(int)); if (decompression_buffer == NULL) { return -1; } @@ -277,7 +278,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga ) return -1; } - if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) { + rle_size = gdGetBuf(conversion_buffer, image_block_size, ctx); + if (rle_size <= 0) { gdFree(conversion_buffer); gdFree(decompression_buffer); return -1; @@ -285,7 +287,7 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga ) buffer_caret = 0; - while( buffer_caret < image_block_size) { + while( buffer_caret < rle_size) { decompression_buffer[buffer_caret] = (int)conversion_buffer[buffer_caret]; buffer_caret++; } @@ -298,14 +300,14 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga ) encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 ); buffer_caret++; - if ((bitmap_caret + (encoded_pixels * pixel_block_size)) >= image_block_size) { + if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) { gdFree( decompression_buffer ); gdFree( conversion_buffer ); return -1; } for (i = 0; i < encoded_pixels; i++) { - memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, pixel_block_size); + memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, pixel_block_size * sizeof(int)); bitmap_caret += pixel_block_size; } buffer_caret += pixel_block_size; @@ -314,13 +316,13 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga ) encoded_pixels = decompression_buffer[ buffer_caret ] + 1; buffer_caret++; - if ((bitmap_caret + (encoded_pixels * pixel_block_size)) >= image_block_size) { + if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) { gdFree( decompression_buffer ); gdFree( conversion_buffer ); return -1; } - memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size); + memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size * sizeof(int)); bitmap_caret += (encoded_pixels * pixel_block_size); buffer_caret += (encoded_pixels * pixel_block_size); } diff --git a/tests/tga/CMakeLists.txt b/tests/tga/CMakeLists.txt index c3a589c..789fb14 100644 --- a/tests/tga/CMakeLists.txt +++ b/tests/tga/CMakeLists.txt @@ -5,6 +5,7 @@ LIST(APPEND TESTS_FILES bug00247a bug00248 bug00248a + tga_read ) ADD_GD_TESTS() diff --git a/tests/tga/Makemodule.am b/tests/tga/Makemodule.am index dff828f..a1e6af6 100644 --- a/tests/tga/Makemodule.am +++ b/tests/tga/Makemodule.am @@ -4,7 +4,8 @@ libgd_test_programs += \ tga/bug00247a \ tga/bug00248 \ tga/bug00248a \ - tga/tga_null + tga/tga_null \ + tga/tga_read EXTRA_DIST += \ tga/CMakeLists.txt \ @@ -12,4 +13,7 @@ EXTRA_DIST += \ tga/bug00247.tga \ tga/bug00247a.tga \ tga/bug00248.tga \ - tga/bug00248a.tga + tga/bug00248a.tga \ + tga/tga_read_rgb.png \ + tga/tga_read_rgb.tga \ + tga/tga_read_rgb_rle.tga diff --git a/tests/tga/tga_read.c b/tests/tga/tga_read.c new file mode 100644 index 0000000..310b72f --- /dev/null +++ b/tests/tga/tga_read.c @@ -0,0 +1,40 @@ +/** + * Basic test case for reading TGA files. + */ + + +#include "gd.h" +#include "gdtest.h" + + +static void assert_equals(char *exp, char *orig); + + +int main() +{ + assert_equals("tga_read_rgb.png", "tga_read_rgb.tga"); + assert_equals("tga_read_rgb.png", "tga_read_rgb_rle.tga"); + + return gdNumFailures(); +} + + +static void assert_equals(char *exp, char *orig) +{ + gdImagePtr im; + FILE *fp; + char *filename; + + fp = gdTestFileOpen2("tga", orig); + gdTestAssertMsg(fp != NULL, "can't open %s", orig); + + im = gdImageCreateFromTga(fp); + gdTestAssertMsg(im != NULL, "can't read %s", orig); + fclose(fp); + + filename = gdTestFilePath2("tga", exp); + gdAssertImageEqualsToFile(filename, im); + gdFree(filename); + + gdImageDestroy(im); +} diff --git a/tests/tga/tga_read_rgb.png b/tests/tga/tga_read_rgb.png new file mode 100644 index 0000000000000000000000000000000000000000..bc468e3d927eaeb77d2f5c3bc35b970457f60f18 GIT binary patch literal 2349 zcmZ`*c{tSX7XOaO7-6K6b&RD_MnXy$nHe#bsVG~TvfZ*vO?Jle8%ar+AySDfStFGh zG#*)pL0RUPJ(FedBaE?x-*o@D_deZwpZ7WMdCuo~-t)faoX_)~lW+lNCI*p(001C{ zHOJWSbt_+Pfp_!wWzS`|-X@&uIeytaE1*v>QB*5J9HUNl9{Spw6`Sc(k6uyJC zHWeNNLm|3~tCo{U002|57?VrEU+1$sy;a&|;-kbZl`6E_C%>gqbDtC=57F3fUD$)k zSG5DTL6#NnU=7wGcCw|M{W*OdYEgjJp6u9Rb7l#X%t` zun;^h28uEP=P3Px?|rNGF#17D%A(CJ_ar|?n^0nq!~w+Wg23867ryn!Zlb|~&7A~z zqkP=IPyLrOM?58>2rEq=&{*9OMU!HNWJkg`(`y(=2{WLg392OTDyiM2$iCLcv5LCG zjWwRq46Da$pV|V^4Gvs36k1dWF^V4c8j%3~jN{*0*$phpF|-#zi@;k@t-s?cqW&sd zPh{x~@zm`!5V23*L&Qb=_elN~nEEqQhrhNZiRU#|qjK>6ptaYgj*sAcuS+t-7X5aB zUI5f*aL0Dut+y0vde?tg7QMa^0`(plvuD^Q>)J(abQY>@6P_*YY;XJ54VC^_f7F2x z21ee^35}!Ek##rQDAOW+@)2?%}XiiSi^ted1PQu{v0&?bA^r%z?7*An3_H zvYFv8{p8fsCguNR$#3=6O{^H&8kT9N92CeaRAj3Y_cNl-znY8JZ{MpO#OK}A<_w9J zWMI2Kl?xv|S-FTV(aUG_`UWTZOFJGgv2)>JR#*H2Uad(wyqbIZt?w|Dw|k zt6D>=sy59jEGoeEx_W13BnmhAs?*j6#bG1a@#16O~1>q+P2@%QN~``Ws7=WX;F9 z`=p5I$1ig*G|iW8vslr2^8hj+A0HWDoT-@fn5I53ZWWp!r8fMghmpjdqC%E#%2HFI zY&A(g!Li3+$(r|V*&yCb;Ha(&ACi9w;?kQ7q1$hwjli^);+KIJAh|K&YL#E z+b(`PZN>V_5?v`hu-U429K9fO%8*k8pE=jDkn5ZJK|Vgl*@&QE^;mwlCxWbq4(hyi zUuz)bk@5^HOk@gB`SaWZfX07Eom07js%np8Xot&?YP8R+3|jrR4c#zO{LONY_mL~1^BUG})*4b;Z_zq+`Q@kzUHC&`trCiQYum;1? zBic+0Bl>LLYU?>!B3k!Ils}uXR*`OEr3`f?aKr2p19c6 zYJ}r+^s>6aD~mrp;oIUhlig4sM)Jg3=J{K;dp#BCzRu1sU3D1wJl{jA^Y#ShVT+|^ zUyjiM&wD~v3zy}K!zWm%3cpu#(*)cmxw1+n+C7V|hcZ6h8CZLubXt&J)h$6yflV6> zOVv_gDb*glO9FLL8x6bqM6(F#pGhGy+jjOyt9-daMWGrJKF{XvnT#^TeYaq2MG)qw zJ=RV;Mwg*goOa?(wM=EH<#AS$egRj*wnm+Bu4Pb{$-O}GZSiuT1UdBDwv2Rz)b3+L zRA=nkaWHB7I$T~B%;KynnS0b@3YpKqt$2;qzwLf>DZ4RFCQB!=QQ`Ft&y_PThuDsA zckawmbFnA9Tl7+Ez%a)>>T+Nh@8UxzrZP`|O) zgw?Xli!)-)xrF2z=thH-TI;|>UVYK64@asT%484CF-pjk+~~wA+Z%fZYua+sDJSw}~|(tM}hK+z>+^8QQhOsTxl+2AJ+ zX8WjlS|;0WRv7s_Bk=@u$v3GL@qC?&jcNEv9Cook& literal 0 HcmV?d00001 diff --git a/tests/tga/tga_read_rgb.tga b/tests/tga/tga_read_rgb.tga new file mode 100644 index 0000000000000000000000000000000000000000..5f11f5a080f3424dff6ff368db6af140a5777e23 GIT binary patch literal 90444 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 literal 0 HcmV?d00001 diff --git a/tests/tga/tga_read_rgb_rle.tga b/tests/tga/tga_read_rgb_rle.tga new file mode 100644 index 0000000000000000000000000000000000000000..ce845ad0c3da65205af25854d64568b1cf0921e3 GIT binary patch literal 9987 zcmeI2J!~9R5Xbkx ziiRRbk%9(oq!dtCIspYA&6UugGcC>X|IOQdZ+$+;#>5ek&eFVnJ3DVa{%>aX?a5Je zF>-%5qwk}eQT$4wzvw%Lr!o5$L%T1%_;U0&GrMhYD|*=1u+QBMI7bBz5GWAXUI?5o z4)=h152)YuP~W$``}B?1quuDQ!tKvI-d*GdmoNVj?N0AU(FV5-mWdwpH55x49>GD6 z=%BBmXlU4mV>@qJ8fX!=CL?@={ z0-|RLqE&j)8olUxtrw;AqBVNamHEBs60Ks5R&l9p6>VC@T4)u!Z+{gD%n-xb5tYDzPz)HDn9RtO}K-2&bfLTDa$ReF=%5-@43+;@(Xqh_Lqg5;e zg}THltzs{E>BBIs4hP5RP*Wqxy6Qz9`Y(v8pI6+HwtX$ra zy1k}`<+7Ep?x=h3^=RRT3_QRAG z_yH!{gxCD>ho1(boNM2tG;8-@MK-H=sqwzy_Dkd} zeC*AO?;PyiJI7egrh5aA*tASEv0P|sHWdv;37nkl7;GWQvslElsh1w>E)mVkrK5Wr zvyT~j8_(=*6BF=71Iw<4W?fOstUs?=BFaQ*Da#xiBX|}K8QkJdG}zFPqlKLAcr83* zWgQ+HzQdV{TOj;%(7%jzp+KJSs$|sS9Fk zi>8|_;%+MHn6)L%h}LxJYN%Lsjm=l2JEG}rgt!}vT81WTD?iXN22oo(>Q%FW$7$$! zt&?$T0IopDHZ|A}nmLfzok8W3vju;nlA35T-r~-!Mh%-@xp^A6E=V4LfMg^hw4o2J zZI)js`N&kV*g%#wDTZ~mcOy6~E}sky$N;c`=y|Ej2+1ZQ2f9i4w?h@e2{8NMT~!94nB@itGuLH} zXVpo_fLn+Ny=`_6ub%qVxz9IOHOQr&m-w|E<2CfOb2=CaIW-6=RoY?8DbvigNhHcJ zG#i_20Ls>TP|sG<1T!>Hm<6C_+a^z4YoiJ>5de05QI0M6IheVSK%5>}CEC#MwBHBI ziIa1Wpa&iZ_r@?tJkJ5|{-W{nZBP!8&Q$t}P*I~(hRwZ6%$Lp+>-V88rG8_ARaUB|->lMt--ZnEI zTJ7{U4;S{j2Ay9PTlySLkZpPkSyjD9xB@11Gqz?H&}bm6INZyXa|}y*$KYeSt=BT^ z9)n8f69who6DC3I4i6#*smWsw#8aACPLFDXvaYploY`rTzv^v6%`=fZ=~tM~+#d%*t zf%)V_G>Dlk3}01X6V9YA0}KH#x+MuyPXYm7$4BlC*YhI}#g|)Uh0-v*i7ggcv&@^C zjYO%ac80KpJfmhZkwXX$pH_*;t&cQIT_(xF6ht!Iic3UdT(%7ihfT|wtXWA&V1Sf; zU3WEU`G(*m{rfc5Lu-SUf;0gW_gTQ5!wKEEk(Qj)=S2;}8FVa^9uYEg=U`?TJS&;e zZ|IGrGhpnT4H$R>%fn7eg+%K9in1ezX3K%Y`r6i