Date: Sat, 03 May 2003 13:21:57 +0100 From: "Richard Dawe" Sender: rich AT phekda DOT freeserve DOT co DOT uk To: djgpp-workers AT delorie DOT com X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6 Subject: djtar and slightly weirdly formatted ZIPs, revision 2 [PATCH] Message-Id: Reply-To: djgpp-workers AT delorie DOT com Hello. Below is revision 2 of my patch for djtar, to make it cope with v2gnu/flx254b.zip on Simtel.NET. This archive has a spanning marker that indicates the archive has been split into one, i.e.: not at all. Changes from the previous patch: * Parse strictly. It fails if the archive doesn't start with the one-span spanning marker or a local header. * Generate an error, if multiple-span spanning is found. * Generate an error, when we don't understand the header type. This seems better than reporting that the ZIP file is invalid. OK to commit? Thanks, bye, Rich =] Index: src/utils/djtar/epunzip.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/utils/djtar/epunzip.c,v retrieving revision 1.4 diff -p -c -3 -r1.4 epunzip.c *** src/utils/djtar/epunzip.c 17 Oct 2002 23:00:26 -0000 1.4 --- src/utils/djtar/epunzip.c 3 May 2003 12:14:11 -0000 *************** int epcopy(char *, long); *** 37,42 **** --- 37,45 ---- void epunzip_read(char *zipfilename) { + int dont_understand = 0; + int at_local_header = 0; + clear_bufs(); errno = 0; ifd = oread_open(zipfilename); *************** epunzip_read(char *zipfilename) *** 46,74 **** return; } while(1) { ! int buffer, ext_header, timedate, crc, size, length, name_length, ! extra_length, should_be_written, count, real_file = 0; ! char filename[2048]; ((char *)&buffer)[0] = (char)get_byte(); ((char *)&buffer)[1] = (char)get_byte(); if(*(short *)&buffer != *(short *)"PK") ! { ! fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); ! break; ! } ((char *)&buffer)[0] = (char)get_byte(); ((char *)&buffer)[1] = (char)get_byte(); ! if(*(short *)&buffer != *(short *)"\3\4") { ! /* not a local header - all done */ break; } /* version info - ignore it */ get_byte(); --- 49,132 ---- return; } + /* Find the first local header. Skip over spanning markers + * for a one-segment ZIP, but fail on other headers. */ while(1) { ! int buffer = 0; ((char *)&buffer)[0] = (char)get_byte(); ((char *)&buffer)[1] = (char)get_byte(); if(*(short *)&buffer != *(short *)"PK") ! break; ((char *)&buffer)[0] = (char)get_byte(); ((char *)&buffer)[1] = (char)get_byte(); ! if(*(short *)&buffer == *(short *)"\x3\x4") ! { ! /* local header */ ! at_local_header = 1; ! break; ! } ! else if(*(short *)&buffer == *(short *)"\x30\x30") { ! /* spanning marker, but only one segment ! * => need to find local header. */ ! continue; ! } ! else if(*(short *)&buffer == *(short *)"\x7\x8") ! { ! /* spanning marker, multiple segments. */ ! fprintf(log_out, "%s: spanning is not supported\n", zipfilename); ! dont_understand = 1; ! break; ! } ! else ! { ! /* unknown header */ ! fprintf(log_out, ! "%s: don't understand header type 0x%x%x\n", ! zipfilename, ((char *)&buffer)[0], ((char *)&buffer)[1]); ! dont_understand = 1; break; } + } + + if (!at_local_header && !dont_understand) + fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); + + if (at_local_header) while(1) + { + int buffer, ext_header, timedate, crc, size, length, name_length, + extra_length, should_be_written, count, real_file = 0; + char filename[2048]; + + if (!at_local_header) + { + ((char *)&buffer)[0] = (char)get_byte(); + ((char *)&buffer)[1] = (char)get_byte(); + + if(*(short *)&buffer != *(short *)"PK") + { + fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); + break; + } + + ((char *)&buffer)[0] = (char)get_byte(); + ((char *)&buffer)[1] = (char)get_byte(); + + if(*(short *)&buffer != *(short *)"\x3\x4") + { + /* not a local header - all done */ + break; + } + } + else + { + at_local_header = 0; + } /* version info - ignore it */ get_byte(); *************** epunzip_read(char *zipfilename) *** 222,228 **** ((char *)&buffer)[1] = (char)get_byte(); ((char *)&buffer)[2] = (char)get_byte(); ((char *)&buffer)[3] = (char)get_byte(); ! if(buffer != *(int *)"PK\7\x8") { fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); --- 280,286 ---- ((char *)&buffer)[1] = (char)get_byte(); ((char *)&buffer)[2] = (char)get_byte(); ((char *)&buffer)[3] = (char)get_byte(); ! if(buffer != *(int *)"PK\x7\x8") { fprintf(log_out, "%s: invalid zip file structure\n", zipfilename);