]> wimlib.net Git - wimlib/blobdiff - src/lookup_table.c
read_wim_lookup_table(): Make sure all resources get validated (try 2)
[wimlib] / src / lookup_table.c
index 47f6195a41fd0138ea7e6e28d6f3d35ebb09b13d..59d7c7cfdd55547ef3b4d55a61c1deadf666743c 100644 (file)
@@ -663,19 +663,24 @@ finish_resource(struct wim_resource_spec *rspec)
 }
 
 /*
- * Reads the lookup table from a WIM file.  Each entry specifies a stream that
- * the WIM file contains, along with its location and SHA1 message digest.
+ * Reads the lookup table from a WIM file.  Usually, each entry specifies a
+ * stream that the WIM file contains, along with its location and SHA1 message
+ * digest.
  *
- * Saves lookup table entries for non-metadata streams in a hash table, and
- * saves the metadata entry for each image in a special per-image location (the
- * image_metadata array).
+ * Saves lookup table entries for non-metadata streams in a hash table (set to
+ * wim->lookup_table), and saves the metadata entry for each image in a special
+ * per-image location (the wim->image_metadata array).
  *
- * Return values:
+ * This works for both version WIM_VERSION_DEFAULT (68864) and version
+ * WIM_VERSION_PACKED_STREAMS (3584) WIMs.
+ *
+ * Possible return values:
  *     WIMLIB_ERR_SUCCESS (0)
  *     WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY
- *     WIMLIB_ERR_RESOURCE_NOT_FOUND
+ *     WIMLIB_ERR_NOMEM
  *
- *     Or an error code caused by failure to read the lookup table into memory.
+ *     Or an error code caused by failure to read the lookup table from the WIM
+ *     file.
  */
 int
 read_wim_lookup_table(WIMStruct *wim)
@@ -722,7 +727,6 @@ read_wim_lookup_table(WIMStruct *wim)
                        &((const struct wim_lookup_table_entry_disk*)buf)[i];
                struct wim_reshdr reshdr;
                u16 part_number;
-               struct wim_lookup_table_entry *duplicate_entry;
 
                /* Get the resource header  */
                get_wim_reshdr(&disk_entry->reshdr, &reshdr);
@@ -849,14 +853,13 @@ read_wim_lookup_table(WIMStruct *wim)
                         * Transfer the values to the `struct
                         * wim_resource_spec', and discard the current stream
                         * since this lookup table entry did not, in fact,
-                        * correspond to a "stream".
-                        */
+                        * correspond to a "stream".  */
 
-                       /* Uncompressed size of the resource pack is actually
-                        * stored in the header of the resource itself.  Read
-                        * it, and also grab the chunk size and compression type
-                        * (which are not necessarily the defaults from the WIM
-                        * header).  */
+                       /* The uncompressed size of the packed resource is
+                        * actually stored in the header of the resource itself.
+                        * Read it, and also grab the chunk size and compression
+                        * type (which are not necessarily the defaults from the
+                        * WIM header).  */
                        struct alt_chunk_table_header_disk hdr;
 
                        ret = full_pread(&wim->in_fd, &hdr,
@@ -887,20 +890,26 @@ read_wim_lookup_table(WIMStruct *wim)
                        goto free_cur_entry_and_continue;
                }
 
-               /* Ignore streams with zero hash.  */
+               /* Ignore entries with all zeroes in the hash field.  */
                if (is_zero_hash(cur_entry->hash))
                        goto free_cur_entry_and_continue;
 
                if (reshdr.flags & WIM_RESHDR_FLAG_METADATA) {
+
                        /* Lookup table entry for a metadata resource.  */
 
-                       /* Metadata entries with no references must be ignored;
-                        * see, for example, the WinPE WIMs from the WAIK v2.1.
+                       /* Metadata entries with no references must be ignored.
+                        * See, for example, the WinPE WIMs from the WAIK v2.1.
                         */
                        if (cur_entry->refcnt == 0)
                                goto free_cur_entry_and_continue;
 
                        if (cur_entry->refcnt != 1) {
+                               /* We don't currently support this case due to
+                                * the complications of multiple images sharing
+                                * the same metadata resource or a metadata
+                                * resource also being referenced by files.
+                                */
                                ERROR("Found metadata resource with refcnt != 1");
                                ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
                                goto out;
@@ -911,18 +920,22 @@ read_wim_lookup_table(WIMStruct *wim)
                                        "non-first part of the split WIM");
                                goto free_cur_entry_and_continue;
                        }
+
+                       /* The number of entries in the lookup table with
+                        * WIM_RESHDR_FLAG_METADATA set should be the same as
+                        * the image_count field in the WIM header.  */
                        if (image_index == wim->hdr.image_count) {
                                WARNING("Found more metadata resources than images");
                                goto free_cur_entry_and_continue;
                        }
 
                        /* Notice very carefully:  We are assigning the metadata
-                        * resources in the exact order mirrored by their lookup
-                        * table entries on disk, which is the behavior of
-                        * Microsoft's software.  In particular, this overrides
-                        * the actual locations of the metadata resources
-                        * themselves in the WIM file as well as any information
-                        * written in the XML data.  */
+                        * resources to images in the same order in which their
+                        * lookup table entries occur on disk.  (This is also
+                        * the behavior of Microsoft's software.)  In
+                        * particular, this overrides the actual locations of
+                        * the metadata resources themselves in the WIM file as
+                        * well as any information written in the XML data.  */
                        DEBUG("Found metadata resource for image %"PRIu32" at "
                              "offset %"PRIu64".",
                              image_index + 1,
@@ -930,18 +943,16 @@ read_wim_lookup_table(WIMStruct *wim)
 
                        wim->image_metadata[image_index++]->metadata_lte = cur_entry;
                } else {
-                       /* Lookup table entry for a stream that is not a metadata
-                        * resource.  */
+                       /* Lookup table entry for a non-metadata stream.  */
 
                        /* Ignore this stream if it's a duplicate.  */
-                       duplicate_entry = lookup_stream(table, cur_entry->hash);
-                       if (duplicate_entry) {
+                       if (lookup_stream(table, cur_entry->hash)) {
                                num_duplicate_entries++;
                                goto free_cur_entry_and_continue;
                        }
 
-                       /* Insert the stream into the lookup table (keyed by its
-                        * SHA1 message digest).  */
+                       /* Insert the stream into the in-memory lookup table,
+                        * keyed by its SHA1 message digest.  */
                        lookup_table_insert(table, cur_entry);
                }
 
@@ -963,7 +974,10 @@ read_wim_lookup_table(WIMStruct *wim)
                        cur_entry->offset_in_res = 0;
                        cur_entry->size = reshdr.uncompressed_size;
                        cur_entry->flags = reshdr.flags;
+                       ret = validate_resource(cur_rspec);
                        cur_rspec = NULL;
+                       if (ret)
+                               goto out;
                }
                continue;