From 93f86406278ed2799417213d0bb8f1f4baaaff35 Mon Sep 17 00:00:00 2001
From: Joel Uckelman <juckelman@strozfriedberg.co.uk>
Date: Thu, 13 Feb 2020 11:23:57 +0000
Subject: [PATCH] Fix HFS incorrect catalog record length checks.

HFS catalog records are variable length. The checks introduced in
f9e8cbc0 ("Fix for heap OOB memory read issue 1076") and 218a868e ("Check
that the allocated node is large enough to be treated as a
hfs_btree_key_cat.") incorrectly assume that all catalog records have
the maximum possible length, and thus halt processing of a node when
there is still sufficient space for catalog records which are shorter.
This results in many catalog records being missed during filesystem
walks.
---
 tsk/fs/hfs.c | 28 ++++------------------------
 1 file changed, 4 insertions(+), 24 deletions(-)

diff --git a/tsk/fs/hfs.c b/tsk/fs/hfs.c
index fede915bd..22618534e 100644
--- a/tsk/fs/hfs.c
+++ b/tsk/fs/hfs.c
@@ -835,20 +835,10 @@ hfs_cat_traverse(HFS_INFO * hfs,
                     return 1;
                 }
 
-                if (sizeof(hfs_btree_key_cat) > nodesize - rec_off) {
-                    tsk_error_set_errno(TSK_ERR_FS_GENFS);
-                    tsk_error_set_errstr
-                    ("hfs_cat_traverse: record %d in index node %d truncated",
-                        rec, cur_node);
-                    free(node);
-                    return 1;
-                }
-
                 key = (hfs_btree_key_cat *) & node[rec_off];
-
                 keylen = 2 + tsk_getu16(hfs->fs_info.endian, key->key_len);
-               
-                if (keylen >= nodesize - rec_off) {
+
+                if (keylen > nodesize - rec_off) {
                     tsk_error_set_errno(TSK_ERR_FS_GENFS);
                     tsk_error_set_errstr
                         ("hfs_cat_traverse: length of key %d in index node %d too large (%d vs %"
@@ -857,7 +847,6 @@ hfs_cat_traverse(HFS_INFO * hfs,
                     return 1;
                 }
 
-
                 /*
                    if (tsk_verbose)
                    tsk_fprintf(stderr,
@@ -956,19 +945,10 @@ hfs_cat_traverse(HFS_INFO * hfs,
                     return 1;
                 }
 
-                if (sizeof(hfs_btree_key_cat) > nodesize - rec_off) {
-                    tsk_error_set_errno(TSK_ERR_FS_GENFS);
-                    tsk_error_set_errstr
-                    ("hfs_cat_traverse: record %d in leaf node %d truncated",
-                        rec, cur_node);
-                    free(node);
-                    return 1;
-                }
-
                 key = (hfs_btree_key_cat *) & node[rec_off];
-
                 keylen = 2 + tsk_getu16(hfs->fs_info.endian, key->key_len);
-                if ((keylen) > nodesize) {
+
+                if (keylen > nodesize - rec_off) {
                     tsk_error_set_errno(TSK_ERR_FS_GENFS);
                     tsk_error_set_errstr
                         ("hfs_cat_traverse: length of key %d in leaf node %d too large (%d vs %"
-- 
GitLab