From: Michihiro NAKAJIMA Date: Sat, 24 Dec 2011 12:49:52 +0000 (-0500) Subject: Issue 199: Merge r3835 from trunk. X-Git-Tag: v3.0.4~2^2~169^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=011805b30146e41c65c5f133656e3e95548ad75f;p=thirdparty%2Flibarchive.git Issue 199: Merge r3835 from trunk. SVN-Revision: 3980 --- diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index f35f0ea80..2c1301ad5 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -302,8 +302,6 @@ struct file_info { struct file_info *first; struct file_info **last; } rede_files; - /* To check a ininity loop. */ - struct file_info *loop_by; }; struct heap_queue { @@ -1799,26 +1797,82 @@ parse_file_info(struct archive_read *a, struct file_info *parent, file->re = 0; parent->subdirs--; } else if (file->re) { - /* This file's parent is not rr_moved, clear invalid - * "RE" mark. */ - if (parent == NULL || parent->rr_moved == 0) - file->re = 0; - else if ((flags & 0x02) == 0) { - file->rr_moved_has_re_only = 0; - file->re = 0; + /* + * Sanity check: file's parent is rr_moved. + */ + if (parent == NULL || parent->rr_moved == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE"); + return (NULL); + } + /* + * Sanity check: file does not have "CL" extension. + */ + if (file->cl_offset) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE and CL"); + return (NULL); + } + /* + * Sanity check: The file type must be a directory. + */ + if ((flags & 0x02) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE"); + return (NULL); } } else if (parent != NULL && parent->rr_moved) file->rr_moved_has_re_only = 0; else if (parent != NULL && (flags & 0x02) && (parent->re || parent->re_descendant)) file->re_descendant = 1; - if (file->cl_offset != 0) { + if (file->cl_offset) { + struct file_info *p; + + if (parent == NULL || parent->parent == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + return (NULL); + } + /* + * Sanity check: The file type must be a regular file. + */ + if ((flags & 0x02) != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + return (NULL); + } parent->subdirs++; /* Overwrite an offset and a number of this "CL" entry * to appear before other dirs. "+1" to those is to * make sure to appear after "RE" entry which this * "CL" entry should be connected with. */ file->offset = file->number = file->cl_offset + 1; + + /* + * Sanity check: cl_offset does not point at its + * the parents or itself. + */ + for (p = parent; p; p = p->parent) { + if (p->offset == file->cl_offset) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + return (NULL); + } + } + if (file->cl_offset == file->offset || + parent->rr_moved) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); + return (NULL); + } } } @@ -1922,6 +1976,13 @@ parse_rockridge(struct archive_read *a, struct file_info *file, */ break; } + if (p[0] == 'P' && p[1] == 'L') { + /* + * PL extension won't appear; + * contents are always ignored. + */ + break; + } if (p[0] == 'P' && p[1] == 'N') { if (version == 1 && data_length == 16) { file->rdev = toi(data,4); @@ -2697,15 +2758,12 @@ rede_add_entry(struct file_info *file) { struct file_info *re; + /* + * Find "RE" entry. + */ re = file->parent; - while (re != NULL && !re->re) { - /* Sanity check to prevent a infinity loop - * cause by a currupted iso file. */ - if (re->loop_by == file) - return (-1); - re->loop_by = file; + while (re != NULL && !re->re) re = re->parent; - } if (re == NULL) return (-1);