@@ -126,11 +126,22 @@ struct rpng
126126 bool has_trns ;
127127};
128128
129+ static const struct adam7_pass passes [] = {
130+ { 0 , 0 , 8 , 8 },
131+ { 4 , 0 , 8 , 8 },
132+ { 0 , 4 , 4 , 8 },
133+ { 2 , 0 , 4 , 4 },
134+ { 0 , 2 , 2 , 4 },
135+ { 1 , 0 , 2 , 2 },
136+ { 0 , 1 , 1 , 2 },
137+ };
138+
129139static INLINE uint32_t dword_be (const uint8_t * buf )
130140{
131141 return (buf [0 ] << 24 ) | (buf [1 ] << 16 ) | (buf [2 ] << 8 ) | (buf [3 ] << 0 );
132142}
133143
144+ #if defined(DEBUG ) || defined(RPNG_TEST )
134145static bool png_process_ihdr (struct png_ihdr * ihdr )
135146{
136147 unsigned i ;
@@ -143,58 +154,71 @@ static bool png_process_ihdr(struct png_ihdr *ihdr)
143154 case PNG_IHDR_COLOR_RGBA :
144155 if (ihdr_depth != 8 && ihdr_depth != 16 )
145156 {
146- #ifdef DEBUG
147157 fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
148- #endif
149158 return false;
150159 }
151160 break ;
152161 case PNG_IHDR_COLOR_GRAY :
153162 /* Valid bitdepths are: 1, 2, 4, 8, 16 */
154163 if (ihdr_depth > 16 || (0x977F7FFF << ihdr_depth ) & 0x80000000 )
155164 {
156- #ifdef DEBUG
157165 fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
158- #endif
159166 return false;
160167 }
161168 break ;
162169 case PNG_IHDR_COLOR_PLT :
163170 /* Valid bitdepths are: 1, 2, 4, 8 */
164171 if (ihdr_depth > 8 || (0x977F7FFF << ihdr_depth ) & 0x80000000 )
165172 {
166- #ifdef DEBUG
167173 fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
168- #endif
169174 return false;
170175 }
171176 break ;
172177 default :
173- #ifdef DEBUG
174178 fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
175- #endif
176179 return false;
177180 }
178181
179- #ifdef RPNG_TEST
180182 fprintf (stderr , "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n" ,
181183 ihdr -> width , ihdr -> height ,
182184 ihdr_depth , (ihdr -> color_type == PNG_IHDR_COLOR_PLT ) ? "yes" : "no" ,
183185 (ihdr -> color_type & PNG_IHDR_COLOR_RGB ) ? "yes" : "no" ,
184186 (ihdr -> color_type & PNG_IHDR_COLOR_GRAY_ALPHA ) ? "yes" : "no" ,
185187 ihdr -> interlace == 1 ? "yes" : "no" );
186- #endif
187188
188- if (ihdr -> compression != 0 )
189+ return true;
190+ }
191+ #else
192+ static bool png_process_ihdr (struct png_ihdr * ihdr )
193+ {
194+ unsigned i ;
195+ uint8_t ihdr_depth = ihdr -> depth ;
196+
197+ switch (ihdr -> color_type )
189198 {
190- #ifdef DEBUG
191- fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
192- #endif
193- return false;
199+ case PNG_IHDR_COLOR_RGB :
200+ case PNG_IHDR_COLOR_GRAY_ALPHA :
201+ case PNG_IHDR_COLOR_RGBA :
202+ if (ihdr_depth != 8 && ihdr_depth != 16 )
203+ return false;
204+ break ;
205+ case PNG_IHDR_COLOR_GRAY :
206+ /* Valid bitdepths are: 1, 2, 4, 8, 16 */
207+ if (ihdr_depth > 16 || (0x977F7FFF << ihdr_depth ) & 0x80000000 )
208+ return false;
209+ break ;
210+ case PNG_IHDR_COLOR_PLT :
211+ /* Valid bitdepths are: 1, 2, 4, 8 */
212+ if (ihdr_depth > 8 || (0x977F7FFF << ihdr_depth ) & 0x80000000 )
213+ return false;
214+ break ;
215+ default :
216+ return false;
194217 }
195218
196219 return true;
197220}
221+ #endif
198222
199223static void png_reverse_filter_copy_line_rgb (uint32_t * data ,
200224 const uint8_t * decoded , unsigned width , unsigned bpp )
@@ -374,9 +398,7 @@ static void png_reverse_filter_copy_line_plt(uint32_t *data,
374398 }
375399
376400 if (width & 1 )
377- {
378401 * data = palette [* decoded >> 4 ];
379- }
380402 }
381403 break ;
382404
@@ -385,9 +407,7 @@ static void png_reverse_filter_copy_line_plt(uint32_t *data,
385407 unsigned i ;
386408
387409 for (i = 0 ; i < width ; i ++ , decoded ++ , data ++ )
388- {
389410 * data = palette [* decoded ];
390- }
391411 }
392412 break ;
393413 }
@@ -397,8 +417,8 @@ static void png_pass_geom(const struct png_ihdr *ihdr,
397417 unsigned width , unsigned height ,
398418 unsigned * bpp_out , unsigned * pitch_out , size_t * pass_size )
399419{
400- unsigned bpp ;
401- unsigned pitch ;
420+ unsigned bpp = 0 ;
421+ unsigned pitch = 0 ;
402422
403423 switch (ihdr -> color_type )
404424 {
@@ -423,15 +443,13 @@ static void png_pass_geom(const struct png_ihdr *ihdr,
423443 pitch = (ihdr -> width * ihdr -> depth * 4 + 7 ) / 8 ;
424444 break ;
425445 default :
426- bpp = 0 ;
427- pitch = 0 ;
428446 break ;
429447 }
430448
431449 if (pass_size )
432450 * pass_size = (pitch + 1 ) * ihdr -> height ;
433451 if (bpp_out )
434- * bpp_out = bpp ;
452+ * bpp_out = bpp ;
435453 if (pitch_out )
436454 * pitch_out = pitch ;
437455}
@@ -470,16 +488,6 @@ static void png_reverse_filter_deinit(struct rpng_process *pngp)
470488 pngp -> h = 0 ;
471489}
472490
473- static const struct adam7_pass passes [] = {
474- { 0 , 0 , 8 , 8 },
475- { 4 , 0 , 8 , 8 },
476- { 0 , 4 , 4 , 8 },
477- { 2 , 0 , 4 , 4 },
478- { 0 , 2 , 2 , 4 },
479- { 1 , 0 , 2 , 2 },
480- { 0 , 1 , 1 , 2 },
481- };
482-
483491static int png_reverse_filter_init (const struct png_ihdr * ihdr ,
484492 struct rpng_process * pngp )
485493{
@@ -919,16 +927,12 @@ static struct rpng_process *rpng_process_init(rpng_t *rpng)
919927 return NULL ;
920928}
921929
922- static enum png_chunk_type read_chunk_header (uint8_t * buf , uint8_t * buf_end ,
923- uint32_t chunk_size )
930+ static enum png_chunk_type read_chunk_header (
931+ uint8_t * buf , uint32_t chunk_size )
924932{
925933 unsigned i ;
926934 char type [4 ];
927935
928- /* Check whether chunk will overflow the data buffer */
929- if (buf + 8 + chunk_size > buf_end )
930- return PNG_CHUNK_ERROR ;
931-
932936 for (i = 0 ; i < 4 ; i ++ )
933937 {
934938 uint8_t byte = buf [i + 4 ];
@@ -983,24 +987,6 @@ static enum png_chunk_type read_chunk_header(uint8_t *buf, uint8_t *buf_end,
983987 return PNG_CHUNK_NOOP ;
984988}
985989
986- static bool png_parse_ihdr (uint8_t * buf ,
987- struct png_ihdr * ihdr )
988- {
989- buf += 4 + 4 ;
990-
991- ihdr -> width = dword_be (buf + 0 );
992- ihdr -> height = dword_be (buf + 4 );
993- ihdr -> depth = buf [8 ];
994- ihdr -> color_type = buf [9 ];
995- ihdr -> compression = buf [10 ];
996- ihdr -> filter = buf [11 ];
997- ihdr -> interlace = buf [12 ];
998-
999- if (ihdr -> width == 0 || ihdr -> height == 0 )
1000- return false;
1001- return true;
1002- }
1003-
1004990bool rpng_iterate_image (rpng_t * rpng )
1005991{
1006992 unsigned i ;
@@ -1018,7 +1004,11 @@ bool rpng_iterate_image(rpng_t *rpng)
10181004
10191005 chunk_size = dword_be (buf );
10201006
1021- switch (read_chunk_header (buf , rpng -> buff_end , chunk_size ))
1007+ /* Check whether chunk will overflow the data buffer */
1008+ if (buf + 8 + chunk_size > rpng -> buff_end )
1009+ return false;
1010+
1011+ switch (read_chunk_header (buf , chunk_size ))
10221012 {
10231013 case PNG_CHUNK_NOOP :
10241014 default :
@@ -1034,20 +1024,43 @@ bool rpng_iterate_image(rpng_t *rpng)
10341024 if (chunk_size != 13 )
10351025 return false;
10361026
1037- if (!png_parse_ihdr (buf , & rpng -> ihdr ))
1027+ buf += 4 + 4 ;
1028+
1029+ rpng -> ihdr .width = dword_be (buf + 0 );
1030+ rpng -> ihdr .height = dword_be (buf + 4 );
1031+ rpng -> ihdr .depth = buf [8 ];
1032+ rpng -> ihdr .color_type = buf [9 ];
1033+ rpng -> ihdr .compression = buf [10 ];
1034+ rpng -> ihdr .filter = buf [11 ];
1035+ rpng -> ihdr .interlace = buf [12 ];
1036+
1037+ if ( rpng -> ihdr .width == 0
1038+ || rpng -> ihdr .height == 0 )
10381039 return false;
10391040
10401041 if (!png_process_ihdr (& rpng -> ihdr ))
10411042 return false;
10421043
1044+ if (rpng -> ihdr .compression != 0 )
1045+ {
1046+ #if defined(DEBUG ) || defined(RPNG_TEST )
1047+ fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
1048+ #endif
1049+ return false;
1050+ }
1051+
10431052 rpng -> has_ihdr = true;
10441053 break ;
10451054
10461055 case PNG_CHUNK_PLTE :
10471056 {
10481057 unsigned entries = chunk_size / 3 ;
10491058
1050- if (!rpng -> has_ihdr || rpng -> has_plte || rpng -> has_iend || rpng -> has_idat || rpng -> has_trns )
1059+ if ( !rpng -> has_ihdr
1060+ || rpng -> has_plte
1061+ || rpng -> has_iend
1062+ || rpng -> has_idat
1063+ || rpng -> has_trns )
10511064 return false;
10521065
10531066 if (chunk_size % 3 )
0 commit comments