@@ -161,6 +161,29 @@ static void phar_zip_u2d_time(time_t time, char *dtime, char *ddate) /* {{{ */
161
161
}
162
162
/* }}} */
163
163
164
+ static char * phar_find_eocd (const char * s , size_t n )
165
+ {
166
+ const char * end = s + n + sizeof ("PK\5\6" ) - 1 - sizeof (phar_zip_dir_end );
167
+
168
+ /* search backwards for end of central directory signatures */
169
+ do {
170
+ uint16_t comment_len ;
171
+ const char * eocd_start = zend_memnrstr (s , "PK\5\6" , sizeof ("PK\5\6" ) - 1 , end );
172
+
173
+ if (eocd_start == NULL ) {
174
+ return NULL ;
175
+ }
176
+ ZEND_ASSERT (eocd_start + sizeof (phar_zip_dir_end ) <= s + n );
177
+ comment_len = PHAR_GET_16 (((phar_zip_dir_end * ) eocd_start )-> comment_len );
178
+ if (eocd_start + sizeof (phar_zip_dir_end ) + comment_len == s + n ) {
179
+ /* we can't be sure, but this looks like the proper EOCD signature */
180
+ return (char * ) eocd_start ;
181
+ }
182
+ end = eocd_start ;
183
+ } while (end > s );
184
+ return NULL ;
185
+ }
186
+
164
187
/**
165
188
* Does not check for a previously opened phar in the cache.
166
189
*
@@ -205,50 +228,48 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia
205
228
return FAILURE ;
206
229
}
207
230
208
- while ((p = (char * ) memchr (p + 1 , 'P' , (size_t ) (size - (p + 1 - buf )))) != NULL ) {
209
- if ((p - buf ) + sizeof (locator ) <= (size_t )size && !memcmp (p + 1 , "K\5\6" , 3 )) {
210
- memcpy ((void * )& locator , (void * ) p , sizeof (locator ));
211
- if (PHAR_GET_16 (locator .centraldisk ) != 0 || PHAR_GET_16 (locator .disknumber ) != 0 ) {
212
- /* split archives not handled */
213
- php_stream_close (fp );
214
- if (error ) {
215
- spprintf (error , 4096 , "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"" , fname );
216
- }
217
- return FAILURE ;
231
+ if ((p = phar_find_eocd (buf , size )) != NULL ) {
232
+ memcpy ((void * )& locator , (void * ) p , sizeof (locator ));
233
+ if (PHAR_GET_16 (locator .centraldisk ) != 0 || PHAR_GET_16 (locator .disknumber ) != 0 ) {
234
+ /* split archives not handled */
235
+ php_stream_close (fp );
236
+ if (error ) {
237
+ spprintf (error , 4096 , "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"" , fname );
218
238
}
239
+ return FAILURE ;
240
+ }
219
241
220
- if (PHAR_GET_16 (locator .counthere ) != PHAR_GET_16 (locator .count )) {
221
- if (error ) {
222
- spprintf (error , 4096 , "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"" , fname );
223
- }
224
- php_stream_close (fp );
225
- return FAILURE ;
242
+ if (PHAR_GET_16 (locator .counthere ) != PHAR_GET_16 (locator .count )) {
243
+ if (error ) {
244
+ spprintf (error , 4096 , "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"" , fname );
226
245
}
246
+ php_stream_close (fp );
247
+ return FAILURE ;
248
+ }
227
249
228
- mydata = pecalloc (1 , sizeof (phar_archive_data ), PHAR_G (persist ));
229
- mydata -> is_persistent = PHAR_G (persist );
250
+ mydata = pecalloc (1 , sizeof (phar_archive_data ), PHAR_G (persist ));
251
+ mydata -> is_persistent = PHAR_G (persist );
230
252
231
- /* read in archive comment, if any */
232
- if (PHAR_GET_16 (locator .comment_len )) {
253
+ /* read in archive comment, if any */
254
+ if (PHAR_GET_16 (locator .comment_len )) {
233
255
234
- metadata = p + sizeof (locator );
256
+ metadata = p + sizeof (locator );
235
257
236
- if (PHAR_GET_16 (locator .comment_len ) != size - (metadata - buf )) {
237
- if (error ) {
238
- spprintf (error , 4096 , "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"" , fname );
239
- }
240
- php_stream_close (fp );
241
- pefree (mydata , mydata -> is_persistent );
242
- return FAILURE ;
258
+ if (PHAR_GET_16 (locator .comment_len ) != size - (metadata - buf )) {
259
+ if (error ) {
260
+ spprintf (error , 4096 , "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"" , fname );
243
261
}
244
-
245
- phar_parse_metadata_lazy (metadata , & mydata -> metadata_tracker , PHAR_GET_16 (locator .comment_len ), mydata -> is_persistent );
246
- } else {
247
- ZVAL_UNDEF (& mydata -> metadata_tracker .val );
262
+ php_stream_close (fp );
263
+ pefree (mydata , mydata -> is_persistent );
264
+ return FAILURE ;
248
265
}
249
266
250
- goto foundit ;
267
+ phar_parse_metadata_lazy (metadata , & mydata -> metadata_tracker , PHAR_GET_16 (locator .comment_len ), mydata -> is_persistent );
268
+ } else {
269
+ ZVAL_UNDEF (& mydata -> metadata_tracker .val );
251
270
}
271
+
272
+ goto foundit ;
252
273
}
253
274
254
275
php_stream_close (fp );
0 commit comments