Make stream_hash() return NULL for unhashed streams
authorEric Biggers <ebiggers3@gmail.com>
Sun, 21 Jan 2018 21:47:10 +0000 (13:47 -0800)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 21 Jan 2018 21:47:10 +0000 (13:47 -0800)
Otherwise it will return a bogus value from the union with ->back_inode
and ->back_stream_id.  Most callers ensured this cannot happen, but a
couple did not.  It should be explicitly prevented or handled.

src/inode.c
src/solid.c
src/test_support.c

index 034b9a1..68e88c0 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /*
- * Copyright (C) 2012, 2013, 2014, 2015 Eric Biggers
+ * Copyright (C) 2012-2018 Eric Biggers
  *
  * This file is free software; you can redistribute it and/or modify it under
  * the terms of the GNU Lesser General Public License as published by the Free
@@ -510,15 +510,25 @@ stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table)
                return lookup_blob(table, strm->_stream_hash);
 }
 
-/* Return the SHA-1 message digest of the data of the specified stream, or a
- * void SHA-1 of all zeroes if the specified stream is empty.   */
+/*
+ * Return the SHA-1 message digest of the data of the specified stream, or a
+ * void SHA-1 of all zeroes if the specified stream is empty, or NULL if the
+ * specified stream is unhashed.  (Most callers ensure the stream cannot be
+ * unhashed.)
+ */
 const u8 *
 stream_hash(const struct wim_inode_stream *strm)
 {
-       if (strm->stream_resolved)
-               return strm->_stream_blob ? strm->_stream_blob->hash : zero_hash;
-       else
+       if (!strm->stream_resolved)
                return strm->_stream_hash;
+
+       if (!strm->_stream_blob)
+               return zero_hash;
+
+       if (strm->_stream_blob->unhashed)
+               return NULL;
+
+       return strm->_stream_blob->hash;
 }
 
 /*
@@ -557,7 +567,9 @@ inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode)
 /*
  * Return the SHA-1 message digest of the unnamed data stream of the inode, or a
  * void SHA-1 of all zeroes if the inode does not have an unnamed data stream or
- * if the inode's unnamed data stream is empty.
+ * if the inode's unnamed data stream is empty, or NULL if the inode's unnamed
+ * data stream is unhashed.  (Most callers ensure the stream cannot be
+ * unhashed.)
  */
 const u8 *
 inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode)
index 2aecf5c..35f2eef 100644 (file)
@@ -139,6 +139,8 @@ dentry_fill_in_solid_sort_names(struct wim_dentry *dentry, void *_blob_table)
        struct blob_descriptor *blob;
 
        hash = inode_get_hash_of_unnamed_data_stream(inode);
+       if (!hash) /* unhashed? */
+               return 0;
        head = &blob_table->table[load_size_t_unaligned(hash) %
                                  blob_table->capacity];
        hlist_for_each_entry(blob, head, hash_list_2) {
index d2fecc8..38cdc1e 100644 (file)
@@ -679,36 +679,6 @@ generate_data(u8 *buffer, size_t size, struct generation_context *ctx)
        }
 }
 
-static int
-add_stream(struct wim_inode *inode, struct generation_context *ctx,
-          int stream_type, const utf16lechar *stream_name,
-          void *buffer, size_t size)
-{
-       struct blob_descriptor *blob = NULL;
-       struct wim_inode_stream *strm;
-
-       if (size) {
-               blob = new_blob_descriptor();
-               if (!blob)
-                       goto err_nomem;
-               blob->attached_buffer = buffer;
-               blob->blob_location = BLOB_IN_ATTACHED_BUFFER;
-               blob->size = size;
-       }
-
-       strm = inode_add_stream(inode, stream_type, stream_name, blob);
-       if (unlikely(!strm))
-               goto err_nomem;
-
-       prepare_unhashed_blob(blob, inode, strm->stream_id,
-                             ctx->params->unhashed_blobs);
-       return 0;
-
-err_nomem:
-       free_blob_descriptor(blob);
-       return WIMLIB_ERR_NOMEM;
-}
-
 static noinline_for_stack int
 set_random_reparse_point(struct wim_inode *inode, struct generation_context *ctx)
 {
@@ -770,6 +740,7 @@ add_random_data_stream(struct wim_inode *inode, struct generation_context *ctx,
 {
        void *buffer = NULL;
        size_t size;
+       int ret;
 
        size = select_stream_size(ctx);
        if (size) {
@@ -779,8 +750,12 @@ add_random_data_stream(struct wim_inode *inode, struct generation_context *ctx,
                generate_data(buffer, size, ctx);
        }
 
-       return add_stream(inode, ctx, STREAM_TYPE_DATA, stream_name,
-                         buffer, size);
+       ret = 0;
+       if (!inode_add_stream_with_data(inode, STREAM_TYPE_DATA, stream_name,
+                                       buffer, size, ctx->params->blob_table))
+               ret = WIMLIB_ERR_NOMEM;
+       FREE(buffer);
+       return ret;
 }
 
 static int