summaryrefslogtreecommitdiffstats
path: root/lib/libarchive
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2011-12-20 20:34:02 +0000
committermm <mm@FreeBSD.org>2011-12-20 20:34:02 +0000
commitf3adf4b52d600e699c5d826866cb5f4c520bb5a3 (patch)
tree7aba9d88ed7560f63791c04867670fedfeaa70b1 /lib/libarchive
parent2d22b480dbd1e46973715a9cf53ae319f414f158 (diff)
downloadFreeBSD-src-f3adf4b52d600e699c5d826866cb5f4c520bb5a3.zip
FreeBSD-src-f3adf4b52d600e699c5d826866cb5f4c520bb5a3.tar.gz
Sync libarchive with vendor branch release/2.8:
3730: Fix issue 174 (Windows path names, not relevant for FreeBSD) 3734: Merge r1989: archive_clear_error should set errno to 0. 3735: Merge r3247 from trunk: Clear errors before returning from archive_read_support_format_all() 3799: Check the position before dereferencing the pointer. This avoids dereferencing one byte past the end of a string 3824: Merge r3823 from trunk for issue 199 (hang in iso9660 reading) Obtained from: http://code.google.com/p/libarchive MFC after: 2 weeks
Diffstat (limited to 'lib/libarchive')
-rw-r--r--lib/libarchive/archive_read_support_format_all.c10
-rw-r--r--lib/libarchive/archive_read_support_format_iso9660.c10
-rw-r--r--lib/libarchive/archive_string.c2
-rw-r--r--lib/libarchive/archive_util.c1
-rw-r--r--lib/libarchive/archive_write_disk.c104
5 files changed, 114 insertions, 13 deletions
diff --git a/lib/libarchive/archive_read_support_format_all.c b/lib/libarchive/archive_read_support_format_all.c
index 69d16fc..e57cd43 100644
--- a/lib/libarchive/archive_read_support_format_all.c
+++ b/lib/libarchive/archive_read_support_format_all.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2011 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,5 +39,13 @@ archive_read_support_format_all(struct archive *a)
archive_read_support_format_tar(a);
archive_read_support_format_xar(a);
archive_read_support_format_zip(a);
+
+ /* Note: We always return ARCHIVE_OK here, even if some of the
+ * above return ARCHIVE_WARN. The intent here is to enable
+ * "as much as possible." Clients who need specific
+ * compression should enable those individually so they can
+ * verify the level of support. */
+ /* Clear any warning messages set by the above functions. */
+ archive_clear_error(a);
return (ARCHIVE_OK);
}
diff --git a/lib/libarchive/archive_read_support_format_iso9660.c b/lib/libarchive/archive_read_support_format_iso9660.c
index 6d8d304..f014eb3 100644
--- a/lib/libarchive/archive_read_support_format_iso9660.c
+++ b/lib/libarchive/archive_read_support_format_iso9660.c
@@ -302,6 +302,8 @@ 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 {
@@ -2699,8 +2701,14 @@ rede_add_entry(struct file_info *file)
struct file_info *re;
re = file->parent;
- while (re != NULL && !re->re)
+ 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;
re = re->parent;
+ }
if (re == NULL)
return (-1);
diff --git a/lib/libarchive/archive_string.c b/lib/libarchive/archive_string.c
index d68ad58..c67182d 100644
--- a/lib/libarchive/archive_string.c
+++ b/lib/libarchive/archive_string.c
@@ -152,7 +152,7 @@ __archive_strncat(struct archive_string *as, const void *_p, size_t n)
/* Like strlen(p), except won't examine positions beyond p[n]. */
s = 0;
pp = p;
- while (*pp && s < n) {
+ while (s < n && *pp) {
pp++;
s++;
}
diff --git a/lib/libarchive/archive_util.c b/lib/libarchive/archive_util.c
index 4c0de02..8f2b4c6 100644
--- a/lib/libarchive/archive_util.c
+++ b/lib/libarchive/archive_util.c
@@ -155,6 +155,7 @@ archive_clear_error(struct archive *a)
{
archive_string_empty(&a->error_string);
a->error = NULL;
+ a->archive_error_number = 0;
}
void
diff --git a/lib/libarchive/archive_write_disk.c b/lib/libarchive/archive_write_disk.c
index 2319220..49ced58 100644
--- a/lib/libarchive/archive_write_disk.c
+++ b/lib/libarchive/archive_write_disk.c
@@ -1513,6 +1513,22 @@ check_symlinks(struct archive_write_disk *a)
}
#if defined(_WIN32) || defined(__CYGWIN__)
+static int
+guidword(const char *p, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if ((*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'f') ||
+ (*p >= 'A' && *p <= 'F'))
+ p++;
+ else
+ return (-1);
+ }
+ return (0);
+}
+
/*
* 1. Convert a path separator from '\' to '/' .
* We shouldn't check multi-byte character directly because some
@@ -1521,26 +1537,92 @@ check_symlinks(struct archive_write_disk *a)
* 2. Replace unusable characters in Windows with underscore('_').
* See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
*/
-static void
+static int
cleanup_pathname_win(struct archive_write_disk *a)
{
wchar_t wc;
char *p;
size_t alen, l;
- alen = 0;
- l = 0;
- for (p = a->name; *p != '\0'; p++) {
- ++alen;
- if (*p == '\\')
- l = 1;
+ p = a->name;
+ /* Skip leading "\\.\" or "\\?\" or "\\?\UNC\" or
+ * "\\?\Volume{GUID}\"
+ * (absolute path prefixes used by Windows API) */
+ if ((p[0] == '\\' || p[0] == '/') && (p[1] == '\\' || p[1] == '/' ) &&
+ (p[2] == '.' || p[2] == '?') && (p[3] == '\\' || p[3] == '/'))
+ {
+ /* A path begin with "\\?\UNC\" */
+ if (p[2] == '?' &&
+ (p[4] == 'U' || p[4] == 'u') &&
+ (p[5] == 'N' || p[5] == 'n') &&
+ (p[6] == 'C' || p[6] == 'c') &&
+ (p[7] == '\\' || p[7] == '/'))
+ p += 8;
+ /* A path begin with "\\?\Volume{GUID}\" */
+ else if (p[2] == '?' &&
+ (p[4] == 'V' || p[4] == 'v') &&
+ (p[5] == 'O' || p[5] == 'o') &&
+ (p[6] == 'L' || p[6] == 'l') &&
+ (p[7] == 'U' || p[7] == 'u') &&
+ (p[8] == 'M' || p[8] == 'm') &&
+ (p[9] == 'E' || p[9] == 'e') &&
+ p[10] == '{') {
+ if (guidword(p+11, 8) == 0 && p[19] == '-' &&
+ guidword(p+20, 4) == 0 && p[24] == '-' &&
+ guidword(p+25, 4) == 0 && p[29] == '-' &&
+ guidword(p+30, 4) == 0 && p[34] == '-' &&
+ guidword(p+35, 12) == 0 && p[47] == '}' &&
+ (p[48] == '\\' || p[48] == '/'))
+ p += 49;
+ else
+ p += 4;
+ /* A path begin with "\\.\PhysicalDriveX" */
+ } else if (p[2] == '.' &&
+ (p[4] == 'P' || p[4] == 'p') &&
+ (p[5] == 'H' || p[5] == 'h') &&
+ (p[6] == 'Y' || p[6] == 'y') &&
+ (p[7] == 'S' || p[7] == 's') &&
+ (p[8] == 'I' || p[8] == 'i') &&
+ (p[9] == 'C' || p[9] == 'c') &&
+ (p[9] == 'A' || p[9] == 'a') &&
+ (p[9] == 'L' || p[9] == 'l') &&
+ (p[9] == 'D' || p[9] == 'd') &&
+ (p[9] == 'R' || p[9] == 'r') &&
+ (p[9] == 'I' || p[9] == 'i') &&
+ (p[9] == 'V' || p[9] == 'v') &&
+ (p[9] == 'E' || p[9] == 'e') &&
+ (p[10] >= '0' && p[10] <= '9') &&
+ p[11] == '\0') {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Path is a physical drive name");
+ return (ARCHIVE_FAILED);
+ } else
+ p += 4;
+ }
+
+ /* Skip leading drive letter from archives created
+ * on Windows. */
+ if (((p[0] >= 'a' && p[0] <= 'z') ||
+ (p[0] >= 'A' && p[0] <= 'Z')) &&
+ p[1] == ':') {
+ if (p[2] == '\0') {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Path is a drive name");
+ return (ARCHIVE_FAILED);
+ }
+ if (p[2] == '\\' || p[2] == '/')
+ p += 3;
+ }
+
+ for (; *p != '\0'; p++) {
/* Rewrite the path name if its character is a unusable. */
if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
*p == '<' || *p == '>' || *p == '|')
*p = '_';
}
- if (alen == 0 || l == 0)
- return;
+ alen = p - a->name;
+ if (alen == 0 || strchr(a->name, '\\') == NULL)
+ return (ARCHIVE_OK);
/*
* Convert path separator.
*/
@@ -1560,6 +1642,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
p += l;
alen -= l;
}
+ return (ARCHIVE_OK);
}
#endif
@@ -1583,7 +1666,8 @@ cleanup_pathname(struct archive_write_disk *a)
}
#if defined(_WIN32) || defined(__CYGWIN__)
- cleanup_pathname_win(a);
+ if (cleanup_pathname_win(a) != ARCHIVE_OK)
+ return (ARCHIVE_FAILED);
#endif
/* Skip leading '/'. */
if (*src == '/')
OpenPOWER on IntegriCloud