Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Feb 2002 20:40:02 -0800 (PST)
From:      "Vadim Mikhailov" <mvp@braz.ru>
To:        freebsd-ports@FreeBSD.org
Subject:   Re: ports/33170: zip -T [zip file] fails with message about missing end signature
Message-ID:  <200202200440.g1K4e2S04126@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR ports/33170; it has been noted by GNATS.

From: "Vadim Mikhailov" <mvp@braz.ru>
To: <freebsd-gnats-submit@FreeBSD.org>, <idart@hotmail.com>
Cc:  
Subject: Re: ports/33170: zip -T [zip file] fails with message about missing end signature
Date: Tue, 19 Feb 2002 20:34:38 -0800

   I have run into the same problem on FreeBSD/alpha system.
 Apparently, I have figured out what's going on. It has nothing to do
 with 64-bit alignment or endianness. It's all about long-standing bug
 in FreeBSD - http://www.freebsd.org/cgi/query-pr.cgi?pr=kern%2F6184
 
 Let's take a look at infozip source, file zipfile.c around line 669:
 ...
     if (fseek(f, -4096L, SEEK_END) == 0) {
       zipbeg = (ulg) (ftell(f) + 4096L);
       while (!found && zipbeg >= 4096) {
         zipbeg -= 4096L;
         buf[4096] = t[1];
         buf[4097] = t[2];
         buf[4098] = t[3];
 /*
  * XXX error check ??
  */
         fread(buf, 1, 4096, f);
         fseek(f, -8192L, SEEK_CUR);
         t = &buf[4095];
 ...
 
   "f" in this context file handle of archive to be processed.
 If size of that archive is less than 4096 that means first
 fseek(f, -4096, SEEK_END) would try to seek to negative
 file offset. I found out that in this case fseek does not
 return an error and ftell(f) yields negative result!
 Of course, this does not make any sense.
   If archive size is between 4096 and 8192 bytes it would mean
 that second fseek(f, -8192, SEEK_CUR) also could try to do
 negative seek.
   Later this code tries to fseek(f, 0, SEEK_SET) but it does not
 help much - errno would be 27 (file too big) and everything blows up.
 I think that fseek should return an error (-1) to negative offset.
 I have checked what happens on other platforms. On FreeBSD/i386
 negative fseek succeeds, but later fseek(f, 0, SEEK_SET) does not
 give any errors - i.e. this negative fseek works without being caught.
 On linux negative fseek returns an error.
   Proper fix for this situation would be apply fix mentioned
 in kern/6184 to kernel. But I also wrote patch for infozip
 to avoid even trying negative seeks, so it works without
 kernel patching:
 
 ===========================================
 --- zipfile.c.orig Sun Nov  7 02:30:11 1999
 +++ zipfile.c Tue Feb 19 19:41:10 2002
 @@ -628,6 +628,16 @@
 
  #endif /* !UTIL */
 
 +local long fsize(FILE *f) {
 +    long size, curpos;
 +    if(!f) return 0;
 +    curpos = ftell(f);
 +    fseek(f, 0, SEEK_END);
 +    size = ftell(f);
 +    fseek(f, curpos, SEEK_SET);
 +    return size;
 +}
 +
  /*
   * scanzipf_reg starts searching for the End Signature at the end of the
 file
   * The End Signature points to the Central Directory Signature which points
 @@ -667,7 +677,7 @@
      t[1] = '\0';
      t[2] = '\0';
      t[3] = '\0';
 -    if (fseek(f, -4096L, SEEK_END) == 0) {
 +    if (fsize(f)>=4096L && fseek(f, -4096L, SEEK_END) == 0) {
        zipbeg = (ulg) (ftell(f) + 4096L);
        while (!found && zipbeg >= 4096) {
          zipbeg -= 4096L;
 @@ -678,7 +688,7 @@
   * XXX error check ??
   */
          fread(buf, 1, 4096, f);
 -        fseek(f, -8192L, SEEK_CUR);
 +        if(ftell(f)>=8192L) fseek(f, -8192L, SEEK_CUR);
          t = &buf[4095];
  /*
   * XXX far pointer arithmetic in DOS
 ===========================================
 
   It would be great if someone could commit this patch to ports tree
 as /usr/ports/archivers/zip/files/patch-negativeseek or something.
 I have checked that with this patch zip works fine for both i386 and alpha.
   In the meantime if someone could commit fix proposed in kern/6184
 it won't hurt as well.
 
 Vadim Mikhailov
 
 
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200202200440.g1K4e2S04126>