diff --git a/CHANGES.txt b/CHANGES.txt index 7bacfc2266b50a517c9adf4d351a468f62259cf0..0651b5cb679b3bd26b517e8e603181821ff9cfbf 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -26,6 +26,8 @@ to meta type). (Bug: 2389901). Reported by Barry Grundy. 1/11/09: Update: Lots of bug fixes in HFS code from Rob Joyce. +1/12/09: Bug Fix: Fixed ISO9660 bug where large directory contents were not displayed. (Bug: 2503552). Reported by Tom Black. + ---------------- VERSION 3.0.0 -------------- 0/00/00: Update: Many, many, many API changes. diff --git a/tsk3/fs/iso9660_dent.c b/tsk3/fs/iso9660_dent.c index f0b6a7c28e60f3fd1f7d492aa8d01d5f9738ea05..a07f7944f7e81f1a55007dd24ccd5794b1f825e9 100644 --- a/tsk3/fs/iso9660_dent.c +++ b/tsk3/fs/iso9660_dent.c @@ -76,10 +76,11 @@ uint8_t iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf, - size_t length, TSK_INUM_T a_addr) + size_t a_length, TSK_INUM_T a_addr) { ISO_INFO *iso = (ISO_INFO *) a_fs; TSK_FS_NAME *fs_name; + size_t buf_idx; iso9660_dentry *dd; /* directory descriptor */ iso9660_inode_node *in; @@ -87,7 +88,8 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf, if ((fs_name = tsk_fs_name_alloc(ISO9660_MAXNAMLEN + 1, 0)) == NULL) return TSK_ERR; - dd = (iso9660_dentry *) buf; + buf_idx = 0; + dd = (iso9660_dentry *) & buf[buf_idx]; /* handle "." entry */ fs_name->meta_addr = a_addr; @@ -97,8 +99,13 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf, tsk_fs_dir_add(a_fs_dir, fs_name); - length -= dd->entry_len; - dd = (iso9660_dentry *) ((char *) dd + dd->entry_len); + buf_idx += dd->entry_len; + if (buf_idx > a_length - sizeof(iso9660_dentry)) { + free(buf); + tsk_fs_name_free(fs_name); + return TSK_OK; + } + dd = (iso9660_dentry *) & buf[buf_idx]; /* handle ".." entry */ in = iso->in_list; @@ -115,15 +122,17 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf, tsk_fs_dir_add(a_fs_dir, fs_name); } - length -= dd->entry_len; - dd = (iso9660_dentry *) ((char *) dd + dd->entry_len); + buf_idx += dd->entry_len; // process the rest of the entries in the directory - while (length > sizeof(iso9660_dentry)) { - if (dd->entry_len) { + while (buf_idx < a_length - sizeof(iso9660_dentry)) { + dd = (iso9660_dentry *) & buf[buf_idx]; + + // process the entry (if it has a defined and valid length) + if ((dd->entry_len) && (buf_idx + dd->entry_len < a_length)) { int i; - // find the entry in our list of files + // find the corresponding entry in the inode/file list in = iso->in_list; while ((in) && (tsk_getu32(a_fs->endian, @@ -132,15 +141,15 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf, in = in->next; } + // we may have not found it because we are reading corrupt data... if ((!in) || (tsk_getu32(a_fs->endian, in->inode.dr.ext_loc_m) != tsk_getu32(a_fs->endian, dd->ext_loc_m))) { - // @@@ - return TSK_COR; + buf_idx++; + continue; } - fs_name->meta_addr = in->inum; strncpy(fs_name->name, in->inode.fn, ISO9660_MAXNAMLEN); @@ -160,27 +169,24 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf, tsk_fs_dir_add(a_fs_dir, fs_name); - length -= dd->entry_len; - - dd = (iso9660_dentry *) ((char *) dd + dd->entry_len); - /* we need to look for files past the next NULL we discover, in case - * directory has a hole in it (this is common) */ + buf_idx += dd->entry_len; } + /* If the length was not defined, we are probably in a hole in the + * directory. The contents are block aligned. So, we + * scan ahead until we get either a non-zero entry or the block boundary */ else { - char *a, *b; - length -= sizeof(iso9660_dentry); - - /* find next non-zero byte and we'll start over there */ - a = (char *) dd; - b = a + sizeof(iso9660_dentry); - while ((*a == 0) && (a != b)) - a++; - - if (a != b) { - length += (int) (b - a); - dd = (iso9660_dentry *) ((char *) dd + - (sizeof(iso9660_dentry) - (int) (b - a))); + while (buf_idx < a_length - sizeof(iso9660_dentry)) { + if (buf[buf_idx] != 0) { + dd = (iso9660_dentry *) & buf[buf_idx]; + if ((dd->entry_len) + && (buf_idx + dd->entry_len < a_length)) + break; + } + if (buf_idx % a_fs->block_size == 0) + break; + + buf_idx++; } } } @@ -211,11 +217,9 @@ iso9660_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, { TSK_RETVAL_ENUM retval; TSK_FS_DIR *fs_dir; - TSK_OFF_T offs; /* where we are reading in the file */ ssize_t cnt; char *buf; size_t length; - ISO_INFO *iso = (ISO_INFO *) a_fs; if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) { tsk_error_reset(); @@ -259,12 +263,6 @@ iso9660_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, return TSK_COR; } - - /* calculate directory extent location */ - offs = - (TSK_OFF_T) (a_fs->block_size * - tsk_getu32(a_fs->endian, iso->dinode->dr.ext_loc_m)); - /* read directory extent into memory */ length = (size_t) fs_dir->fs_file->meta->size; if ((buf = tsk_malloc(length)) == NULL)