1 /* This file is part of libmspack.
2  * (C) 2003-2018 Stuart Caie.
3  *
4  * libmspack is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6  *
7  * For further details, see the file COPYING.LIB distributed with libmspack
8  */
9 
10 /* Cabinet (.CAB) files are a form of file archive. Each cabinet contains
11  * "folders", which are compressed spans of data. Each cabinet has
12  * "files", whose metadata is in the cabinet header, but whose actual data
13  * is stored compressed in one of the "folders". Cabinets can span more
14  * than one physical file on disk, in which case they are a "cabinet set",
15  * and usually the last folder of each cabinet extends into the next
16  * cabinet.
17  *
18  * For a complete description of the format, see the MSDN site:
19  *   http://msdn.microsoft.com/en-us/library/bb267310.aspx
20  */
21 
22 /* CAB decompression implementation */
23 
24 #include <system.h>
25 #include <cab.h>
26 #include <mszip.h>
27 #include <lzx.h>
28 #include <qtm.h>
29 
30 /* Notes on compliance with cabinet specification:
31  *
32  * One of the main changes between cabextract 0.6 and libmspack's cab
33  * decompressor is the move from block-oriented decompression to
34  * stream-oriented decompression.
35  *
36  * cabextract would read one data block from disk, decompress it with the
37  * appropriate method, then write the decompressed data. The CAB
38  * specification is specifically designed to work like this, as it ensures
39  * compression matches do not span the maximum decompressed block size
40  * limit of 32kb.
41  *
42  * However, the compression algorithms used are stream oriented, with
43  * specific hacks added to them to enforce the "individual 32kb blocks"
44  * rule in CABs. In other file formats, they do not have this limitation.
45  *
46  * In order to make more generalised decompressors, libmspack's CAB
47  * decompressor has moved from being block-oriented to more stream
48  * oriented. This also makes decompression slightly faster.
49  *
50  * However, this leads to incompliance with the CAB specification. The
51  * CAB controller can no longer ensure each block of input given to the
52  * decompressors is matched with their output. The "decompressed size" of
53  * each individual block is thrown away.
54  *
55  * Each CAB block is supposed to be seen as individually compressed. This
56  * means each consecutive data block can have completely different
57  * "uncompressed" sizes, ranging from 1 to 32768 bytes. However, in
58  * reality, all data blocks in a folder decompress to exactly 32768 bytes,
59  * excepting the final block.
60  *
61  * Given this situation, the decompression algorithms are designed to
62  * realign their input bitstreams on 32768 output-byte boundaries, and
63  * various other special cases have been made. libmspack will not
64  * correctly decompress LZX or Quantum compressed folders where the blocks
65  * do not follow this "32768 bytes until last block" pattern. It could be
66  * implemented if needed, but hopefully this is not necessary -- it has
67  * not been seen in over 3Gb of CAB archives.
68  */
69 
70 /* prototypes */
71 static struct mscabd_cabinet * cabd_open(
72   struct mscab_decompressor *base, const char *filename);
73 static void cabd_close(
74   struct mscab_decompressor *base, struct mscabd_cabinet *origcab);
75 static int cabd_read_headers(
76   struct mspack_system *sys, struct mspack_file *fh,
77   struct mscabd_cabinet_p *cab, off_t offset, int salvage, int quiet);
78 static char *cabd_read_string(
79   struct mspack_system *sys, struct mspack_file *fh, int *error);
80 
81 static struct mscabd_cabinet *cabd_search(
82   struct mscab_decompressor *base, const char *filename);
83 static int cabd_find(
84   struct mscab_decompressor_p *self, unsigned char *buf,
85   struct mspack_file *fh, const char *filename, off_t flen,
86   off_t *firstlen, struct mscabd_cabinet_p **firstcab);
87 
88 static int cabd_prepend(
89   struct mscab_decompressor *base, struct mscabd_cabinet *cab,
90   struct mscabd_cabinet *prevcab);
91 static int cabd_append(
92   struct mscab_decompressor *base, struct mscabd_cabinet *cab,
93   struct mscabd_cabinet *nextcab);
94 static int cabd_merge(
95   struct mscab_decompressor *base, struct mscabd_cabinet *lcab,
96   struct mscabd_cabinet *rcab);
97 static int cabd_can_merge_folders(
98   struct mspack_system *sys, struct mscabd_folder_p *lfol,
99   struct mscabd_folder_p *rfol);
100 
101 static int cabd_extract(
102   struct mscab_decompressor *base, struct mscabd_file *file,
103   const char *filename);
104 static int cabd_init_decomp(
105   struct mscab_decompressor_p *self, unsigned int ct);
106 static void cabd_free_decomp(
107   struct mscab_decompressor_p *self);
108 static int cabd_sys_read(
109   struct mspack_file *file, void *buffer, int bytes);
110 static int cabd_sys_write(
111   struct mspack_file *file, void *buffer, int bytes);
112 static int cabd_sys_read_block(
113   struct mspack_system *sys, struct mscabd_decompress_state *d, int *out,
114   int ignore_cksum, int ignore_blocksize);
115 static unsigned int cabd_checksum(
116   unsigned char *data, unsigned int bytes, unsigned int cksum);
117 static struct noned_state *noned_init(
118   struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out,
119   int bufsize);
120 
121 static int noned_decompress(
122   struct noned_state *s, off_t bytes);
123 static void noned_free(
124   struct noned_state *state);
125 
126 static int cabd_param(
127   struct mscab_decompressor *base, int param, int value);
128 
129 static int cabd_error(
130   struct mscab_decompressor *base);
131 
132 
133 /***************************************
134  * MSPACK_CREATE_CAB_DECOMPRESSOR
135  ***************************************
136  * constructor
137  */
138 struct mscab_decompressor *
mspack_create_cab_decompressor(struct mspack_system * sys)139   mspack_create_cab_decompressor(struct mspack_system *sys)
140 {
141   struct mscab_decompressor_p *self = NULL;
142 
143   if (!sys) sys = mspack_default_system;
144   if (!mspack_valid_system(sys)) return NULL;
145 
146   if ((self = (struct mscab_decompressor_p *) sys->alloc(sys, sizeof(struct mscab_decompressor_p)))) {
147     self->base.open       = &cabd_open;
148     self->base.close      = &cabd_close;
149     self->base.search     = &cabd_search;
150     self->base.extract    = &cabd_extract;
151     self->base.prepend    = &cabd_prepend;
152     self->base.append     = &cabd_append;
153     self->base.set_param  = &cabd_param;
154     self->base.last_error = &cabd_error;
155     self->system          = sys;
156     self->d               = NULL;
157     self->error           = MSPACK_ERR_OK;
158 
159     self->searchbuf_size  = 32768;
160     self->fix_mszip       = 0;
161     self->buf_size        = 4096;
162     self->salvage         = 0;
163   }
164   return (struct mscab_decompressor *) self;
165 }
166 
167 /***************************************
168  * MSPACK_DESTROY_CAB_DECOMPRESSOR
169  ***************************************
170  * destructor
171  */
mspack_destroy_cab_decompressor(struct mscab_decompressor * base)172 void mspack_destroy_cab_decompressor(struct mscab_decompressor *base) {
173   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
174   if (self) {
175     struct mspack_system *sys = self->system;
176     if (self->d) {
177       if (self->d->infh) sys->close(self->d->infh);
178       cabd_free_decomp(self);
179       sys->free(self->d);
180     }
181     sys->free(self);
182   }
183 }
184 
185 
186 /***************************************
187  * CABD_OPEN
188  ***************************************
189  * opens a file and tries to read it as a cabinet file
190  */
cabd_open(struct mscab_decompressor * base,const char * filename)191 static struct mscabd_cabinet *cabd_open(struct mscab_decompressor *base,
192                                         const char *filename)
193 {
194   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
195   struct mscabd_cabinet_p *cab = NULL;
196   struct mspack_system *sys;
197   struct mspack_file *fh;
198   int error;
199 
200   if (!base) return NULL;
201   sys = self->system;
202 
203   if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
204     if ((cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
205       cab->base.filename = filename;
206       error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->salvage, 0);
207       if (error) {
208         cabd_close(base, (struct mscabd_cabinet *) cab);
209         cab = NULL;
210       }
211       self->error = error;
212     }
213     else {
214       self->error = MSPACK_ERR_NOMEMORY;
215     }
216     sys->close(fh);
217   }
218   else {
219     self->error = MSPACK_ERR_OPEN;
220   }
221   return (struct mscabd_cabinet *) cab;
222 }
223 
224 /***************************************
225  * CABD_CLOSE
226  ***************************************
227  * frees all memory associated with a given mscabd_cabinet.
228  */
cabd_close(struct mscab_decompressor * base,struct mscabd_cabinet * origcab)229 static void cabd_close(struct mscab_decompressor *base,
230                        struct mscabd_cabinet *origcab)
231 {
232   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
233   struct mscabd_folder_data *dat, *ndat;
234   struct mscabd_cabinet *cab, *ncab;
235   struct mscabd_folder *fol, *nfol;
236   struct mscabd_file *fi, *nfi;
237   struct mspack_system *sys;
238 
239   if (!base) return;
240   sys = self->system;
241 
242   self->error = MSPACK_ERR_OK;
243 
244   while (origcab) {
245     /* free files */
246     for (fi = origcab->files; fi; fi = nfi) {
247       nfi = fi->next;
248       sys->free(fi->filename);
249       sys->free(fi);
250     }
251 
252     /* free folders */
253     for (fol = origcab->folders; fol; fol = nfol) {
254       nfol = fol->next;
255 
256       /* free folder decompression state if it has been decompressed */
257       if (self->d && (self->d->folder == (struct mscabd_folder_p *) fol)) {
258         if (self->d->infh) sys->close(self->d->infh);
259         cabd_free_decomp(self);
260         sys->free(self->d);
261         self->d = NULL;
262       }
263 
264       /* free folder data segments */
265       for (dat = ((struct mscabd_folder_p *)fol)->data.next; dat; dat = ndat) {
266         ndat = dat->next;
267         sys->free(dat);
268       }
269       sys->free(fol);
270     }
271 
272     /* free predecessor cabinets (and the original cabinet's strings) */
273     for (cab = origcab; cab; cab = ncab) {
274       ncab = cab->prevcab;
275       sys->free(cab->prevname);
276       sys->free(cab->nextname);
277       sys->free(cab->previnfo);
278       sys->free(cab->nextinfo);
279       if (cab != origcab) sys->free(cab);
280     }
281 
282     /* free successor cabinets */
283     for (cab = origcab->nextcab; cab; cab = ncab) {
284       ncab = cab->nextcab;
285       sys->free(cab->prevname);
286       sys->free(cab->nextname);
287       sys->free(cab->previnfo);
288       sys->free(cab->nextinfo);
289       sys->free(cab);
290     }
291 
292     /* free actual cabinet structure */
293     cab = origcab->next;
294     sys->free(origcab);
295 
296     /* repeat full procedure again with the cab->next pointer (if set) */
297     origcab = cab;
298   }
299 }
300 
301 /***************************************
302  * CABD_READ_HEADERS
303  ***************************************
304  * reads the cabinet file header, folder list and file list.
305  * fills out a pre-existing mscabd_cabinet structure, allocates memory
306  * for folders and files as necessary
307  */
cabd_read_headers(struct mspack_system * sys,struct mspack_file * fh,struct mscabd_cabinet_p * cab,off_t offset,int salvage,int quiet)308 static int cabd_read_headers(struct mspack_system *sys,
309                              struct mspack_file *fh,
310                              struct mscabd_cabinet_p *cab,
311                              off_t offset, int salvage, int quiet)
312 {
313   int num_folders, num_files, folder_resv, i, x, err, fidx;
314   struct mscabd_folder_p *fol, *linkfol = NULL;
315   struct mscabd_file *file, *linkfile = NULL;
316   unsigned char buf[64];
317 
318   /* initialise pointers */
319   cab->base.next     = NULL;
320   cab->base.files    = NULL;
321   cab->base.folders  = NULL;
322   cab->base.prevcab  = cab->base.nextcab  = NULL;
323   cab->base.prevname = cab->base.nextname = NULL;
324   cab->base.previnfo = cab->base.nextinfo = NULL;
325 
326   cab->base.base_offset = offset;
327 
328   /* seek to CFHEADER */
329   if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
330     return MSPACK_ERR_SEEK;
331   }
332 
333   /* read in the CFHEADER */
334   if (sys->read(fh, &buf[0], cfhead_SIZEOF) != cfhead_SIZEOF) {
335     return MSPACK_ERR_READ;
336   }
337 
338   /* check for "MSCF" signature */
339   if (EndGetI32(&buf[cfhead_Signature]) != 0x4643534D) {
340     return MSPACK_ERR_SIGNATURE;
341   }
342 
343   /* some basic header fields */
344   cab->base.length    = EndGetI32(&buf[cfhead_CabinetSize]);
345   cab->base.set_id    = EndGetI16(&buf[cfhead_SetID]);
346   cab->base.set_index = EndGetI16(&buf[cfhead_CabinetIndex]);
347 
348   /* get the number of folders */
349   num_folders = EndGetI16(&buf[cfhead_NumFolders]);
350   if (num_folders == 0) {
351     if (!quiet) sys->message(fh, "no folders in cabinet.");
352     return MSPACK_ERR_DATAFORMAT;
353   }
354 
355   /* get the number of files */
356   num_files = EndGetI16(&buf[cfhead_NumFiles]);
357   if (num_files == 0) {
358     if (!quiet) sys->message(fh, "no files in cabinet.");
359     return MSPACK_ERR_DATAFORMAT;
360   }
361 
362   /* check cabinet version */
363   if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3)) {
364     if (!quiet) sys->message(fh, "WARNING; cabinet version is not 1.3");
365   }
366 
367   /* read the reserved-sizes part of header, if present */
368   cab->base.flags = EndGetI16(&buf[cfhead_Flags]);
369 
370   if (cab->base.flags & cfheadRESERVE_PRESENT) {
371     if (sys->read(fh, &buf[0], cfheadext_SIZEOF) != cfheadext_SIZEOF) {
372       return MSPACK_ERR_READ;
373     }
374     cab->base.header_resv = EndGetI16(&buf[cfheadext_HeaderReserved]);
375     folder_resv           = buf[cfheadext_FolderReserved];
376     cab->block_resv       = buf[cfheadext_DataReserved];
377 
378     if (cab->base.header_resv > 60000) {
379       if (!quiet) sys->message(fh, "WARNING; reserved header > 60000.");
380     }
381 
382     /* skip the reserved header */
383     if (cab->base.header_resv) {
384       if (sys->seek(fh, (off_t) cab->base.header_resv, MSPACK_SYS_SEEK_CUR)) {
385         return MSPACK_ERR_SEEK;
386       }
387     }
388   }
389   else {
390     cab->base.header_resv = 0;
391     folder_resv           = 0;
392     cab->block_resv       = 0;
393   }
394 
395   /* read name and info of preceeding cabinet in set, if present */
396   if (cab->base.flags & cfheadPREV_CABINET) {
397     cab->base.prevname = cabd_read_string(sys, fh, &err);
398     if (err) return err;
399     cab->base.previnfo = cabd_read_string(sys, fh, &err);
400     if (err) return err;
401   }
402 
403   /* read name and info of next cabinet in set, if present */
404   if (cab->base.flags & cfheadNEXT_CABINET) {
405     cab->base.nextname = cabd_read_string(sys, fh, &err);
406     if (err) return err;
407     cab->base.nextinfo = cabd_read_string(sys, fh, &err);
408     if (err) return err;
409   }
410 
411   /* read folders */
412   for (i = 0; i < num_folders; i++) {
413     if (sys->read(fh, &buf[0], cffold_SIZEOF) != cffold_SIZEOF) {
414       return MSPACK_ERR_READ;
415     }
416     if (folder_resv) {
417       if (sys->seek(fh, (off_t) folder_resv, MSPACK_SYS_SEEK_CUR)) {
418         return MSPACK_ERR_SEEK;
419       }
420     }
421 
422     if (!(fol = (struct mscabd_folder_p *) sys->alloc(sys, sizeof(struct mscabd_folder_p)))) {
423       return MSPACK_ERR_NOMEMORY;
424     }
425     fol->base.next       = NULL;
426     fol->base.comp_type  = EndGetI16(&buf[cffold_CompType]);
427     fol->base.num_blocks = EndGetI16(&buf[cffold_NumBlocks]);
428     fol->data.next       = NULL;
429     fol->data.cab        = (struct mscabd_cabinet_p *) cab;
430     fol->data.offset     = offset + (off_t)
431       ( (unsigned int) EndGetI32(&buf[cffold_DataOffset]) );
432     fol->merge_prev      = NULL;
433     fol->merge_next      = NULL;
434 
435     /* link folder into list of folders */
436     if (!linkfol) cab->base.folders = (struct mscabd_folder *) fol;
437     else linkfol->base.next = (struct mscabd_folder *) fol;
438     linkfol = fol;
439   }
440 
441   /* read files */
442   for (i = 0; i < num_files; i++) {
443     if (sys->read(fh, &buf[0], cffile_SIZEOF) != cffile_SIZEOF) {
444       return MSPACK_ERR_READ;
445     }
446 
447     if (!(file = (struct mscabd_file *) sys->alloc(sys, sizeof(struct mscabd_file)))) {
448       return MSPACK_ERR_NOMEMORY;
449     }
450 
451     file->next     = NULL;
452     file->length   = EndGetI32(&buf[cffile_UncompressedSize]);
453     file->attribs  = EndGetI16(&buf[cffile_Attribs]);
454     file->offset   = EndGetI32(&buf[cffile_FolderOffset]);
455 
456     /* set folder pointer */
457     fidx = EndGetI16(&buf[cffile_FolderIndex]);
458     if (fidx < cffileCONTINUED_FROM_PREV) {
459       /* normal folder index; count up to the correct folder */
460       if (fidx < num_folders) {
461         struct mscabd_folder *ifol = cab->base.folders;
462         while (fidx--) if (ifol) ifol = ifol->next;
463         file->folder = ifol;
464       }
465       else {
466         D(("invalid folder index"))
467         file->folder = NULL;
468       }
469     }
470     else {
471       /* either CONTINUED_TO_NEXT, CONTINUED_FROM_PREV or
472        * CONTINUED_PREV_AND_NEXT */
473       if ((fidx == cffileCONTINUED_TO_NEXT) ||
474           (fidx == cffileCONTINUED_PREV_AND_NEXT))
475       {
476         /* get last folder */
477         struct mscabd_folder *ifol = cab->base.folders;
478         while (ifol->next) ifol = ifol->next;
479         file->folder = ifol;
480 
481         /* set "merge next" pointer */
482         fol = (struct mscabd_folder_p *) ifol;
483         if (!fol->merge_next) fol->merge_next = file;
484       }
485 
486       if ((fidx == cffileCONTINUED_FROM_PREV) ||
487           (fidx == cffileCONTINUED_PREV_AND_NEXT))
488       {
489         /* get first folder */
490         file->folder = cab->base.folders;
491 
492         /* set "merge prev" pointer */
493         fol = (struct mscabd_folder_p *) file->folder;
494         if (!fol->merge_prev) fol->merge_prev = file;
495       }
496     }
497 
498     /* get time */
499     x = EndGetI16(&buf[cffile_Time]);
500     file->time_h = x >> 11;
501     file->time_m = (x >> 5) & 0x3F;
502     file->time_s = (x << 1) & 0x3E;
503 
504     /* get date */
505     x = EndGetI16(&buf[cffile_Date]);
506     file->date_d = x & 0x1F;
507     file->date_m = (x >> 5) & 0xF;
508     file->date_y = (x >> 9) + 1980;
509 
510     /* get filename */
511     file->filename = cabd_read_string(sys, fh, &err);
512 
513     /* if folder index or filename are bad, either skip it or fail */
514     if (err || !file->folder) {
515       sys->free(file->filename);
516       sys->free(file);
517       if (salvage) continue;
518       return err ? err : MSPACK_ERR_DATAFORMAT;
519     }
520 
521     /* link file entry into file list */
522     if (!linkfile) cab->base.files = file;
523     else linkfile->next = file;
524     linkfile = file;
525   }
526 
527   if (cab->base.files == NULL) {
528     /* We never actually added any files to the file list.  Something went wrong.
529      * The file header may have been invalid */
530     D(("No files found, even though header claimed to have %d files", num_files))
531     return MSPACK_ERR_DATAFORMAT;
532   }
533 
534   return MSPACK_ERR_OK;
535 }
536 
cabd_read_string(struct mspack_system * sys,struct mspack_file * fh,int * error)537 static char *cabd_read_string(struct mspack_system *sys,
538                               struct mspack_file *fh, int *error)
539 {
540   off_t base = sys->tell(fh);
541   char buf[256], *str;
542   int len, i, ok;
543 
544   /* read up to 256 bytes */
545   if ((len = sys->read(fh, &buf[0], 256)) <= 0) {
546     *error = MSPACK_ERR_READ;
547     return NULL;
548   }
549 
550   /* search for a null terminator in the buffer */
551   for (i = 0, ok = 0; i < len; i++) if (!buf[i]) { ok = 1; break; }
552   /* reject empty strings */
553   if (i == 0) ok = 0;
554 
555   if (!ok) {
556     *error = MSPACK_ERR_DATAFORMAT;
557     return NULL;
558   }
559 
560   len = i + 1;
561 
562   /* set the data stream to just after the string and return */
563   if (sys->seek(fh, base + (off_t)len, MSPACK_SYS_SEEK_START)) {
564     *error = MSPACK_ERR_SEEK;
565     return NULL;
566   }
567 
568   if (!(str = (char *) sys->alloc(sys, len))) {
569     *error = MSPACK_ERR_NOMEMORY;
570     return NULL;
571   }
572 
573   sys->copy(&buf[0], str, len);
574   *error = MSPACK_ERR_OK;
575   return str;
576 }
577 
578 /***************************************
579  * CABD_SEARCH, CABD_FIND
580  ***************************************
581  * cabd_search opens a file, finds its extent, allocates a search buffer,
582  * then reads through the whole file looking for possible cabinet headers.
583  * if it finds any, it tries to read them as real cabinets. returns a linked
584  * list of results
585  *
586  * cabd_find is the inner loop of cabd_search, to make it easier to
587  * break out of the loop and be sure that all resources are freed
588  */
cabd_search(struct mscab_decompressor * base,const char * filename)589 static struct mscabd_cabinet *cabd_search(struct mscab_decompressor *base,
590                                           const char *filename)
591 {
592   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
593   struct mscabd_cabinet_p *cab = NULL;
594   struct mspack_system *sys;
595   unsigned char *search_buf;
596   struct mspack_file *fh;
597   off_t filelen, firstlen = 0;
598 
599   if (!base) return NULL;
600   sys = self->system;
601 
602   /* allocate a search buffer */
603   search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->searchbuf_size);
604   if (!search_buf) {
605     self->error = MSPACK_ERR_NOMEMORY;
606     return NULL;
607   }
608 
609   /* open file and get its full file length */
610   if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
611     if (!(self->error = mspack_sys_filelen(sys, fh, &filelen))) {
612       self->error = cabd_find(self, search_buf, fh, filename,
613                               filelen, &firstlen, &cab);
614     }
615 
616     /* truncated / extraneous data warning: */
617     if (firstlen && (firstlen != filelen) &&
618         (!cab || (cab->base.base_offset == 0)))
619     {
620       if (firstlen < filelen) {
621         sys->message(fh, "WARNING; possible %" LD
622                      " extra bytes at end of file.",
623                      filelen - firstlen);
624       }
625       else {
626         sys->message(fh, "WARNING; file possibly truncated by %" LD " bytes.",
627                      firstlen - filelen);
628       }
629     }
630 
631     sys->close(fh);
632   }
633   else {
634     self->error = MSPACK_ERR_OPEN;
635   }
636 
637   /* free the search buffer */
638   sys->free(search_buf);
639 
640   return (struct mscabd_cabinet *) cab;
641 }
642 
cabd_find(struct mscab_decompressor_p * self,unsigned char * buf,struct mspack_file * fh,const char * filename,off_t flen,off_t * firstlen,struct mscabd_cabinet_p ** firstcab)643 static int cabd_find(struct mscab_decompressor_p *self, unsigned char *buf,
644                      struct mspack_file *fh, const char *filename, off_t flen,
645                      off_t *firstlen, struct mscabd_cabinet_p **firstcab)
646 {
647   struct mscabd_cabinet_p *cab, *link = NULL;
648   off_t caboff, offset, length;
649   struct mspack_system *sys = self->system;
650   unsigned char *p, *pend, state = 0;
651   unsigned int cablen_u32 = 0, foffset_u32 = 0;
652   int false_cabs = 0;
653 
654 #if !LARGEFILE_SUPPORT
655   /* detect 32-bit off_t overflow */
656   if (flen < 0) {
657     sys->message(fh, largefile_msg);
658     return MSPACK_ERR_OK;
659   }
660 #endif
661 
662   /* search through the full file length */
663   for (offset = 0; offset < flen; offset += length) {
664     /* search length is either the full length of the search buffer, or the
665      * amount of data remaining to the end of the file, whichever is less. */
666     length = flen - offset;
667     if (length > self->searchbuf_size) {
668       length = self->searchbuf_size;
669     }
670 
671     /* fill the search buffer with data from disk */
672     if (sys->read(fh, &buf[0], (int) length) != (int) length) {
673       return MSPACK_ERR_READ;
674     }
675 
676     /* FAQ avoidance strategy */
677     if ((offset == 0) && (EndGetI32(&buf[0]) == 0x28635349)) {
678       sys->message(fh, "WARNING; found InstallShield header. Use unshield "
679                    "(https://github.com/twogood/unshield) to unpack this file");
680     }
681 
682     /* read through the entire buffer. */
683     for (p = &buf[0], pend = &buf[length]; p < pend; ) {
684       switch (state) {
685         /* starting state */
686       case 0:
687         /* we spend most of our time in this while loop, looking for
688          * a leading 'M' of the 'MSCF' signature */
689         while (p < pend && *p != 0x4D) p++;
690         /* if we found tht 'M', advance state */
691         if (p++ < pend) state = 1;
692         break;
693 
694       /* verify that the next 3 bytes are 'S', 'C' and 'F' */
695       case 1: state = (*p++ == 0x53) ? 2 : 0; break;
696       case 2: state = (*p++ == 0x43) ? 3 : 0; break;
697       case 3: state = (*p++ == 0x46) ? 4 : 0; break;
698 
699       /* we don't care about bytes 4-7 (see default: for action) */
700 
701       /* bytes 8-11 are the overall length of the cabinet */
702       case 8:  cablen_u32  = *p++;       state++; break;
703       case 9:  cablen_u32 |= *p++ << 8;  state++; break;
704       case 10: cablen_u32 |= *p++ << 16; state++; break;
705       case 11: cablen_u32 |= *p++ << 24; state++; break;
706 
707       /* we don't care about bytes 12-15 (see default: for action) */
708 
709       /* bytes 16-19 are the offset within the cabinet of the filedata */
710       case 16: foffset_u32  = *p++;       state++; break;
711       case 17: foffset_u32 |= *p++ << 8;  state++; break;
712       case 18: foffset_u32 |= *p++ << 16; state++; break;
713       case 19: foffset_u32 |= *p++ << 24;
714         /* now we have recieved 20 bytes of potential cab header. work out
715          * the offset in the file of this potential cabinet */
716         caboff = offset + (p - &buf[0]) - 20;
717 
718         /* should reading cabinet fail, restart search just after 'MSCF' */
719         offset = caboff + 4;
720 
721         /* capture the "length of cabinet" field if there is a cabinet at
722          * offset 0 in the file, regardless of whether the cabinet can be
723          * read correctly or not */
724         if (caboff == 0) *firstlen = (off_t) cablen_u32;
725 
726         /* check that the files offset is less than the alleged length of
727          * the cabinet, and that the offset + the alleged length are
728          * 'roughly' within the end of overall file length. In salvage
729          * mode, don't check the alleged length, allow it to be garbage */
730         if ((foffset_u32 < cablen_u32) &&
731             ((caboff + (off_t) foffset_u32) < (flen + 32)) &&
732             (((caboff + (off_t) cablen_u32)  < (flen + 32)) || self->salvage))
733         {
734           /* likely cabinet found -- try reading it */
735           if (!(cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
736             return MSPACK_ERR_NOMEMORY;
737           }
738           cab->base.filename = filename;
739           if (cabd_read_headers(sys, fh, cab, caboff, self->salvage, 1)) {
740             /* destroy the failed cabinet */
741             cabd_close((struct mscab_decompressor *) self,
742                        (struct mscabd_cabinet *) cab);
743             false_cabs++;
744           }
745           else {
746             /* cabinet read correctly! */
747 
748             /* link the cab into the list */
749             if (!link) *firstcab = cab;
750             else link->base.next = (struct mscabd_cabinet *) cab;
751             link = cab;
752 
753             /* cause the search to restart after this cab's data. */
754             offset = caboff + (off_t) cablen_u32;
755 
756 #if !LARGEFILE_SUPPORT
757             /* detect 32-bit off_t overflow */
758             if (offset < caboff) {
759               sys->message(fh, largefile_msg);
760               return MSPACK_ERR_OK;
761             }
762 #endif
763           }
764         }
765 
766         /* restart search */
767         if (offset >= flen) return MSPACK_ERR_OK;
768         if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
769           return MSPACK_ERR_SEEK;
770         }
771         length = 0;
772         p = pend;
773         state = 0;
774         break;
775 
776       /* for bytes 4-7 and 12-15, just advance state/pointer */
777       default:
778         p++, state++;
779       } /* switch(state) */
780     } /* for (... p < pend ...) */
781   } /* for (... offset < length ...) */
782 
783   if (false_cabs) {
784     D(("%d false cabinets found", false_cabs))
785   }
786 
787   return MSPACK_ERR_OK;
788 }
789 
790 /***************************************
791  * CABD_MERGE, CABD_PREPEND, CABD_APPEND
792  ***************************************
793  * joins cabinets together, also merges split folders between these two
794  * cabinets only. This includes freeing the duplicate folder and file(s)
795  * and allocating a further mscabd_folder_data structure to append to the
796  * merged folder's data parts list.
797  */
cabd_prepend(struct mscab_decompressor * base,struct mscabd_cabinet * cab,struct mscabd_cabinet * prevcab)798 static int cabd_prepend(struct mscab_decompressor *base,
799                         struct mscabd_cabinet *cab,
800                         struct mscabd_cabinet *prevcab)
801 {
802   return cabd_merge(base, prevcab, cab);
803 }
804 
cabd_append(struct mscab_decompressor * base,struct mscabd_cabinet * cab,struct mscabd_cabinet * nextcab)805 static int cabd_append(struct mscab_decompressor *base,
806                         struct mscabd_cabinet *cab,
807                         struct mscabd_cabinet *nextcab)
808 {
809   return cabd_merge(base, cab, nextcab);
810 }
811 
cabd_merge(struct mscab_decompressor * base,struct mscabd_cabinet * lcab,struct mscabd_cabinet * rcab)812 static int cabd_merge(struct mscab_decompressor *base,
813                       struct mscabd_cabinet *lcab,
814                       struct mscabd_cabinet *rcab)
815 {
816   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
817   struct mscabd_folder_data *data, *ndata;
818   struct mscabd_folder_p *lfol, *rfol;
819   struct mscabd_file *fi, *rfi, *lfi;
820   struct mscabd_cabinet *cab;
821   struct mspack_system *sys;
822 
823   if (!self) return MSPACK_ERR_ARGS;
824   sys = self->system;
825 
826   /* basic args check */
827   if (!lcab || !rcab || (lcab == rcab)) {
828     D(("lcab NULL, rcab NULL or lcab = rcab"))
829     return self->error = MSPACK_ERR_ARGS;
830   }
831 
832   /* check there's not already a cabinet attached */
833   if (lcab->nextcab || rcab->prevcab) {
834     D(("cabs already joined"))
835     return self->error = MSPACK_ERR_ARGS;
836   }
837 
838   /* do not create circular cabinet chains */
839   for (cab = lcab->prevcab; cab; cab = cab->prevcab) {
840     if (cab == rcab) {D(("circular!")) return self->error = MSPACK_ERR_ARGS;}
841   }
842   for (cab = rcab->nextcab; cab; cab = cab->nextcab) {
843     if (cab == lcab) {D(("circular!")) return self->error = MSPACK_ERR_ARGS;}
844   }
845 
846   /* warn about odd set IDs or indices */
847   if (lcab->set_id != rcab->set_id) {
848     sys->message(NULL, "WARNING; merged cabinets with differing Set IDs.");
849   }
850 
851   if (lcab->set_index > rcab->set_index) {
852     sys->message(NULL, "WARNING; merged cabinets with odd order.");
853   }
854 
855   /* merging the last folder in lcab with the first folder in rcab */
856   lfol = (struct mscabd_folder_p *) lcab->folders;
857   rfol = (struct mscabd_folder_p *) rcab->folders;
858   while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next;
859 
860   /* do we need to merge folders? */
861   if (!lfol->merge_next && !rfol->merge_prev) {
862     /* no, at least one of the folders is not for merging */
863 
864     /* attach cabs */
865     lcab->nextcab = rcab;
866     rcab->prevcab = lcab;
867 
868     /* attach folders */
869     lfol->base.next = (struct mscabd_folder *) rfol;
870 
871     /* attach files */
872     fi = lcab->files;
873     while (fi->next) fi = fi->next;
874     fi->next = rcab->files;
875   }
876   else {
877     /* folder merge required - do the files match? */
878     if (! cabd_can_merge_folders(sys, lfol, rfol)) {
879       return self->error = MSPACK_ERR_DATAFORMAT;
880     }
881 
882     /* allocate a new folder data structure */
883     if (!(data = (struct mscabd_folder_data *) sys->alloc(sys, sizeof(struct mscabd_folder_data)))) {
884       return self->error = MSPACK_ERR_NOMEMORY;
885     }
886 
887     /* attach cabs */
888     lcab->nextcab = rcab;
889     rcab->prevcab = lcab;
890 
891     /* append rfol's data to lfol */
892     ndata = &lfol->data;
893     while (ndata->next) ndata = ndata->next;
894     ndata->next = data;
895     *data = rfol->data;
896     rfol->data.next = NULL;
897 
898     /* lfol becomes rfol.
899      * NOTE: special case, don't merge if rfol is merge prev and next,
900      * rfol->merge_next is going to be deleted, so keep lfol's version
901      * instead */
902     lfol->base.num_blocks += rfol->base.num_blocks - 1;
903     if ((rfol->merge_next == NULL) ||
904         (rfol->merge_next->folder != (struct mscabd_folder *) rfol))
905     {
906       lfol->merge_next = rfol->merge_next;
907     }
908 
909     /* attach the rfol's folder (except the merge folder) */
910     while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next;
911     lfol->base.next = rfol->base.next;
912 
913     /* free disused merge folder */
914     sys->free(rfol);
915 
916     /* attach rfol's files */
917     fi = lcab->files;
918     while (fi->next) fi = fi->next;
919     fi->next = rcab->files;
920 
921     /* delete all files from rfol's merge folder */
922     lfi = NULL;
923     for (fi = lcab->files; fi ; fi = rfi) {
924       rfi = fi->next;
925       /* if file's folder matches the merge folder, unlink and free it */
926       if (fi->folder == (struct mscabd_folder *) rfol) {
927         if (lfi) lfi->next = rfi; else lcab->files = rfi;
928         sys->free(fi->filename);
929         sys->free(fi);
930       }
931       else lfi = fi;
932     }
933   }
934 
935   /* all done! fix files and folders pointers in all cabs so they all
936    * point to the same list  */
937   for (cab = lcab->prevcab; cab; cab = cab->prevcab) {
938     cab->files   = lcab->files;
939     cab->folders = lcab->folders;
940   }
941 
942   for (cab = lcab->nextcab; cab; cab = cab->nextcab) {
943     cab->files   = lcab->files;
944     cab->folders = lcab->folders;
945   }
946 
947   return self->error = MSPACK_ERR_OK;
948 }
949 
950 /* decides if two folders are OK to merge */
cabd_can_merge_folders(struct mspack_system * sys,struct mscabd_folder_p * lfol,struct mscabd_folder_p * rfol)951 static int cabd_can_merge_folders(struct mspack_system *sys,
952                                   struct mscabd_folder_p *lfol,
953                                   struct mscabd_folder_p *rfol)
954 {
955     struct mscabd_file *lfi, *rfi, *l, *r;
956     int matching = 1;
957 
958     /* check that both folders use the same compression method/settings */
959     if (lfol->base.comp_type != rfol->base.comp_type) {
960         D(("folder merge: compression type mismatch"))
961         return 0;
962     }
963 
964     /* check there are not too many data blocks after merging */
965     if ((lfol->base.num_blocks + rfol->base.num_blocks) > CAB_FOLDERMAX) {
966         D(("folder merge: too many data blocks in merged folders"))
967         return 0;
968     }
969 
970     if (!(lfi = lfol->merge_next) || !(rfi = rfol->merge_prev)) {
971         D(("folder merge: one cabinet has no files to merge"))
972         return 0;
973     }
974 
975     /* for all files in lfol (which is the last folder in whichever cab and
976      * only has files to merge), compare them to the files from rfol. They
977      * should be identical in number and order. to verify this, check the
978      * offset and length of each file. */
979     for (l=lfi, r=rfi; l; l=l->next, r=r->next) {
980         if (!r || (l->offset != r->offset) || (l->length != r->length)) {
981             matching = 0;
982             break;
983         }
984     }
985 
986     if (matching) return 1;
987 
988     /* if rfol does not begin with an identical copy of the files in lfol, make
989      * make a judgement call; if at least ONE file from lfol is in rfol, allow
990      * the merge with a warning about missing files. */
991     matching = 0;
992     for (l = lfi; l; l = l->next) {
993         for (r = rfi; r; r = r->next) {
994             if (l->offset == r->offset && l->length == r->length) break;
995         }
996         if (r) matching = 1; else sys->message(NULL,
997             "WARNING; merged file %s not listed in both cabinets", l->filename);
998     }
999     return matching;
1000 }
1001 
1002 
1003 /***************************************
1004  * CABD_EXTRACT
1005  ***************************************
1006  * extracts a file from a cabinet
1007  */
cabd_extract(struct mscab_decompressor * base,struct mscabd_file * file,const char * filename)1008 static int cabd_extract(struct mscab_decompressor *base,
1009                         struct mscabd_file *file, const char *filename)
1010 {
1011   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1012   struct mscabd_folder_p *fol;
1013   struct mspack_system *sys;
1014   struct mspack_file *fh;
1015   off_t filelen;
1016 
1017   if (!self) return MSPACK_ERR_ARGS;
1018   if (!file) return self->error = MSPACK_ERR_ARGS;
1019 
1020   sys = self->system;
1021   fol = (struct mscabd_folder_p *) file->folder;
1022 
1023   /* if offset is beyond 2GB, nothing can be extracted */
1024   if (file->offset > CAB_LENGTHMAX) {
1025     return self->error = MSPACK_ERR_DATAFORMAT;
1026   }
1027 
1028   /* if file claims to go beyond 2GB either error out,
1029    * or in salvage mode reduce file length so it fits 2GB limit
1030    */
1031   filelen = file->length;
1032   if (filelen > CAB_LENGTHMAX || (file->offset + filelen) > CAB_LENGTHMAX) {
1033     if (self->salvage) {
1034       filelen = CAB_LENGTHMAX - file->offset;
1035     }
1036     else {
1037       return self->error = MSPACK_ERR_DATAFORMAT;
1038     }
1039   }
1040 
1041   /* extraction impossible if no folder, or folder needs predecessor */
1042   if (!fol || fol->merge_prev) {
1043     sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
1044                  "cabinet set is incomplete", file->filename);
1045     return self->error = MSPACK_ERR_DECRUNCH;
1046   }
1047 
1048   /* if file goes beyond what can be decoded, given an error.
1049    * In salvage mode, don't assume block sizes, just try decoding
1050    */
1051   if (!self->salvage) {
1052     off_t maxlen = fol->base.num_blocks * CAB_BLOCKMAX;
1053     if ((file->offset + filelen) > maxlen) {
1054       sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
1055                    "cabinet set is incomplete", file->filename);
1056       return self->error = MSPACK_ERR_DECRUNCH;
1057     }
1058   }
1059 
1060   /* allocate generic decompression state */
1061   if (!self->d) {
1062     self->d = (struct mscabd_decompress_state *) sys->alloc(sys, sizeof(struct mscabd_decompress_state));
1063     if (!self->d) return self->error = MSPACK_ERR_NOMEMORY;
1064     self->d->folder     = NULL;
1065     self->d->data       = NULL;
1066     self->d->sys        = *sys;
1067     self->d->sys.read   = &cabd_sys_read;
1068     self->d->sys.write  = &cabd_sys_write;
1069     self->d->state      = NULL;
1070     self->d->infh       = NULL;
1071     self->d->incab      = NULL;
1072   }
1073 
1074   /* do we need to change folder or reset the current folder? */
1075   if ((self->d->folder != fol) || (self->d->offset > file->offset) ||
1076       !self->d->state)
1077   {
1078     /* free any existing decompressor */
1079     cabd_free_decomp(self);
1080 
1081     /* do we need to open a new cab file? */
1082     if (!self->d->infh || (fol->data.cab != self->d->incab)) {
1083       /* close previous file handle if from a different cab */
1084       if (self->d->infh) sys->close(self->d->infh);
1085       self->d->incab = fol->data.cab;
1086       self->d->infh = sys->open(sys, fol->data.cab->base.filename,
1087                                 MSPACK_SYS_OPEN_READ);
1088       if (!self->d->infh) return self->error = MSPACK_ERR_OPEN;
1089     }
1090     /* seek to start of data blocks */
1091     if (sys->seek(self->d->infh, fol->data.offset, MSPACK_SYS_SEEK_START)) {
1092       return self->error = MSPACK_ERR_SEEK;
1093     }
1094 
1095     /* set up decompressor */
1096     if (cabd_init_decomp(self, (unsigned int) fol->base.comp_type)) {
1097       return self->error;
1098     }
1099 
1100     /* initialise new folder state */
1101     self->d->folder = fol;
1102     self->d->data   = &fol->data;
1103     self->d->offset = 0;
1104     self->d->block  = 0;
1105     self->d->outlen = 0;
1106     self->d->i_ptr = self->d->i_end = &self->d->input[0];
1107 
1108     /* read_error lasts for the lifetime of a decompressor */
1109     self->read_error = MSPACK_ERR_OK;
1110   }
1111 
1112   /* open file for output */
1113   if (!(fh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
1114     return self->error = MSPACK_ERR_OPEN;
1115   }
1116 
1117   self->error = MSPACK_ERR_OK;
1118 
1119   /* if file has more than 0 bytes */
1120   if (filelen) {
1121     off_t bytes;
1122     int error;
1123     /* get to correct offset.
1124      * - use NULL fh to say 'no writing' to cabd_sys_write()
1125      * - if cabd_sys_read() has an error, it will set self->read_error
1126      *   and pass back MSPACK_ERR_READ
1127      */
1128     self->d->outfh = NULL;
1129     if ((bytes = file->offset - self->d->offset)) {
1130         error = self->d->decompress(self->d->state, bytes);
1131         self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
1132     }
1133 
1134     /* if getting to the correct offset was error free, unpack file */
1135     if (!self->error) {
1136       self->d->outfh = fh;
1137       error = self->d->decompress(self->d->state, filelen);
1138       self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
1139     }
1140   }
1141 
1142   /* close output file */
1143   sys->close(fh);
1144   self->d->outfh = NULL;
1145 
1146   return self->error;
1147 }
1148 
1149 /***************************************
1150  * CABD_INIT_DECOMP, CABD_FREE_DECOMP
1151  ***************************************
1152  * cabd_init_decomp initialises decompression state, according to which
1153  * decompression method was used. relies on self->d->folder being the same
1154  * as when initialised.
1155  *
1156  * cabd_free_decomp frees decompression state, according to which method
1157  * was used.
1158  */
cabd_init_decomp(struct mscab_decompressor_p * self,unsigned int ct)1159 static int cabd_init_decomp(struct mscab_decompressor_p *self, unsigned int ct)
1160 {
1161   struct mspack_file *fh = (struct mspack_file *) self;
1162 
1163   self->d->comp_type = ct;
1164 
1165   switch (ct & cffoldCOMPTYPE_MASK) {
1166   case cffoldCOMPTYPE_NONE:
1167     self->d->decompress = (int (*)(void *, off_t)) &noned_decompress;
1168     self->d->state = noned_init(&self->d->sys, fh, fh, self->buf_size);
1169     break;
1170   case cffoldCOMPTYPE_MSZIP:
1171     self->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress;
1172     self->d->state = mszipd_init(&self->d->sys, fh, fh, self->buf_size,
1173                                  self->fix_mszip);
1174     break;
1175   case cffoldCOMPTYPE_QUANTUM:
1176     self->d->decompress = (int (*)(void *, off_t)) &qtmd_decompress;
1177     self->d->state = qtmd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f,
1178                                self->buf_size);
1179     break;
1180   case cffoldCOMPTYPE_LZX:
1181     self->d->decompress = (int (*)(void *, off_t)) &lzxd_decompress;
1182     self->d->state = lzxd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, 0,
1183                                self->buf_size, (off_t)0,0);
1184     break;
1185   default:
1186     return self->error = MSPACK_ERR_DATAFORMAT;
1187   }
1188   return self->error = (self->d->state) ? MSPACK_ERR_OK : MSPACK_ERR_NOMEMORY;
1189 }
1190 
cabd_free_decomp(struct mscab_decompressor_p * self)1191 static void cabd_free_decomp(struct mscab_decompressor_p *self) {
1192   if (!self || !self->d || !self->d->state) return;
1193 
1194   switch (self->d->comp_type & cffoldCOMPTYPE_MASK) {
1195   case cffoldCOMPTYPE_NONE:    noned_free((struct noned_state *) self->d->state);   break;
1196   case cffoldCOMPTYPE_MSZIP:   mszipd_free((struct mszipd_stream *) self->d->state);  break;
1197   case cffoldCOMPTYPE_QUANTUM: qtmd_free((struct qtmd_stream *) self->d->state);    break;
1198   case cffoldCOMPTYPE_LZX:     lzxd_free((struct lzxd_stream *) self->d->state);    break;
1199   }
1200   self->d->decompress = NULL;
1201   self->d->state      = NULL;
1202 }
1203 
1204 /***************************************
1205  * CABD_SYS_READ, CABD_SYS_WRITE
1206  ***************************************
1207  * cabd_sys_read is the internal reader function which the decompressors
1208  * use. will read data blocks (and merge split blocks) from the cabinet
1209  * and serve the read bytes to the decompressors
1210  *
1211  * cabd_sys_write is the internal writer function which the decompressors
1212  * use. it either writes data to disk (self->d->outfh) with the real
1213  * sys->write() function, or does nothing with the data when
1214  * self->d->outfh == NULL. advances self->d->offset
1215  */
cabd_sys_read(struct mspack_file * file,void * buffer,int bytes)1216 static int cabd_sys_read(struct mspack_file *file, void *buffer, int bytes) {
1217   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) file;
1218   unsigned char *buf = (unsigned char *) buffer;
1219   struct mspack_system *sys = self->system;
1220   int avail, todo, outlen, ignore_cksum, ignore_blocksize;
1221 
1222   ignore_cksum = self->salvage ||
1223     (self->fix_mszip &&
1224      ((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP));
1225   ignore_blocksize = self->salvage;
1226 
1227   todo = bytes;
1228   while (todo > 0) {
1229     avail = self->d->i_end - self->d->i_ptr;
1230 
1231     /* if out of input data, read a new block */
1232     if (avail) {
1233       /* copy as many input bytes available as possible */
1234       if (avail > todo) avail = todo;
1235       sys->copy(self->d->i_ptr, buf, (size_t) avail);
1236       self->d->i_ptr += avail;
1237       buf  += avail;
1238       todo -= avail;
1239     }
1240     else {
1241       /* out of data, read a new block */
1242 
1243       /* check if we're out of input blocks, advance block counter */
1244       if (self->d->block++ >= self->d->folder->base.num_blocks) {
1245         if (!self->salvage) {
1246           self->read_error = MSPACK_ERR_DATAFORMAT;
1247         }
1248         else {
1249           D(("Ran out of CAB input blocks prematurely"))
1250         }
1251         break;
1252       }
1253 
1254       /* read a block */
1255       self->read_error = cabd_sys_read_block(sys, self->d, &outlen,
1256         ignore_cksum, ignore_blocksize);
1257       if (self->read_error) return -1;
1258       self->d->outlen += outlen;
1259 
1260       /* special Quantum hack -- trailer byte to allow the decompressor
1261        * to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
1262        * anything from 0 to 4 trailing null bytes. */
1263       if ((self->d->comp_type & cffoldCOMPTYPE_MASK)==cffoldCOMPTYPE_QUANTUM) {
1264         *self->d->i_end++ = 0xFF;
1265       }
1266 
1267       /* is this the last block? */
1268       if (self->d->block >= self->d->folder->base.num_blocks) {
1269         if ((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_LZX) {
1270           /* special LZX hack -- on the last block, inform LZX of the
1271            * size of the output data stream. */
1272           lzxd_set_output_length((struct lzxd_stream *) self->d->state, self->d->outlen);
1273         }
1274       }
1275     } /* if (avail) */
1276   } /* while (todo > 0) */
1277   return bytes - todo;
1278 }
1279 
cabd_sys_write(struct mspack_file * file,void * buffer,int bytes)1280 static int cabd_sys_write(struct mspack_file *file, void *buffer, int bytes) {
1281   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) file;
1282   self->d->offset += bytes;
1283   if (self->d->outfh) {
1284     return self->system->write(self->d->outfh, buffer, bytes);
1285   }
1286   return bytes;
1287 }
1288 
1289 /***************************************
1290  * CABD_SYS_READ_BLOCK
1291  ***************************************
1292  * reads a whole data block from a cab file. the block may span more than
1293  * one cab file, if it does then the fragments will be reassembled
1294  */
cabd_sys_read_block(struct mspack_system * sys,struct mscabd_decompress_state * d,int * out,int ignore_cksum,int ignore_blocksize)1295 static int cabd_sys_read_block(struct mspack_system *sys,
1296                                struct mscabd_decompress_state *d,
1297                                int *out, int ignore_cksum,
1298                                int ignore_blocksize)
1299 {
1300   unsigned char hdr[cfdata_SIZEOF];
1301   unsigned int cksum;
1302   int len, full_len;
1303 
1304   /* reset the input block pointer and end of block pointer */
1305   d->i_ptr = d->i_end = &d->input[0];
1306 
1307   do {
1308     /* read the block header */
1309     if (sys->read(d->infh, &hdr[0], cfdata_SIZEOF) != cfdata_SIZEOF) {
1310       return MSPACK_ERR_READ;
1311     }
1312 
1313     /* skip any reserved block headers */
1314     if (d->data->cab->block_resv &&
1315         sys->seek(d->infh, (off_t) d->data->cab->block_resv,
1316                   MSPACK_SYS_SEEK_CUR))
1317     {
1318       return MSPACK_ERR_SEEK;
1319     }
1320 
1321     /* blocks must not be over CAB_INPUTMAX in size */
1322     len = EndGetI16(&hdr[cfdata_CompressedSize]);
1323     full_len = (d->i_end - d->i_ptr) + len; /* include cab-spanning blocks */
1324     if (full_len > CAB_INPUTMAX) {
1325       D(("block size %d > CAB_INPUTMAX", full_len));
1326       /* in salvage mode, blocks can be 65535 bytes but no more than that */
1327       if (!ignore_blocksize || full_len > CAB_INPUTMAX_SALVAGE) {
1328           return MSPACK_ERR_DATAFORMAT;
1329       }
1330     }
1331 
1332      /* blocks must not expand to more than CAB_BLOCKMAX */
1333     if (EndGetI16(&hdr[cfdata_UncompressedSize]) > CAB_BLOCKMAX) {
1334       D(("block size > CAB_BLOCKMAX"))
1335       if (!ignore_blocksize) return MSPACK_ERR_DATAFORMAT;
1336     }
1337 
1338     /* read the block data */
1339     if (sys->read(d->infh, d->i_end, len) != len) {
1340       return MSPACK_ERR_READ;
1341     }
1342 
1343     /* perform checksum test on the block (if one is stored) */
1344     if ((cksum = EndGetI32(&hdr[cfdata_CheckSum]))) {
1345       unsigned int sum2 = cabd_checksum(d->i_end, (unsigned int) len, 0);
1346       if (cabd_checksum(&hdr[4], 4, sum2) != cksum) {
1347         if (!ignore_cksum) return MSPACK_ERR_CHECKSUM;
1348         sys->message(d->infh, "WARNING; bad block checksum found");
1349       }
1350     }
1351 
1352     /* advance end of block pointer to include newly read data */
1353     d->i_end += len;
1354 
1355     /* uncompressed size == 0 means this block was part of a split block
1356      * and it continues as the first block of the next cabinet in the set.
1357      * otherwise, this is the last part of the block, and no more block
1358      * reading needs to be done.
1359      */
1360     /* EXIT POINT OF LOOP -- uncompressed size != 0 */
1361     if ((*out = EndGetI16(&hdr[cfdata_UncompressedSize]))) {
1362       return MSPACK_ERR_OK;
1363     }
1364 
1365     /* otherwise, advance to next cabinet */
1366 
1367     /* close current file handle */
1368     sys->close(d->infh);
1369     d->infh = NULL;
1370 
1371     /* advance to next member in the cabinet set */
1372     if (!(d->data = d->data->next)) {
1373       sys->message(d->infh, "WARNING; ran out of cabinets in set. Are any missing?");
1374       return MSPACK_ERR_DATAFORMAT;
1375     }
1376 
1377     /* open next cab file */
1378     d->incab = d->data->cab;
1379     if (!(d->infh = sys->open(sys, d->incab->base.filename,
1380                               MSPACK_SYS_OPEN_READ)))
1381     {
1382       return MSPACK_ERR_OPEN;
1383     }
1384 
1385     /* seek to start of data blocks */
1386     if (sys->seek(d->infh, d->data->offset, MSPACK_SYS_SEEK_START)) {
1387       return MSPACK_ERR_SEEK;
1388     }
1389   } while (1);
1390 
1391   /* not reached */
1392   return MSPACK_ERR_OK;
1393 }
1394 
cabd_checksum(unsigned char * data,unsigned int bytes,unsigned int cksum)1395 static unsigned int cabd_checksum(unsigned char *data, unsigned int bytes,
1396                                   unsigned int cksum)
1397 {
1398   unsigned int len, ul = 0;
1399 
1400   for (len = bytes >> 2; len--; data += 4) {
1401     cksum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
1402   }
1403 
1404   switch (bytes & 3) {
1405   case 3: ul |= *data++ << 16; /*@fallthrough@*/
1406   case 2: ul |= *data++ <<  8; /*@fallthrough@*/
1407   case 1: ul |= *data;
1408   }
1409   cksum ^= ul;
1410 
1411   return cksum;
1412 }
1413 
1414 /***************************************
1415  * NONED_INIT, NONED_DECOMPRESS, NONED_FREE
1416  ***************************************
1417  * the "not compressed" method decompressor
1418  */
1419 struct noned_state {
1420   struct mspack_system *sys;
1421   struct mspack_file *i;
1422   struct mspack_file *o;
1423   unsigned char *buf;
1424   int bufsize;
1425 };
1426 
noned_init(struct mspack_system * sys,struct mspack_file * in,struct mspack_file * out,int bufsize)1427 static struct noned_state *noned_init(struct mspack_system *sys,
1428                                       struct mspack_file *in,
1429                                       struct mspack_file *out,
1430                                       int bufsize)
1431 {
1432   struct noned_state *state = (struct noned_state *) sys->alloc(sys, sizeof(struct noned_state));
1433   unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) bufsize);
1434   if (state && buf) {
1435     state->sys     = sys;
1436     state->i       = in;
1437     state->o       = out;
1438     state->buf     = buf;
1439     state->bufsize = bufsize;
1440   }
1441   else {
1442     sys->free(buf);
1443     sys->free(state);
1444     state = NULL;
1445   }
1446   return state;
1447 }
1448 
noned_decompress(struct noned_state * s,off_t bytes)1449 static int noned_decompress(struct noned_state *s, off_t bytes) {
1450   int run;
1451   while (bytes > 0) {
1452     run = (bytes > s->bufsize) ? s->bufsize : (int) bytes;
1453     if (s->sys->read(s->i, &s->buf[0], run) != run) return MSPACK_ERR_READ;
1454     if (s->sys->write(s->o, &s->buf[0], run) != run) return MSPACK_ERR_WRITE;
1455     bytes -= run;
1456   }
1457   return MSPACK_ERR_OK;
1458 }
1459 
noned_free(struct noned_state * state)1460 static void noned_free(struct noned_state *state) {
1461   struct mspack_system *sys;
1462   if (state) {
1463     sys = state->sys;
1464     sys->free(state->buf);
1465     sys->free(state);
1466   }
1467 }
1468 
1469 
1470 /***************************************
1471  * CABD_PARAM
1472  ***************************************
1473  * allows a parameter to be set
1474  */
cabd_param(struct mscab_decompressor * base,int param,int value)1475 static int cabd_param(struct mscab_decompressor *base, int param, int value) {
1476   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1477   if (!self) return MSPACK_ERR_ARGS;
1478 
1479   switch (param) {
1480   case MSCABD_PARAM_SEARCHBUF:
1481     if (value < 4) return MSPACK_ERR_ARGS;
1482     self->searchbuf_size = value;
1483     break;
1484   case MSCABD_PARAM_FIXMSZIP:
1485     self->fix_mszip = value;
1486     break;
1487   case MSCABD_PARAM_DECOMPBUF:
1488     if (value < 4) return MSPACK_ERR_ARGS;
1489     self->buf_size = value;
1490     break;
1491   case MSCABD_PARAM_SALVAGE:
1492     self->salvage = value;
1493     break;
1494   default:
1495     return MSPACK_ERR_ARGS;
1496   }
1497   return MSPACK_ERR_OK;
1498 }
1499 
1500 /***************************************
1501  * CABD_ERROR
1502  ***************************************
1503  * returns the last error that occurred
1504  */
cabd_error(struct mscab_decompressor * base)1505 static int cabd_error(struct mscab_decompressor *base) {
1506   struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1507   return (self) ? self->error : MSPACK_ERR_ARGS;
1508 }
1509