2020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2121 */
2222
23+ #ifdef DEBUG
2324#include <stdio.h>
25+ #endif
2426#include <stdint.h>
2527#include <stdlib.h>
2628#include <string.h>
@@ -80,12 +82,6 @@ struct idat_buffer
8082 size_t size ;
8183};
8284
83- struct png_chunk
84- {
85- uint32_t size ;
86- char type [4 ];
87- };
88-
8985struct rpng_process
9086{
9187 uint32_t * data ;
@@ -135,97 +131,69 @@ static INLINE uint32_t dword_be(const uint8_t *buf)
135131 return (buf [0 ] << 24 ) | (buf [1 ] << 16 ) | (buf [2 ] << 8 ) | (buf [3 ] << 0 );
136132}
137133
138- static enum png_chunk_type png_chunk_type (char chunk_type [4 ])
139- {
140- unsigned i ;
141- struct
142- {
143- const char * id ;
144- enum png_chunk_type type ;
145- } static const chunk_map [] = {
146- { "IHDR" , PNG_CHUNK_IHDR },
147- { "IDAT" , PNG_CHUNK_IDAT },
148- { "IEND" , PNG_CHUNK_IEND },
149- { "PLTE" , PNG_CHUNK_PLTE },
150- { "tRNS" , PNG_CHUNK_tRNS },
151- };
152-
153- for (i = 0 ; i < ARRAY_SIZE (chunk_map ); i ++ )
154- {
155- if (!memcmp (chunk_type , chunk_map [i ].id , 4 ))
156- return chunk_map [i ].type ;
157- }
158-
159- return PNG_CHUNK_NOOP ;
160- }
161-
162134static bool png_process_ihdr (struct png_ihdr * ihdr )
163135{
164136 unsigned i ;
165- bool ret = true ;
137+ uint8_t ihdr_depth = ihdr -> depth ;
166138
167139 switch (ihdr -> color_type )
168140 {
169141 case PNG_IHDR_COLOR_RGB :
170142 case PNG_IHDR_COLOR_GRAY_ALPHA :
171143 case PNG_IHDR_COLOR_RGBA :
172- if (ihdr -> depth != 8 && ihdr -> depth != 16 )
173- GOTO_END_ERROR ();
144+ if (ihdr_depth != 8 && ihdr_depth != 16 )
145+ {
146+ #ifdef DEBUG
147+ fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
148+ #endif
149+ return false;
150+ }
174151 break ;
175152 case PNG_IHDR_COLOR_GRAY :
153+ /* Valid bitdepths are: 1, 2, 4, 8, 16 */
154+ if (ihdr_depth > 16 || (0x977F7FFF << ihdr_depth ) & 0x80000000 )
176155 {
177- static const unsigned valid_bpp [] = { 1 , 2 , 4 , 8 , 16 };
178- bool correct_bpp = false;
179-
180- for (i = 0 ; i < ARRAY_SIZE (valid_bpp ); i ++ )
181- {
182- if (valid_bpp [i ] == ihdr -> depth )
183- {
184- correct_bpp = true;
185- break ;
186- }
187- }
188-
189- if (!correct_bpp )
190- GOTO_END_ERROR ();
156+ #ifdef DEBUG
157+ fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
158+ #endif
159+ return false;
191160 }
192161 break ;
193162 case PNG_IHDR_COLOR_PLT :
163+ /* Valid bitdepths are: 1, 2, 4, 8 */
164+ if (ihdr_depth > 8 || (0x977F7FFF << ihdr_depth ) & 0x80000000 )
194165 {
195- static const unsigned valid_bpp [] = { 1 , 2 , 4 , 8 };
196- bool correct_bpp = false;
197-
198- for (i = 0 ; i < ARRAY_SIZE (valid_bpp ); i ++ )
199- {
200- if (valid_bpp [i ] == ihdr -> depth )
201- {
202- correct_bpp = true;
203- break ;
204- }
205- }
206-
207- if (!correct_bpp )
208- GOTO_END_ERROR ();
166+ #ifdef DEBUG
167+ fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
168+ #endif
169+ return false;
209170 }
210171 break ;
211172 default :
212- GOTO_END_ERROR ();
173+ #ifdef DEBUG
174+ fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
175+ #endif
176+ return false;
213177 }
214178
215179#ifdef RPNG_TEST
216180 fprintf (stderr , "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n" ,
217181 ihdr -> width , ihdr -> height ,
218- ihdr -> depth , (ihdr -> color_type == PNG_IHDR_COLOR_PLT ) ? "yes" : "no" ,
219- (ihdr -> color_type & PNG_IHDR_COLOR_RGB ) ? "yes" : "no" ,
220- (ihdr -> color_type & PNG_IHDR_COLOR_GRAY_ALPHA ) ? "yes" : "no" ,
182+ ihdr_depth , (ihdr -> color_type == PNG_IHDR_COLOR_PLT ) ? "yes" : "no" ,
183+ (ihdr -> color_type & PNG_IHDR_COLOR_RGB ) ? "yes" : "no" ,
184+ (ihdr -> color_type & PNG_IHDR_COLOR_GRAY_ALPHA ) ? "yes" : "no" ,
221185 ihdr -> interlace == 1 ? "yes" : "no" );
222186#endif
223187
224188 if (ihdr -> compression != 0 )
225- GOTO_END_ERROR ();
189+ {
190+ #ifdef DEBUG
191+ fprintf (stderr , "[RPNG]: Error in line %d.\n" , __LINE__ );
192+ #endif
193+ return false;
194+ }
226195
227- end :
228- return ret ;
196+ return true;
229197}
230198
231199static void png_reverse_filter_copy_line_rgb (uint32_t * data ,
@@ -951,16 +919,15 @@ static struct rpng_process *rpng_process_init(rpng_t *rpng)
951919 return NULL ;
952920}
953921
954- static bool read_chunk_header (uint8_t * buf , uint8_t * buf_end ,
955- struct png_chunk * chunk )
922+ static enum png_chunk_type read_chunk_header (uint8_t * buf , uint8_t * buf_end ,
923+ uint32_t chunk_size )
956924{
957925 unsigned i ;
958-
959- chunk -> size = dword_be (buf );
926+ char type [4 ];
960927
961928 /* Check whether chunk will overflow the data buffer */
962- if (buf + 8 + chunk -> size > buf_end )
963- return false ;
929+ if (buf + 8 + chunk_size > buf_end )
930+ return PNG_CHUNK_ERROR ;
964931
965932 for (i = 0 ; i < 4 ; i ++ )
966933 {
@@ -969,12 +936,51 @@ static bool read_chunk_header(uint8_t *buf, uint8_t *buf_end,
969936 /* All four bytes of the chunk type must be
970937 * ASCII letters (codes 65-90 and 97-122) */
971938 if ((byte < 65 ) || ((byte > 90 ) && (byte < 97 )) || (byte > 122 ))
972- return false;
973-
974- chunk -> type [i ] = byte ;
939+ return PNG_CHUNK_ERROR ;
940+ type [i ] = byte ;
975941 }
976942
977- return true;
943+ if (
944+ type [0 ] == 'I'
945+ && type [1 ] == 'H'
946+ && type [2 ] == 'D'
947+ && type [3 ] == 'R'
948+ )
949+ return PNG_CHUNK_IHDR ;
950+ else if
951+ (
952+ type [0 ] == 'I'
953+ && type [1 ] == 'D'
954+ && type [2 ] == 'A'
955+ && type [3 ] == 'T'
956+ )
957+ return PNG_CHUNK_IDAT ;
958+ else if
959+ (
960+ type [0 ] == 'I'
961+ && type [1 ] == 'E'
962+ && type [2 ] == 'N'
963+ && type [3 ] == 'D'
964+ )
965+ return PNG_CHUNK_IEND ;
966+ else if
967+ (
968+ type [0 ] == 'P'
969+ && type [1 ] == 'L'
970+ && type [2 ] == 'T'
971+ && type [3 ] == 'E'
972+ )
973+ return PNG_CHUNK_PLTE ;
974+ else if
975+ (
976+ type [0 ] == 't'
977+ && type [1 ] == 'R'
978+ && type [2 ] == 'N'
979+ && type [3 ] == 'S'
980+ )
981+ return PNG_CHUNK_tRNS ;
982+
983+ return PNG_CHUNK_NOOP ;
978984}
979985
980986static bool png_parse_ihdr (uint8_t * buf ,
@@ -998,11 +1004,8 @@ static bool png_parse_ihdr(uint8_t *buf,
9981004bool rpng_iterate_image (rpng_t * rpng )
9991005{
10001006 unsigned i ;
1001- struct png_chunk chunk ;
1002- uint8_t * buf = (uint8_t * )rpng -> buff_data ;
1003-
1004- chunk .size = 0 ;
1005- chunk .type [0 ] = 0 ;
1007+ uint8_t * buf = (uint8_t * )rpng -> buff_data ;
1008+ uint32_t chunk_size = 0 ;
10061009
10071010 /* Check whether data buffer pointer is valid */
10081011 if (buf > rpng -> buff_end )
@@ -1012,10 +1015,10 @@ bool rpng_iterate_image(rpng_t *rpng)
10121015 * the data buffer */
10131016 if (rpng -> buff_end - buf < 8 )
10141017 return false;
1015- if (!read_chunk_header (buf , rpng -> buff_end , & chunk ))
1016- return false;
10171018
1018- switch (png_chunk_type (chunk .type ))
1019+ chunk_size = dword_be (buf );
1020+
1021+ switch (read_chunk_header (buf , rpng -> buff_end , chunk_size ))
10191022 {
10201023 case PNG_CHUNK_NOOP :
10211024 default :
@@ -1028,7 +1031,7 @@ bool rpng_iterate_image(rpng_t *rpng)
10281031 if (rpng -> has_ihdr || rpng -> has_idat || rpng -> has_iend )
10291032 return false;
10301033
1031- if (chunk . size != 13 )
1034+ if (chunk_size != 13 )
10321035 return false;
10331036
10341037 if (!png_parse_ihdr (buf , & rpng -> ihdr ))
@@ -1042,12 +1045,12 @@ bool rpng_iterate_image(rpng_t *rpng)
10421045
10431046 case PNG_CHUNK_PLTE :
10441047 {
1045- unsigned entries = chunk . size / 3 ;
1048+ unsigned entries = chunk_size / 3 ;
10461049
10471050 if (!rpng -> has_ihdr || rpng -> has_plte || rpng -> has_iend || rpng -> has_idat || rpng -> has_trns )
10481051 return false;
10491052
1050- if (chunk . size % 3 )
1053+ if (chunk_size % 3 )
10511054 return false;
10521055
10531056 if (entries > 256 )
@@ -1069,12 +1072,12 @@ bool rpng_iterate_image(rpng_t *rpng)
10691072 if (rpng -> ihdr .color_type == PNG_IHDR_COLOR_PLT )
10701073 {
10711074 /* we should compare with the number of palette entries */
1072- if (chunk . size > 256 )
1075+ if (chunk_size > 256 )
10731076 return false;
10741077
10751078 buf += 8 ;
10761079
1077- if (!png_read_trns (buf , rpng -> palette , chunk . size ))
1080+ if (!png_read_trns (buf , rpng -> palette , chunk_size ))
10781081 return false;
10791082 }
10801083 /* TODO: support colorkey in grayscale and truecolor images */
@@ -1086,15 +1089,15 @@ bool rpng_iterate_image(rpng_t *rpng)
10861089 if (!(rpng -> has_ihdr ) || rpng -> has_iend || (rpng -> ihdr .color_type == PNG_IHDR_COLOR_PLT && !(rpng -> has_plte )))
10871090 return false;
10881091
1089- if (!png_realloc_idat (& rpng -> idat_buf , chunk . size ))
1092+ if (!png_realloc_idat (& rpng -> idat_buf , chunk_size ))
10901093 return false;
10911094
10921095 buf += 8 ;
10931096
1094- for (i = 0 ; i < chunk . size ; i ++ )
1097+ for (i = 0 ; i < chunk_size ; i ++ )
10951098 rpng -> idat_buf .data [i + rpng -> idat_buf .size ] = buf [i ];
10961099
1097- rpng -> idat_buf .size += chunk . size ;
1100+ rpng -> idat_buf .size += chunk_size ;
10981101
10991102 rpng -> has_idat = true;
11001103 break ;
@@ -1107,7 +1110,7 @@ bool rpng_iterate_image(rpng_t *rpng)
11071110 return false;
11081111 }
11091112
1110- rpng -> buff_data += chunk . size + 12 ;
1113+ rpng -> buff_data += chunk_size + 12 ;
11111114
11121115 /* Check whether data buffer pointer is valid */
11131116 if (rpng -> buff_data > rpng -> buff_end )
@@ -1184,7 +1187,6 @@ void rpng_free(rpng_t *rpng)
11841187bool rpng_start (rpng_t * rpng )
11851188{
11861189 unsigned i ;
1187- char header [8 ];
11881190
11891191 if (!rpng )
11901192 return false;
@@ -1194,12 +1196,8 @@ bool rpng_start(rpng_t *rpng)
11941196 if (rpng -> buff_end - rpng -> buff_data < 8 )
11951197 return false;
11961198
1197- header [0 ] = '\0' ;
1198-
1199- for (i = 0 ; i < 8 ; i ++ )
1200- header [i ] = rpng -> buff_data [i ];
1201-
1202- if (string_is_not_equal_fast (header , png_magic , sizeof (png_magic )))
1199+ if (string_is_not_equal_fast (
1200+ rpng -> buff_data , png_magic , sizeof (png_magic )))
12031201 return false;
12041202
12051203 rpng -> buff_data += 8 ;
0 commit comments