From 1d4211457b5a3576353d325e3dbf7e7c745dd90c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 21 Jan 2018 13:47:10 -0800 Subject: [PATCH] Make stream_hash() return NULL for unhashed streams 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 | 26 +++++++++++++++++++------- src/solid.c | 2 ++ src/test_support.c | 39 +++++++-------------------------------- 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/inode.c b/src/inode.c index 034b9a11..68e88c05 100644 --- a/src/inode.c +++ b/src/inode.c @@ -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) diff --git a/src/solid.c b/src/solid.c index 2aecf5c9..35f2eef0 100644 --- a/src/solid.c +++ b/src/solid.c @@ -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) { diff --git a/src/test_support.c b/src/test_support.c index d2fecc82..38cdc1ea 100644 --- a/src/test_support.c +++ b/src/test_support.c @@ -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 -- 2.43.0