From: Tim Kientzle Date: Fri, 13 Nov 2009 07:04:35 +0000 (-0500) Subject: Fix ACL parsing bug that would erroneously set the mode bits for X-Git-Tag: v2.8.0~164 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7d460d3622701443e9d86daa5b3268787266605;p=thirdparty%2Flibarchive.git Fix ACL parsing bug that would erroneously set the mode bits for the last ACL entry to 0. Also, fix the test that was verifying the wrong results. Thanks to Michihiro Nakajima and Clang static analyzer for finding this. SVN-Revision: 1651 --- diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index bd2c4469e..03dda1af5 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -1615,7 +1615,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, const wchar_t *end; } field[4], name; - int fields; + int fields, n; int type, tag, permset, id; wchar_t sep; @@ -1635,6 +1635,10 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, ++fields; } while (sep == L':'); + /* Set remaining fields to blank. */ + for (n = fields; n < 4; ++n) + field[n].start = field[n].end = NULL; + /* Check for a numeric ID in field 1 or 3. */ id = -1; isint_w(field[1].start, field[1].end, &id); @@ -1646,7 +1650,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, * Solaris extension: "defaultuser::rwx" is the * default ACL corresponding to "user::rwx", etc. */ - if (field[0].end-field[0].start > 7 + if (field[0].end - field[0].start > 7 && wmemcmp(field[0].start, L"default", 7) == 0) { type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; field[0].start += 7; @@ -1673,7 +1677,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, } else if (prefix_w(field[0].start, field[0].end, L"other")) { if (fields == 2 && field[1].start < field[1].end - && ismode_w(field[1].start, field[2].end, &permset)) { + && ismode_w(field[1].start, field[1].end, &permset)) { /* This is Solaris-style "other:rwx" */ } else if (fields == 3 && field[1].start == field[1].end @@ -1742,6 +1746,8 @@ ismode_w(const wchar_t *start, const wchar_t *end, int *permset) { const wchar_t *p; + if (start >= end) + return (0); p = start; *permset = 0; while (p < end) { diff --git a/libarchive/test/test_compat_solaris_tar_acl.c b/libarchive/test/test_compat_solaris_tar_acl.c index ec3955ecd..af4f9d382 100644 --- a/libarchive/test/test_compat_solaris_tar_acl.c +++ b/libarchive/test/test_compat_solaris_tar_acl.c @@ -50,9 +50,9 @@ DEFINE_TEST(test_compat_solaris_tar_acl) /* Archive has 1 entry with some ACLs set on it. */ assertA(0 == archive_read_next_header(a, &ae)); - failure("Basic ACLs should set mode to 0640, not %04o", + failure("Basic ACLs should set mode to 0644, not %04o", archive_entry_mode(ae)&0777); - assertEqualInt((archive_entry_mode(ae) & 0777), 0640); + assertEqualInt((archive_entry_mode(ae) & 0777), 0644); assertEqualInt(7, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae, @@ -77,7 +77,7 @@ DEFINE_TEST(test_compat_solaris_tar_acl) ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type); - assertEqualInt(000, permset); + assertEqualInt(004, permset); assertEqualInt(ARCHIVE_ENTRY_ACL_OTHER, tag); assertEqualInt(-1, qual); assert(name == NULL);