[Mesa-dev] [PATCH v2 2/5] disk_cache: enable limited hash collision detection in release builds

Timothy Arceri tarceri at itsqueeze.com
Wed Aug 23 06:32:58 UTC 2017


It really doesn't cost us much and will stop strange crashes should
the stars align.
---
 src/util/disk_cache.c | 26 ++++++++++----------------
 1 file changed, 10 insertions(+), 16 deletions(-)

diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c
index 644a911e53..2df49cf626 100644
--- a/src/util/disk_cache.c
+++ b/src/util/disk_cache.c
@@ -981,63 +981,55 @@ inflate_cache_data(uint8_t *in_data, size_t in_data_size,
 }
 
 void *
 disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
 {
    int fd = -1, ret;
    struct stat sb;
    char *filename = NULL;
    uint8_t *data = NULL;
    uint8_t *uncompressed_data = NULL;
+   uint8_t *file_header = NULL;
 
    if (size)
       *size = 0;
 
    filename = get_cache_file(cache, key);
    if (filename == NULL)
       goto fail;
 
    fd = open(filename, O_RDONLY | O_CLOEXEC);
    if (fd == -1)
       goto fail;
 
    if (fstat(fd, &sb) == -1)
       goto fail;
 
    data = malloc(sb.st_size);
    if (data == NULL)
       goto fail;
 
    size_t ck_size = cache->driver_keys_blob_size;
-#ifndef NDEBUG
-   uint8_t *file_header = malloc(ck_size);
+   file_header = malloc(ck_size);
    if (!file_header)
       goto fail;
 
-   assert(sb.st_size > ck_size);
-   ret = read_all(fd, file_header, ck_size);
-   if (ret == -1) {
-      free(file_header);
+   if (sb.st_size < ck_size)
       goto fail;
-   }
-
-   assert(memcmp(cache->driver_keys_blob, file_header, ck_size) == 0);
 
-   free(file_header);
-#else
-   /* The cache keys are currently just used for distributing precompiled
-    * shaders, they are not used by Mesa so just skip them for now.
-    */
-   ret = lseek(fd, ck_size, SEEK_CUR);
+   ret = read_all(fd, file_header, ck_size);
    if (ret == -1)
       goto fail;
-#endif
+
+   /* Check for extremely unlikely hash collisions */
+   if (memcmp(cache->driver_keys_blob, file_header, ck_size) != 0)
+      goto fail;
 
    /* Load the CRC that was created when the file was written. */
    struct cache_entry_file_data cf_data;
    size_t cf_data_size = sizeof(cf_data);
    ret = read_all(fd, &cf_data, cf_data_size);
    if (ret == -1)
       goto fail;
 
    /* Load the actual cache data. */
    size_t cache_data_size = sb.st_size - cf_data_size - ck_size;
@@ -1065,20 +1057,22 @@ disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
 
    return uncompressed_data;
 
  fail:
    if (data)
       free(data);
    if (uncompressed_data)
       free(uncompressed_data);
    if (filename)
       free(filename);
+   if (file_header)
+      free(file_header);
    if (fd != -1)
       close(fd);
 
    return NULL;
 }
 
 void
 disk_cache_put_key(struct disk_cache *cache, const cache_key key)
 {
    const uint32_t *key_chunk = (const uint32_t *) key;
-- 
2.13.4



More information about the mesa-dev mailing list