zip-reader: Report corrupted Zip archives.
[pspp] / src / libpspp / zip-reader.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2011, 2013, 2014, 2021 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "libpspp/zip-reader.h"
20 #include "libpspp/zip-private.h"
21
22 #include <errno.h>
23 #include <inttypes.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "libpspp/assertion.h"
30 #include "libpspp/cast.h"
31 #include "libpspp/compiler.h"
32 #include "libpspp/integer-format.h"
33 #include "libpspp/str.h"
34
35 #include "gl/crc.h"
36 #include "gl/xalloc.h"
37
38 #include "gettext.h"
39 #define _(msgid) gettext (msgid)
40 #define N_(msgid) (msgid)
41
42 struct zip_member
43 {
44   char *file_name;             /* File name. */
45   char *member_name;          /* Member name. */
46   FILE *fp;                   /* The stream from which the data is read */
47   uint32_t offset;            /* Starting offset in file. */
48   uint32_t comp_size;         /* Length of member file data, in bytes. */
49   uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
50
51   uint32_t expected_crc;
52   uint32_t accumulated_crc;
53
54   const struct decompressor *decompressor;
55
56   size_t bytes_unread;       /* Number of bytes left in the member available for reading */
57   char *error;               /* Error message, if any. */
58   void *aux;
59 };
60
61 struct decompressor
62 {
63   char *(*init) (struct zip_member *);
64   int  (*read) (struct zip_member *, void *, size_t);
65   void (*finish) (struct zip_member *);
66 };
67 static const struct decompressor stored_decompressor;
68 static const struct decompressor inflate_decompressor;
69
70 static bool find_eocd (FILE *fp, off_t *off);
71
72 static const struct decompressor *
73 get_decompressor (uint16_t c)
74 {
75   switch (c)
76     {
77     case 0:
78       return &stored_decompressor;
79
80     case 8:
81       return &inflate_decompressor;
82
83     default:
84       return NULL;
85     }
86 }
87
88 struct zip_reader
89 {
90   int ref_cnt;
91   char *file_name;                  /* The name of the file from which the data is read */
92   uint16_t n_entries;              /* Number of directory entries. */
93   struct zip_entry *entries;       /* Directory entries. */
94 };
95
96 struct zip_entry
97 {
98   uint32_t offset;            /* Starting offset in file. */
99   uint32_t comp_size;         /* Length of member file data, in bytes. */
100   uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
101   uint32_t expected_crc;      /* CRC32 of uncompressed data. */
102   char *name;                 /* Name of member file. */
103 };
104
105 char * WARN_UNUSED_RESULT
106 zip_member_steal_error (struct zip_member *zm)
107 {
108   char *retval = zm->error;
109   zm->error = NULL;
110   return retval;
111 }
112
113 void
114 zip_member_finish (struct zip_member *zm)
115 {
116   if (zm)
117     {
118       free (zm->file_name);
119       free (zm->member_name);
120       zm->decompressor->finish (zm);
121       fclose (zm->fp);
122       free (zm->error);
123       free (zm);
124     }
125 }
126
127 struct zip_reader *
128 zip_reader_ref (const struct zip_reader *zr_)
129 {
130   struct zip_reader *zr = CONST_CAST (struct zip_reader *, zr_);
131   assert (zr->ref_cnt > 0);
132   zr->ref_cnt++;
133   return zr;
134 }
135
136 /* Destroy the zip reader */
137 void
138 zip_reader_unref (struct zip_reader *zr)
139 {
140   if (zr == NULL)
141     return;
142   assert (zr->ref_cnt > 0);
143   if (--zr->ref_cnt)
144     return;
145
146   free (zr->file_name);
147
148   for (int i = 0; i < zr->n_entries; ++i)
149     {
150       struct zip_entry *ze = &zr->entries[i];
151       free (ze->name);
152     }
153   free (zr->entries);
154   free (zr);
155 }
156
157
158 /* Skip N bytes in F */
159 static void
160 skip_bytes (FILE *f, size_t n)
161 {
162   fseeko (f, n, SEEK_CUR);
163 }
164
165 static void
166 get_bytes (FILE *f, void *x, size_t n)
167 {
168   if (!fread (x, n, 1, f))
169     memset (x, 0, n);
170 }
171
172 static uint32_t
173 get_u32 (FILE *f)
174 {
175   uint32_t x;
176   get_bytes (f, &x, sizeof x);
177   return le_to_native32 (x);
178 }
179
180 static uint16_t
181 get_u16 (FILE *f)
182 {
183   uint16_t x;
184   get_bytes (f, &x, sizeof x);
185   return le_to_native16 (x);
186 }
187
188 static char * WARN_UNUSED_RESULT
189 get_stream_error (FILE *f, const char *file_name)
190 {
191   if (feof (f))
192     return xasprintf (_("%s: unexpected end of file"), file_name);
193   else if (ferror (f))
194     {
195       /* The particular error might not be in errno anymore.  Try to find out
196          what the error was. */
197       errno = 0;
198       char x;
199       return (!fread (&x, 1, sizeof x, f) && errno
200               ? xasprintf (_("%s: I/O error reading Zip archive (%s)"),
201                            file_name, strerror (errno))
202               : xasprintf (_("%s: I/O error reading Zip archive"), file_name));
203     }
204   else
205     return NULL;
206 }
207
208 /* Read 32 bit integer and compare it with EXPECTED.
209    place an error string in ERR if necessary. */
210 static char * WARN_UNUSED_RESULT
211 check_magic (FILE *f, const char *file_name, uint32_t expected)
212 {
213   uint32_t magic = get_u32 (f);
214   char *error = get_stream_error (f, file_name);
215   if (error)
216     return error;
217   else if (expected != magic)
218     return xasprintf (_("%s: corrupt archive at 0x%llx: "
219                         "expected %#"PRIx32" but got %#"PRIx32),
220                       file_name,
221                       (long long int) ftello (f) - sizeof (uint32_t),
222                       expected, magic);
223   else
224     return NULL;
225 }
226
227
228 /* Reads upto BYTES bytes from ZM and puts them in BUF.
229    Returns the number of bytes read, or -1 on error */
230 int
231 zip_member_read (struct zip_member *zm, void *buf, size_t bytes)
232 {
233   if (bytes > zm->bytes_unread)
234     bytes = zm->bytes_unread;
235   if (!bytes)
236     return 0;
237
238   int bytes_read = zm->decompressor->read (zm, buf, bytes);
239   if (bytes_read <= 0)
240     return bytes_read;
241
242   zm->bytes_unread -= bytes_read;
243   zm->accumulated_crc = crc32_update (zm->accumulated_crc, buf, bytes_read);
244   if (!zm->bytes_unread && zm->accumulated_crc != zm->expected_crc)
245     {
246       zm->error = xasprintf (_("%s: corrupt archive reading member \"%s\": "
247                                "bad CRC %#"PRIx32" (expected %"PRIx32")"),
248                              zm->file_name, zm->member_name,
249                              zm->accumulated_crc, zm->expected_crc);
250       return -1;
251     }
252
253   return bytes_read;
254 }
255
256 /* Read all of ZM into memory, storing the data in *DATAP and its size in *NP.
257    Returns NULL if successful, otherwise an error string that the caller
258    must eventually free(). */
259 char * WARN_UNUSED_RESULT
260 zip_member_read_all (struct zip_reader *zr, const char *member_name,
261                      void **datap, size_t *np)
262 {
263   struct zip_member *zm;
264   char *error = zip_member_open (zr, member_name, &zm);
265   if (error)
266     {
267       *datap = NULL;
268       *np = 0;
269       return error;
270     }
271
272   *datap = xmalloc (zm->ucomp_size);
273   *np = zm->ucomp_size;
274
275   uint8_t *data = *datap;
276   while (zm->bytes_unread)
277     if (zip_member_read (zm, data + (zm->ucomp_size - zm->bytes_unread),
278                          zm->bytes_unread) == -1)
279       {
280         char *error = zip_member_steal_error (zm);
281         zip_member_finish (zm);
282         free (*datap);
283         *datap = NULL;
284         *np = 0;
285         return error;
286       }
287
288   zip_member_finish (zm);
289   return NULL;
290 }
291
292 /* Read a central directory header from FILE and initializes ZE with it.
293    Returns true if successful, false otherwise.  On error, appends error
294    messages to ERRS. */
295 static char * WARN_UNUSED_RESULT
296 zip_header_read_next (FILE *file, const char *file_name,
297                       struct zip_entry *ze)
298 {
299   char *error = check_magic (file, file_name, MAGIC_SOCD);
300   if (error)
301     return error;
302
303   get_u16 (file);       /* v */
304   get_u16 (file);       /* v */
305   get_u16 (file);       /* gp */
306   get_u16 (file);       /* comp_type */
307   get_u16 (file);       /* time */
308   get_u16 (file);       /* date */
309   ze->expected_crc = get_u32 (file);
310   ze->comp_size = get_u32 (file);
311   ze->ucomp_size = get_u32 (file);
312   uint16_t nlen = get_u16 (file);
313   uint16_t extralen = get_u16 (file);
314   get_u16 (file);       /* clen */
315   get_u16 (file);       /* diskstart */
316   get_u16 (file);       /* iattr */
317   get_u32 (file);       /* eattr */
318   ze->offset = get_u32 (file);
319
320   error = get_stream_error (file, file_name);
321   if (error)
322     return error;
323
324   ze->name = xzalloc (nlen + 1);
325   get_bytes (file, ze->name, nlen);
326   error = get_stream_error (file, file_name);
327   if (error)
328     return error;
329
330   skip_bytes (file, extralen);
331
332   return NULL;
333 }
334
335
336 /* Create a reader from the zip called FILE_NAME */
337 char * WARN_UNUSED_RESULT
338 zip_reader_create (const char *file_name, struct zip_reader **zrp)
339 {
340   *zrp = NULL;
341
342   FILE *file = fopen (file_name, "rb");
343   if (!file)
344     return xasprintf (_("%s: open failed (%s)"), file_name, strerror (errno));
345
346   /* Check the Zip file magic. */
347   char *error = check_magic (file, file_name, MAGIC_LHDR);
348   if (error)
349     {
350       fclose (file);
351       return error;
352     }
353
354   /* Find end of central directory record and read it. */
355   off_t offset = 0;
356   if (! find_eocd (file, &offset))
357     {
358       fclose (file);
359       return xasprintf (_("%s: cannot find central directory"), file_name);
360     }
361   if (0 != fseeko (file, offset, SEEK_SET))
362     {
363       error = xasprintf (_("%s: seek failed (%s)"),
364                          file_name, strerror (errno));
365       fclose (file);
366       return error;
367     }
368   error = check_magic (file, file_name, MAGIC_EOCD);
369   if (error)
370     {
371       fclose (file);
372       return error;
373     }
374   get_u16 (file);               /* disknum */
375   get_u16 (file);               /* disknum */
376   uint16_t n_members = get_u16 (file);
377   get_u16 (file);               /* total_members */
378   get_u32 (file);               /* central_dir_length */
379   uint32_t central_dir_start = get_u32 (file);
380   error = get_stream_error (file, file_name);
381   if (error)
382     {
383       fclose (file);
384       return error;
385     }
386
387   /* Read central directory. */
388   if (0 != fseeko (file, central_dir_start, SEEK_SET))
389     {
390       error = xasprintf (_("%s: seek failed (%s)"),
391                          file_name, strerror (errno));
392       fclose (file);
393       return NULL;
394     }
395
396   struct zip_reader *zr = XZALLOC (struct zip_reader);
397   zr->ref_cnt = 1;
398   zr->file_name = xstrdup (file_name);
399   zr->entries = xcalloc (n_members, sizeof *zr->entries);
400   for (int i = 0; i < n_members; i++)
401     {
402       error = zip_header_read_next (file, file_name,
403                                     &zr->entries[zr->n_entries]);
404       if (error)
405         {
406           fclose (file);
407           zip_reader_unref (zr);
408           return error;
409         }
410       zr->n_entries++;
411     }
412
413   fclose (file);
414
415   *zrp = zr;
416   return NULL;
417 }
418
419 static struct zip_entry *
420 zip_entry_find (const struct zip_reader *zr, const char *member)
421 {
422   for (int i = 0; i < zr->n_entries; ++i)
423     {
424       struct zip_entry *ze = &zr->entries[i];
425       if (0 == strcmp (ze->name, member))
426         return ze;
427     }
428   return NULL;
429 }
430
431 const char *
432 zip_reader_get_member_name(const struct zip_reader *zr, size_t idx)
433 {
434   return idx < zr->n_entries ? zr->entries[idx].name : NULL;
435 }
436
437 /* Returns true if ZR contains a member named MEMBER, false otherwise. */
438 bool
439 zip_reader_contains_member (const struct zip_reader *zr, const char *member)
440 {
441   return zip_entry_find (zr, member) != NULL;
442 }
443
444 /* Return the member called MEMBER from the reader ZR  */
445 char * WARN_UNUSED_RESULT
446 zip_member_open (struct zip_reader *zr, const char *member,
447                  struct zip_member **zmp)
448 {
449   *zmp = NULL;
450
451   struct zip_entry *ze = zip_entry_find (zr, member);
452   if (ze == NULL)
453     return xasprintf (_("%s: unknown member \"%s\""),
454                         zr->file_name, member);
455
456   FILE *fp = fopen (zr->file_name, "rb");
457   if (!fp)
458     return xasprintf ( _("%s: open failed (%s)"),
459                        zr->file_name, strerror (errno));
460
461   struct zip_member *zm = xmalloc (sizeof *zm);
462   *zm = (struct zip_member) {
463     .file_name = xstrdup (zr->file_name),
464     .member_name = xstrdup (member),
465     .fp = fp,
466     .offset = ze->offset,
467     .comp_size = ze->comp_size,
468     .ucomp_size = ze->ucomp_size,
469     .bytes_unread = ze->ucomp_size,
470     .expected_crc = ze->expected_crc,
471   };
472
473   char *error;
474   if (0 != fseeko (zm->fp, zm->offset, SEEK_SET))
475     {
476       error = xasprintf (_("%s: seek failed (%s)"),
477                          ze->name, strerror (errno));
478       goto error;
479     }
480
481   error = check_magic (zm->fp, zr->file_name, MAGIC_LHDR);
482   if (error)
483     goto error;
484
485   get_u16 (zm->fp);             /* v */
486   get_u16 (zm->fp);             /* gp */
487   uint16_t comp_type = get_u16 (zm->fp);
488   zm->decompressor = get_decompressor (comp_type);
489   if (!zm->decompressor)
490     {
491       error = xasprintf (_("%s: member \"%s\" has unknown compression "
492                            "type %"PRIu16),
493                          zr->file_name, zm->member_name, comp_type);
494       goto error;
495     }
496   get_u16 (zm->fp);             /* time */
497   get_u16 (zm->fp);             /* date */
498   get_u32 (zm->fp);             /* crc */
499   get_u32 (zm->fp);             /* comp_size */
500   get_u32 (zm->fp);             /* ucomp_size */
501   uint16_t nlen = get_u16 (zm->fp);
502   uint16_t extra_len = get_u16 (zm->fp);
503   error = get_stream_error (zm->fp, zr->file_name);
504   if (error)
505     goto error;
506
507   char *name = xzalloc (nlen + 1);
508   get_bytes (zm->fp, name, nlen);
509   error = get_stream_error (zm->fp, zr->file_name);
510   if (error)
511     goto error;
512   if (strcmp (name, ze->name) != 0)
513     {
514       error = xasprintf (_("%s: name mismatch between central directory (%s) "
515                            "and local file header (%s)"),
516                          zm->file_name, ze->name, name);
517       free (name);
518       goto error;
519     }
520   free (name);
521
522   skip_bytes (zm->fp, extra_len);
523
524   error = zm->decompressor->init (zm);
525   if (error)
526     goto error;
527
528   *zmp = zm;
529   return NULL;
530
531 error:
532   fclose (zm->fp);
533   free (zm->file_name);
534   free (zm->member_name);
535   free (zm);
536   return error;
537 }
538
539 \f
540
541 static bool probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off);
542
543
544 /* Search for something that looks like the End Of Central Directory in FP.
545    If found, the offset of the record will be placed in OFF.
546    Returns true if found false otherwise.
547 */
548 static bool
549 find_eocd (FILE *fp, off_t *off)
550 {
551   off_t start, stop;
552   const uint32_t magic = MAGIC_EOCD;
553   bool found = false;
554
555   /* The magic cannot be more than 22 bytes from the end of the file,
556      because that is the minimum length of the EndOfCentralDirectory
557      record.
558    */
559   if (0 > fseeko (fp, -22, SEEK_END))
560     {
561       return false;
562     }
563   start = ftello (fp);
564   stop = start + sizeof (magic);
565   do
566     {
567       found = probe_magic (fp, magic, start, stop, off);
568       /* FIXME: For extra confidence lookup the directory start record here*/
569       if (start == 0)
570         break;
571       stop = start + sizeof (magic);
572       start >>= 1;
573     }
574   while (!found);
575
576   return found;
577 }
578
579
580 /*
581   Search FP for MAGIC starting at START and reaching until STOP.
582   Returns true iff MAGIC is found.  False otherwise.
583   OFF receives the location of the magic.
584 */
585 static bool
586 probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off)
587 {
588   int i;
589   int state = 0;
590   unsigned char seq[4];
591   unsigned char byte;
592
593   if (0 > fseeko (fp, start, SEEK_SET))
594     {
595       return false;
596     }
597
598   for (i = 0; i < 4 ; ++i)
599     {
600       seq[i] = (magic >> i * 8) & 0xFF;
601     }
602
603   do
604     {
605       if (1 != fread (&byte, 1, 1, fp))
606         break;
607
608       if (byte == seq[state])
609         state++;
610       else
611         state = 0;
612
613       if (state == 4)
614         {
615           *off = ftello (fp) - 4;
616           return true;
617         }
618       start++;
619       if (start >= stop)
620         break;
621     }
622   while (!feof (fp));
623
624   return false;
625 }
626 \f
627 /* Null decompressor. */
628
629 static int
630 stored_read (struct zip_member *zm, void *buf, size_t n)
631 {
632   size_t bytes_read = fread (buf, 1, n, zm->fp);
633   if (!bytes_read && !zm->error)
634     zm->error = get_stream_error (zm->fp, zm->file_name);
635   return bytes_read;
636 }
637
638 static char *
639 stored_init (struct zip_member *zm UNUSED)
640 {
641   return NULL;
642 }
643
644 static void
645 stored_finish (struct zip_member *zm UNUSED)
646 {
647   /* Nothing required */
648 }
649
650 static const struct decompressor stored_decompressor =
651   {stored_init, stored_read, stored_finish};
652 \f
653 /* Inflate decompressor. */
654
655 #undef crc32
656 #include <zlib.h>
657
658 #define UCOMPSIZE 4096
659
660 struct inflator
661 {
662   z_stream zss;
663   int state;
664   unsigned char ucomp[UCOMPSIZE];
665   size_t bytes_uncomp;
666   size_t ucomp_bytes_read;
667
668   /* Two bitfields as defined by RFC1950 */
669   uint16_t cmf_flg ;
670 };
671
672 static void
673 inflate_finish (struct zip_member *zm)
674 {
675   struct inflator *inf = zm->aux;
676
677   inflateEnd (&inf->zss);
678
679   free (inf);
680 }
681
682 static char *
683 inflate_init (struct zip_member *zm)
684 {
685   int r;
686   struct inflator *inf = XZALLOC (struct inflator);
687
688   uint16_t flg = 0 ;
689   uint16_t cmf = 0x8; /* Always 8 for inflate */
690
691   const uint16_t cinfo = 7;  /* log_2(Window size) - 8 */
692
693   cmf |= cinfo << 4;     /* Put cinfo into the high nibble */
694
695   /* make these into a 16 bit word */
696   inf->cmf_flg = (cmf << 8) | flg;
697
698   /* Set the check bits */
699   inf->cmf_flg += 31 - (inf->cmf_flg % 31);
700   assert (inf->cmf_flg % 31 == 0);
701
702   inf->zss.next_in = Z_NULL;
703   inf->zss.avail_in = 0;
704   inf->zss.zalloc = Z_NULL;
705   inf->zss.zfree  = Z_NULL;
706   inf->zss.opaque = Z_NULL;
707   r = inflateInit (&inf->zss);
708
709   if (Z_OK != r)
710     return xasprintf (_("%s: cannot initialize inflator (%s)"),
711                       zm->file_name, zError (r));
712
713   zm->aux = inf;
714
715   return NULL;
716 }
717
718 static int
719 inflate_read (struct zip_member *zm, void *buf, size_t n)
720 {
721   int r;
722   struct inflator *inf = zm->aux;
723
724   if (inf->zss.avail_in == 0)
725     {
726       int bytes_read;
727       int bytes_to_read;
728       int pad = 0;
729
730       if (inf->state == 0)
731         {
732           inf->ucomp[1] = inf->cmf_flg ;
733           inf->ucomp[0] = inf->cmf_flg >> 8 ;
734
735           pad = 2;
736           inf->state++;
737         }
738
739       bytes_to_read = zm->comp_size - inf->ucomp_bytes_read;
740
741       if (bytes_to_read == 0)
742         return 0;
743
744       if (bytes_to_read > UCOMPSIZE)
745         bytes_to_read = UCOMPSIZE;
746
747       bytes_read = fread (inf->ucomp + pad, 1, bytes_to_read - pad, zm->fp);
748       if (!bytes_read && !zm->error)
749         {
750           zm->error = get_stream_error (zm->fp, zm->file_name);
751           return -1;
752         }
753
754       inf->ucomp_bytes_read += bytes_read;
755
756       inf->zss.avail_in = bytes_read + pad;
757       inf->zss.next_in = inf->ucomp;
758     }
759   inf->zss.avail_out = n;
760   inf->zss.next_out = buf;
761
762   r = inflate (&inf->zss, Z_NO_FLUSH);
763   if (Z_OK == r)
764     {
765       return n - inf->zss.avail_out;
766     }
767
768   if (!zm->error)
769     zm->error = xasprintf (_("%s: error inflating \"%s\" (%s)"),
770                            zm->file_name, zm->member_name, zError (r));
771
772   return -1;
773 }
774
775 static const struct decompressor inflate_decompressor =
776   {inflate_init, inflate_read, inflate_finish};
777