X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fzip-reader.c;h=4810ae53378c4dda4b98426f809002c4f1c3ad1e;hb=5dbf5abcbed01f04422d4dead1c0ae0bb7efde4f;hp=56a4c81019d620ce8c43627fa2101d348defc1d4;hpb=ad9374fb26300c7d6c72b358b6ee9f0b6e5b5c87;p=pspp diff --git a/src/libpspp/zip-reader.c b/src/libpspp/zip-reader.c index 56a4c81019..4810ae5337 100644 --- a/src/libpspp/zip-reader.c +++ b/src/libpspp/zip-reader.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,7 @@ stored_finish (struct zip_member *zm UNUSED) } -static struct decompressor decompressors[n_COMPRESSION] = +static struct decompressor decompressors[n_COMPRESSION] = { {stored_init, stored_read, stored_finish}, {inflate_init, inflate_read, inflate_finish} @@ -72,6 +73,7 @@ static enum compression comp_code (struct zip_member *zm, uint16_t c) { enum compression which; + assert (zm->errmsgs); switch (c) { case 0: @@ -81,7 +83,7 @@ comp_code (struct zip_member *zm, uint16_t c) which = COMPRESSION_INFLATE; break; default: - ds_put_format (zm->errs, _("Unsupported compression type (%d)"), c); + ds_put_format (zm->errmsgs, _("Unsupported compression type (%d)"), c); which = n_COMPRESSION; break; } @@ -102,7 +104,7 @@ struct zip_reader void zip_member_finish (struct zip_member *zm) { - ds_clear (zm->errs); + ds_clear (zm->errmsgs); /* Probably not useful, because we would have to read right to the end of the member if (zm->expected_crc != zm->crc) { @@ -119,7 +121,7 @@ void zip_reader_destroy (struct zip_reader *zr) { int i; - if (zr == NULL) + if (zr == NULL) return; fclose (zr->fr); @@ -148,37 +150,50 @@ skip_bytes (FILE *f, size_t n) fseeko (f, n, SEEK_CUR); } +static bool get_bytes (FILE *f, void *x, size_t n) WARN_UNUSED_RESULT; + + /* Read N bytes from F, storing the result in X */ -static void +static bool get_bytes (FILE *f, void *x, size_t n) { - fread (x, 1, n, f); + return (n == fread (x, 1, n, f)); } +static bool get_u32 (FILE *f, uint32_t *v) WARN_UNUSED_RESULT; + + /* Read a 32 bit value from F */ -static void +static bool get_u32 (FILE *f, uint32_t *v) { uint32_t x; - get_bytes (f, &x, sizeof x); + if (!get_bytes (f, &x, sizeof x)) + return false; #ifdef WORDS_BIGENDIAN *v = bswap_32 (x); #else *v = x; #endif + return true; } +static bool get_u16 (FILE *f, uint16_t *v) WARN_UNUSED_RESULT; + + /* Read a 16 bit value from F */ -static void +static bool get_u16 (FILE *f, uint16_t *v) { uint16_t x; - get_bytes (f, &x, sizeof x); + if (!get_bytes (f, &x, sizeof x)) + return false; #ifdef WORDS_BIGENDIAN *v = bswap_16 (x); #else *v = x; #endif + return true; } @@ -189,12 +204,12 @@ check_magic (FILE *f, uint32_t expected, struct string *err) { uint32_t magic; - get_u32 (f, &magic); + if (! get_u32 (f, &magic)) return false; if ((expected != magic)) { ds_put_format (err, - _("Corrupt file at 0x%llx: Expected %"PRIx32"; got %"PRIx32), + _("Corrupt file at 0x%llx: Expected %"PRIx32"; got %"PRIx32), (long long int) ftello (f) - sizeof (uint32_t), expected, magic); return false; @@ -210,7 +225,7 @@ zip_member_read (struct zip_member *zm, void *buf, size_t bytes) { int bytes_read = 0; - ds_clear (zm->errs); + ds_clear (zm->errmsgs); if ( bytes > zm->bytes_unread) bytes = zm->bytes_unread; @@ -230,7 +245,7 @@ zip_member_read (struct zip_member *zm, void *buf, size_t bytes) /* Read a local file header from ZR and add it to ZR's internal array. Returns a pointer to the member read. This pointer belongs to ZR. - If the caller wishes to control it, she should ref it with + If the caller wishes to control it, she should ref it with zip_member_ref. */ static struct zip_member * @@ -240,47 +255,48 @@ zip_header_read_next (struct zip_reader *zr) uint16_t v, nlen, extralen; uint16_t gp, time, date; - + uint16_t clen, diskstart, iattr; uint32_t eattr; uint16_t comp_type; ds_clear (zr->errs); + zm->errmsgs = zr->errs; if ( ! check_magic (zr->fr, MAGIC_SOCD, zr->errs)) return NULL; - get_u16 (zr->fr, &v); + if (! get_u16 (zr->fr, &v)) return NULL; - get_u16 (zr->fr, &v); - get_u16 (zr->fr, &gp); - get_u16 (zr->fr, &comp_type); + if (! get_u16 (zr->fr, &v)) return NULL; + if (! get_u16 (zr->fr, &gp)) return NULL; + if (! get_u16 (zr->fr, &comp_type)) return NULL; zm->compression = comp_code (zm, comp_type); - get_u16 (zr->fr, &time); - get_u16 (zr->fr, &date); - get_u32 (zr->fr, &zm->expected_crc); - get_u32 (zr->fr, &zm->comp_size); - get_u32 (zr->fr, &zm->ucomp_size); - get_u16 (zr->fr, &nlen); - get_u16 (zr->fr, &extralen); - get_u16 (zr->fr, &clen); - get_u16 (zr->fr, &diskstart); - get_u16 (zr->fr, &iattr); - get_u32 (zr->fr, &eattr); - get_u32 (zr->fr, &zm->offset); + if (! get_u16 (zr->fr, &time)) return NULL; + if (! get_u16 (zr->fr, &date)) return NULL; + if (! get_u32 (zr->fr, &zm->expected_crc)) return NULL; + if (! get_u32 (zr->fr, &zm->comp_size)) return NULL; + if (! get_u32 (zr->fr, &zm->ucomp_size)) return NULL; + if (! get_u16 (zr->fr, &nlen)) return NULL; + if (! get_u16 (zr->fr, &extralen)) return NULL; + if (! get_u16 (zr->fr, &clen)) return NULL; + if (! get_u16 (zr->fr, &diskstart)) return NULL; + if (! get_u16 (zr->fr, &iattr)) return NULL; + if (! get_u32 (zr->fr, &eattr)) return NULL; + if (! get_u32 (zr->fr, &zm->offset)) return NULL; zm->name = xzalloc (nlen + 1); - get_bytes (zr->fr, zm->name, nlen); + if (! get_bytes (zr->fr, zm->name, nlen)) return NULL; skip_bytes (zr->fr, extralen); - + zr->members[zr->nm++] = zm; zm->fp = fopen (zr->filename, "rb"); zm->ref_cnt = 1; - zm->errs = zr->errs; + return zm; } @@ -340,15 +356,15 @@ zip_reader_create (const char *filename, struct string *errs) free (zr); return NULL; } - - get_u16 (zr->fr, &disknum); - get_u16 (zr->fr, &disknum); - get_u16 (zr->fr, &zr->n_members); - get_u16 (zr->fr, &total_members); + if (! get_u16 (zr->fr, &disknum)) return NULL; + if (! get_u16 (zr->fr, &disknum)) return NULL; + + if (! get_u16 (zr->fr, &zr->n_members)) return NULL; + if (! get_u16 (zr->fr, &total_members)) return NULL; - get_u32 (zr->fr, ¢ral_dir_length); - get_u32 (zr->fr, ¢ral_dir_start); + if (! get_u32 (zr->fr, ¢ral_dir_length)) return NULL; + if (! get_u32 (zr->fr, ¢ral_dir_start)) return NULL; if ( 0 != fseeko (zr->fr, central_dir_start, SEEK_SET)) { @@ -362,7 +378,7 @@ zip_reader_create (const char *filename, struct string *errs) zr->members = xcalloc (zr->n_members, sizeof (*zr->members)); memset (zr->members, 0, zr->n_members * sizeof (*zr->members)); - zr->filename = strdup (filename); + zr->filename = xstrdup (filename); return zr; } @@ -376,7 +392,7 @@ zip_member_open (struct zip_reader *zr, const char *member) uint16_t v, nlen, extra_len; uint16_t gp, comp_type, time, date; uint32_t ucomp_size, comp_size; - + uint32_t crc; bool new_member = false; char *name = NULL; @@ -401,14 +417,14 @@ zip_member_open (struct zip_reader *zr, const char *member) else zm = NULL; } - + if ( zm == NULL) return NULL; if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET)) { const char *mm = strerror (errno); - ds_put_format (zm->errs, _("Failed to seek to start of member `%s': %s"), zm->name, mm); + ds_put_format (zm->errmsgs, _("Failed to seek to start of member `%s': %s"), zm->name, mm); return NULL; } @@ -417,28 +433,28 @@ zip_member_open (struct zip_reader *zr, const char *member) return NULL; } - get_u16 (zm->fp, &v); - get_u16 (zm->fp, &gp); - get_u16 (zm->fp, &comp_type); + if (! get_u16 (zm->fp, &v)) return NULL; + if (! get_u16 (zm->fp, &gp)) return NULL; + if (! get_u16 (zm->fp, &comp_type)) return NULL; zm->compression = comp_code (zm, comp_type); - get_u16 (zm->fp, &time); - get_u16 (zm->fp, &date); - get_u32 (zm->fp, &crc); - get_u32 (zm->fp, &comp_size); + if (! get_u16 (zm->fp, &time)) return NULL; + if (! get_u16 (zm->fp, &date)) return NULL; + if (! get_u32 (zm->fp, &crc)) return NULL; + if (! get_u32 (zm->fp, &comp_size)) return NULL; - get_u32 (zm->fp, &ucomp_size); - get_u16 (zm->fp, &nlen); - get_u16 (zm->fp, &extra_len); + if (! get_u32 (zm->fp, &ucomp_size)) return NULL; + if (! get_u16 (zm->fp, &nlen)) return NULL; + if (! get_u16 (zm->fp, &extra_len)) return NULL; name = xzalloc (nlen + 1); - get_bytes (zm->fp, name, nlen); + if (! get_bytes (zm->fp, name, nlen)) return NULL; skip_bytes (zm->fp, extra_len); if (strcmp (name, zm->name) != 0) { - ds_put_format (zm->errs, + ds_put_format (zm->errmsgs, _("Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"), zm->name, name); free (name); @@ -449,7 +465,7 @@ zip_member_open (struct zip_reader *zr, const char *member) free (name); zm->bytes_unread = zm->ucomp_size; - + if ( !new_member) decompressors[zm->compression].finish (zm); @@ -501,7 +517,7 @@ find_eocd (FILE *fp, off_t *off) const uint32_t magic = MAGIC_EOCD; bool found = false; - /* The magic cannot be more than 22 bytes from the end of the file, + /* The magic cannot be more than 22 bytes from the end of the file, because that is the minimum length of the EndOfCentralDirectory record. */ @@ -511,7 +527,7 @@ find_eocd (FILE *fp, off_t *off) } start = ftello (fp); stop = start + sizeof (magic); - do + do { found = probe_magic (fp, magic, start, stop, off); /* FIXME: For extra confidence lookup the directory start record here*/ @@ -558,7 +574,7 @@ probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off) state++; else state = 0; - + if ( state == 4) { *off = ftello (fp) - 4;