www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/10/24/13:14:52

From: "A.Appleyard" <A DOT APPLEYARD AT fs2 DOT mt DOT umist DOT ac DOT uk>
To: DJGPP AT SUN DOT SOE DOT CLARKSON DOT EDU
Date: Tue, 24 Oct 1995 15:21:30 BST
Subject: An apparent fault in GZIP

In DJGPP\SRC\GZIP-124\ I have the source (but not the compiled form) of an
unzipper. It seems to claim to be able to be able to unzip any zipped file
that has only one file in. The file DJGPP\SRC\GZIP-124\UNLZW.C "decompress
files in LZW format" is the file to unzip files that have been shrunk. Here
follows a program that I just wrote that successfully unzips a PKZIP file that
contains one file, which must have been packed by shrinking. But its algorithm
varies in various places from DJGPP\SRC\GZIP-124\UNLZW.C, which may be able to
handle ordinary LZW'ing, but therefore won't be able to PKZIP's version:-

#include <stdio.h>
#include <string.h>
#define pk __attribute__((packed))
typedef unsigned long ul;
typedef unsigned short us;
typedef unsigned char byte;
/*-----*/
class fileheader{public: ul signature pk; byte version pk; byte opsystem pk;
  us gp pk; us compmethod pk; us time pk; us date pk; ul crc32 pk;
  ul compsize pk; ul uncompsize pk; us fnleng pk; us extraleng pk;};
class centralfileheader : public fileheader {public: us fcommleng pk;
  us filediskno pk; us intattr pk; ul extattr pk; ul localoffset pk;};
/*-----*/
class bits{public: int addr,mask;
inline bits(void*i){addr=(int)i;};
inline void operator=(void*i){addr=(int)i;};
inline int operator[](int i){return (*(long*)(addr+(i>>3))>>(i&7))&mask;};};
/*-----*/
main(){int i,j,k,l,fs,fhs=sizeof(fileheader),ptr; fileheader*fh;
char file[0x100000],*p,sw[256],inname[256],outname[256];
printf("pkzip file to unshrink from?"); gets(inname);
printf("text file to unshrink into?"); gets(outname);
FILE*Z=fopen(inname,"rb"); fs=fread(file,1,0x100000,Z);
FILE*Y=fopen(outname,"wb");
fh=(fileheader*)file;
ptr=sizeof(fileheader)+fh->fnleng+fh->extraleng;
{ /* unshrink */ bits F(file+ptr); F.mask=0x1ff;
    int N=9,c,q,inbit=0,n=0,i=0,j,k,l,m,p=-1,pc=0;
    us a[0x10000],b[0x10000]; char w[256],pn[0x10000];
    for(i=0;i<0x10000;i++) a[i]=b[i]=pn[i]=0; q=256;
    for(c=-1,i=0;(inbit>>3)<fh->compsize;i++) {
        p=c; X: k=inbit; c=F[inbit]; inbit+=N;
        if(c==256) {c=F[inbit]; inbit+=N;
            if(c==1) {N++; F.mask=(F.mask<<1)|1;}
/* Here UNLZW.C rounds `inbit' up to the next code boundary which is also */
/* a byte boundary, but this program (and therefore PKZIP) do not. */
            else if(c==2) {pc++;
                for(m=256;m<0x10000;m++) b[a[m]]|=0x8000;
                for(m=0;m<0x10000;m++)
                  if(b[m]&0x8000) b[m]&=0x7fff; else a[m]=b[m]=0;
                  for(q=257;b[q];q++) if(q>=0x10000) break /* MOAN */;}
/* Here UNLZW.C zeros all the arrays a and b, and returns N to 9 */
/* I and PKZIP merely remove all code entries that no other code entry is */
/* pointing to. */
            goto X;}
        for(l=0,j=c;j>255;j=j==q?p:a[j]) w[l++]=b[j]; w[l++]=j;
        a[q]=p; b[q]=j; if(c==q) w[0]=j; pn[q]=pc;
        for(q++;b[q];q++) if(q>=0x10000) break /* MOAN */;
        for(j=l-1;j>=0;j--) putc(w[j],Y);}}
fclose(Y); fclose(Z);}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019