diff --git a/tsk/fs/iso9660.c b/tsk/fs/iso9660.c
index 5fa9e313c74084d597ae29449cc574c6221dec7d..f171ad0f975fa96aa3ca3fcc068593c4c44c3525 100644
--- a/tsk/fs/iso9660.c
+++ b/tsk/fs/iso9660.c
@@ -110,20 +110,25 @@ parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
         return NULL;
     }
 
-    while (buf < end) {
+    while ((uintptr_t)buf + sizeof(iso9660_susp_head) <= (uintptr_t)end) {
         iso9660_susp_head *head = (iso9660_susp_head *) buf;
 
-        if (((uintptr_t) & (head->len) >= (uintptr_t) end) ||
-            (buf + head->len - 1 > end))
+        if (buf + head->len - 1 > end)
             break;
 
         /* Identify the entry type -- listed in the order
          * that they are listed in the specs */
 
-        // SUSP Continuation Entry -- NOT SUPPORTED
+        // SUSP Continuation Entry 
         if ((head->sig[0] == 'C') && (head->sig[1] == 'E')) {
             iso9660_susp_ce *ce = (iso9660_susp_ce *) buf;
 
+            if ((uintptr_t)buf + sizeof(iso9660_susp_ce) > (uintptr_t)end) {
+                if (tsk_verbose) 
+                    tsk_fprintf(stderr, "parse_susp: not enough room for CE structure\n");
+                break;
+            }
+
             if (hFile) {
                 fprintf(hFile, "CE Entry\n");
                 fprintf(hFile, "* Block: %" PRIu32 "\n",
@@ -134,6 +139,7 @@ parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
                     tsk_getu32(fs->endian, ce->celen_m));
             }
 
+            // read the continued buffer and parse it
             if ((tsk_getu32(fs->endian, ce->blk_m) < fs->last_block) &&
                 (tsk_getu32(fs->endian, ce->offset_m) < fs->block_size)) {
                 ssize_t cnt;
@@ -238,6 +244,13 @@ parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
         /* POSIX file attributes */
         else if ((head->sig[0] == 'P') && (head->sig[1] == 'X')) {
             iso9660_rr_px_entry *rr_px;
+
+            if ((uintptr_t)buf + sizeof(iso9660_rr_px_entry) > (uintptr_t)end) {
+                if (tsk_verbose) 
+                    tsk_fprintf(stderr, "parse_susp: not enough room for POSIX structure\n");
+                break;
+            }
+
             rr_px = (iso9660_rr_px_entry *) buf;
             rr->uid = tsk_getu32(fs->endian, rr_px->uid_m);
             rr->gid = tsk_getu32(fs->endian, rr_px->gid_m);
@@ -277,7 +290,21 @@ parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
         // RR -- alternative name
         else if ((head->sig[0] == 'N') && (head->sig[1] == 'M')) {
             iso9660_rr_nm_entry *rr_nm;
+
+            if ((uintptr_t)buf + sizeof(iso9660_rr_nm_entry) > (uintptr_t)end) {
+                if (tsk_verbose) 
+                    tsk_fprintf(stderr, "parse_susp: not enough room for RR alternative name structure\n");
+                break;
+            }
+
             rr_nm = (iso9660_rr_nm_entry *) buf;
+
+            if ((uintptr_t)&rr_nm->name[0] + (int) rr_nm->len - 5 > (uintptr_t)end) {
+                if (tsk_verbose) 
+                    tsk_fprintf(stderr, "parse_susp: not enough room for RR alternative name\n");
+                break;
+            }
+
             strncpy(rr->fn, &rr_nm->name[0], (int) rr_nm->len - 5);
             rr->fn[(int) rr_nm->len - 5] = '\0';
             if (hFile) {
@@ -406,10 +433,9 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
             return -1;
         }
 
-        // @@@@ We  need to add more checks when reading from buf to make sure b_off is still in the buffer
         /* process the directory entries */
         for (b_offs = 0; b_offs < ISO9660_SSIZE_B;) {
-            iso9660_inode_node *in_node;
+            iso9660_inode_node *in_node = NULL;
             iso9660_dentry *dentry;
 
             dentry = (iso9660_dentry *) & buf[b_offs];
@@ -418,6 +444,19 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                 b_offs += 2;
                 continue;
             }
+            // sanity checks on entry_len
+            else if (dentry->entry_len < sizeof(iso9660_dentry)) {
+                if (tsk_verbose)
+                    tsk_fprintf(stderr,
+                                "iso9660_load_inodes_dir: entry length is shorter than dentry, bailing\n");
+                break;
+            }
+            else if (b_offs + dentry->entry_len > ISO9660_SSIZE_B) {
+                if (tsk_verbose)
+                    tsk_fprintf(stderr,
+                                "iso9660_load_inodes_dir: entry is longer than sector, bailing\n");
+                break;
+            }
 
             /* when processing the other volume descriptor directories, we ignore the
              * directories because we have no way of detecting if it is a duplicate of
@@ -435,16 +474,27 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                 return -1;
             }
 
-            // the first entry should have no name and is for the current directory
+            // the first entry is for the current directory
             if ((i == 0) && (b_offs == 0)) {
-                if (dentry->fi_len != 0) {
-                    // XXX
+                // should have no name or '.'
+                if (dentry->fi_len > 1) {
+                    if (tsk_verbose)
+                        tsk_fprintf(stderr,
+                                    "iso9660_load_inodes_dir: first entry has name length > 1\n");
+                    free(in_node);
+                    in_node = NULL;
+                    b_offs += dentry->entry_len;
+                    continue;
                 }
 
                 /* find how many more sectors are in the directory */
                 s_cnt =
                     tsk_getu32(fs->endian,
                     dentry->data_len_m) / ISO9660_SSIZE_B;
+                if (tsk_verbose)
+                    tsk_fprintf(stderr, "iso9660_load_inodes_dir: %d number of additional sectors\n", s_cnt);
+                
+                // @@@ Should have a sanity check here on s_cnt, but I'm not sure what it would be...
 
                 /* use the specified name instead of "." */
                 if (strlen(a_fn) > ISO9660_MAXNAMLEN_STD) {
@@ -454,8 +504,7 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                         ("iso9660_load_inodes_dir: Name argument specified is too long");
                     return -1;
                 }
-                strncpy(in_node->inode.fn, a_fn,
-                    ISO9660_MAXNAMLEN_STD + 1);
+                strncpy(in_node->inode.fn, a_fn, ISO9660_MAXNAMLEN_STD + 1);
 
                 /* for all directories except the root, we skip processing the "." and ".." entries because
                  * they duplicate the other entires and the dent_walk code will rely on the offset
@@ -471,13 +520,20 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
             }
             else {
                 char *file_ver;
-
+                
                 // the entry has a UTF-16 name
                 if (ctype == ISO9660_CTYPE_UTF16) {
                     UTF16 *name16;
                     UTF8 *name8;
                     int retVal;
 
+                    if (dentry->entry_len < sizeof(iso9660_dentry) + dentry->fi_len) {
+                        if (tsk_verbose)
+                            tsk_fprintf(stderr,
+                                        "iso9660_load_inodes_dir: UTF-16 name length is too large, bailing\n");
+                        break;
+                    }
+
                     name16 =
                         (UTF16 *) & buf[b_offs + sizeof(iso9660_dentry)];
                     // the name is in UTF-16 BE -- convert to LE if needed
@@ -485,8 +541,8 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                         int a;
 
                         for (a = 0; a < dentry->fi_len / 2; a++) {
-                            name16[i] = ((name16[i] & 0xff) << 8) +
-                                ((name16[i] & 0xff00) >> 8);
+                            name16[a] = ((name16[a] & 0xff) << 8) +
+                                ((name16[a] & 0xff00) >> 8);
                         }
                     }
                     name8 = (UTF8 *) in_node->inode.fn;
@@ -515,6 +571,14 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                     readlen = dentry->fi_len;
                     if (readlen > ISO9660_MAXNAMLEN_STD)
                         readlen = ISO9660_MAXNAMLEN_STD;
+                    
+                    if (dentry->entry_len < sizeof(iso9660_dentry) + dentry->fi_len) {
+                        if (tsk_verbose)
+                            tsk_fprintf(stderr,
+                                        "iso9660_load_inodes_dir: ASCII name length is too large, bailing\n");
+                        break;
+                    }
+
 
                     memcpy(in_node->inode.fn,
                         &buf[b_offs + sizeof(iso9660_dentry)], readlen);
@@ -541,15 +605,47 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                     '.')
                     in_node->inode.fn[strlen(in_node->inode.fn) - 1] =
                         '\0';
+                
+                
+                if (strlen(in_node->inode.fn) == 0) {
+                    if (tsk_verbose)
+                        tsk_fprintf(stderr,
+                                    "iso9660_load_inodes_dir: length of name after processing is 0. bailing\n");
+                    break;
+                    
+                }
             }
 
+            
 
             // copy the raw dentry data into the node
             memcpy(&(in_node->inode.dr), dentry, sizeof(iso9660_dentry));
 
             in_node->inode.ea = NULL;
+
+            // sanity checks
+            if (tsk_getu32(fs->endian, dentry->ext_loc_m) > fs->last_block) {
+                if (tsk_verbose)
+                    tsk_fprintf(stderr,
+                                "iso9660_load_inodes_dir: file starts past end of image (%"PRIu32"). bailing\n",
+                                tsk_getu32(fs->endian, dentry->ext_loc_m));
+                break;
+            }
             in_node->offset =
                 tsk_getu32(fs->endian, dentry->ext_loc_m) * fs->block_size;
+            
+            if (tsk_getu32(fs->endian, in_node->inode.dr.data_len_m) + in_node->offset > fs->last_block * fs->block_size) {
+                if (tsk_verbose)
+                    tsk_fprintf(stderr,
+                                "iso9660_load_inodes_dir: file ends past end of image (%"PRIu32" bytes). bailing\n",
+                                tsk_getu32(fs->endian, in_node->inode.dr.data_len_m) + in_node->offset);
+                break;
+            }
+            /* record size to make sure fifos show up as unique files */
+            in_node->size =
+                tsk_getu32(fs->endian, in_node->inode.dr.data_len_m);
+
+            
             in_node->ea_size = dentry->ext_len;
             in_node->dentry_offset = s_offs + b_offs;
 
@@ -558,9 +654,6 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
             else
                 in_node->inode.is_orphan = 1;
 
-            /* record size to make sure fifos show up as unique files */
-            in_node->size =
-                tsk_getu32(fs->endian, in_node->inode.dr.data_len_m);
             in_node->inum = count++;
 
             /* RockRidge data is located after the name.  See if it is there.  */
@@ -574,17 +667,20 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                     parse_susp(fs,
                     &buf[b_offs + sizeof(iso9660_dentry) + dentry->fi_len],
                     extra_bytes, NULL);
+                if (in_node->inode.rr == NULL) {
+                    if (tsk_verbose)
+                        tsk_fprintf(stderr,
+                                    "iso9660_load_inodes_dir: parse_susp returned error (%s). bailing\n", tsk_error_get());
+                    break;
+                }
+                
                 in_node->inode.susp_off =
                     b_offs + sizeof(iso9660_dentry) + dentry->fi_len +
                     s_offs;
                 in_node->inode.susp_len = extra_bytes;
-
-                if (in_node->inode.rr == NULL) {
-                    // return -1;
-                    // @@@ Verbose error
-                }
             }
             else {
+                in_node->inode.rr = NULL;
                 in_node->inode.susp_off = 0;
                 in_node->inode.susp_len = 0;
             }
@@ -595,11 +691,13 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
 
                 for (tmp = iso->in_list; tmp; tmp = tmp->next) {
                     /* When processing the "first" volume descriptor, all entries get added to the list.
-                     * for the later ones, we skip duplicate ones that overlap with entries from a
-                     * previous volume descriptor. */
+                     * for the later ones, we skip duplicate ones that have content (blocks) that overlaps
+                     * with entries from a previous volume descriptor. */
                     if ((in_node->offset == tmp->offset)
                         && (in_node->size == tmp->size)
                         && (in_node->size) && (is_first == 0)) {
+                        
+                        // if we found rockridge, then update original if needed.
                         if (in_node->inode.rr) {
                             if (tmp->inode.rr == NULL) {
                                 tmp->inode.rr = in_node->inode.rr;
@@ -611,13 +709,14 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                             }
                             else {
                                 free(in_node->inode.rr);
+                                in_node->inode.rr = NULL;
                             }
                         }
 
                         if (tsk_verbose)
                             tsk_fprintf(stderr,
-                                "iso9660_load_inodes_dir: Removing duplicate entry for: %s\n",
-                                in_node->inode.fn);
+                                "iso9660_load_inodes_dir: Removing duplicate entry for: %s (orig name: %s start: %d size: %d)\n",
+                                in_node->inode.fn, tmp->inode.fn, in_node->offset, in_node->size);
                         free(in_node);
                         in_node = NULL;
                         count--;