|
|
58251f |
From 1e18cbb71515a22b2a6f1eb4aaadea461929b834 Mon Sep 17 00:00:00 2001
|
|
|
58251f |
From: Tim Kientzle <kientzle@acm.org>
|
|
|
58251f |
Date: Sat, 21 Feb 2015 10:37:48 -0800
|
|
|
58251f |
Subject: [PATCH] Issue 408: Fix escaped newline parsing
|
|
|
58251f |
|
|
|
58251f |
---
|
|
|
58251f |
libarchive/archive_read_support_format_mtree.c | 56 ++++++++++++-------------
|
|
|
58251f |
libarchive/test/test_read_format_mtree.c | 8 +++-
|
|
|
58251f |
libarchive/test/test_read_format_mtree.mtree.uu | 20 +++++----
|
|
|
58251f |
3 files changed, 45 insertions(+), 39 deletions(-)
|
|
|
58251f |
|
|
|
58251f |
diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
|
|
|
58251f |
index c4e7021..397bfee 100644
|
|
|
58251f |
--- a/libarchive/archive_read_support_format_mtree.c
|
|
|
58251f |
+++ b/libarchive/archive_read_support_format_mtree.c
|
|
|
58251f |
@@ -1661,6 +1661,10 @@ parse_escapes(char *src, struct mtree_entry *mentry)
|
|
|
58251f |
c = '\v';
|
|
|
58251f |
++src;
|
|
|
58251f |
break;
|
|
|
58251f |
+ case '\\':
|
|
|
58251f |
+ c = '\\';
|
|
|
58251f |
+ ++src;
|
|
|
58251f |
+ break;
|
|
|
58251f |
}
|
|
|
58251f |
}
|
|
|
58251f |
*dest++ = c;
|
|
|
58251f |
@@ -1804,8 +1808,7 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi
|
|
|
58251f |
ssize_t total_size = 0;
|
|
|
58251f |
ssize_t find_off = 0;
|
|
|
58251f |
const void *t;
|
|
|
58251f |
- const char *s;
|
|
|
58251f |
- void *p;
|
|
|
58251f |
+ void *nl;
|
|
|
58251f |
char *u;
|
|
|
58251f |
|
|
|
58251f |
/* Accumulate line in a line buffer. */
|
|
|
58251f |
@@ -1816,11 +1819,10 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi
|
|
|
58251f |
return (0);
|
|
|
58251f |
if (bytes_read < 0)
|
|
|
58251f |
return (ARCHIVE_FATAL);
|
|
|
58251f |
- s = t; /* Start of line? */
|
|
|
58251f |
- p = memchr(t, '\n', bytes_read);
|
|
|
58251f |
- /* If we found '\n', trim the read. */
|
|
|
58251f |
- if (p != NULL) {
|
|
|
58251f |
- bytes_read = 1 + ((const char *)p) - s;
|
|
|
58251f |
+ nl = memchr(t, '\n', bytes_read);
|
|
|
58251f |
+ /* If we found '\n', trim the read to end exactly there. */
|
|
|
58251f |
+ if (nl != NULL) {
|
|
|
58251f |
+ bytes_read = ((const char *)nl) - ((const char *)t) + 1;
|
|
|
58251f |
}
|
|
|
58251f |
if (total_size + bytes_read + 1 > limit) {
|
|
|
58251f |
archive_set_error(&a->archive,
|
|
|
58251f |
@@ -1834,38 +1836,34 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi
|
|
|
58251f |
"Can't allocate working buffer");
|
|
|
58251f |
return (ARCHIVE_FATAL);
|
|
|
58251f |
}
|
|
|
58251f |
+ /* Append new bytes to string. */
|
|
|
58251f |
memcpy(mtree->line.s + total_size, t, bytes_read);
|
|
|
58251f |
__archive_read_consume(a, bytes_read);
|
|
|
58251f |
total_size += bytes_read;
|
|
|
58251f |
- /* Null terminate. */
|
|
|
58251f |
mtree->line.s[total_size] = '\0';
|
|
|
58251f |
- /* If we found an unescaped '\n', clean up and return. */
|
|
|
58251f |
+
|
|
|
58251f |
for (u = mtree->line.s + find_off; *u; ++u) {
|
|
|
58251f |
if (u[0] == '\n') {
|
|
|
58251f |
+ /* Ends with unescaped newline. */
|
|
|
58251f |
*start = mtree->line.s;
|
|
|
58251f |
return total_size;
|
|
|
58251f |
- }
|
|
|
58251f |
- if (u[0] == '#') {
|
|
|
58251f |
- if (p == NULL)
|
|
|
58251f |
+ } else if (u[0] == '#') {
|
|
|
58251f |
+ /* Ends with comment sequence #...\n */
|
|
|
58251f |
+ if (nl == NULL) {
|
|
|
58251f |
+ /* But we've not found the \n yet */
|
|
|
58251f |
break;
|
|
|
58251f |
- *start = mtree->line.s;
|
|
|
58251f |
- return total_size;
|
|
|
58251f |
- }
|
|
|
58251f |
- if (u[0] != '\\')
|
|
|
58251f |
- continue;
|
|
|
58251f |
- if (u[1] == '\\') {
|
|
|
58251f |
- ++u;
|
|
|
58251f |
- continue;
|
|
|
58251f |
- }
|
|
|
58251f |
- if (u[1] == '\n') {
|
|
|
58251f |
- memmove(u, u + 1,
|
|
|
58251f |
- total_size - (u - mtree->line.s) + 1);
|
|
|
58251f |
- --total_size;
|
|
|
58251f |
- ++u;
|
|
|
58251f |
- break;
|
|
|
58251f |
+ }
|
|
|
58251f |
+ } else if (u[0] == '\\') {
|
|
|
58251f |
+ if (u[1] == '\n') {
|
|
|
58251f |
+ /* Trim escaped newline. */
|
|
|
58251f |
+ total_size -= 2;
|
|
|
58251f |
+ mtree->line.s[total_size] = '\0';
|
|
|
58251f |
+ break;
|
|
|
58251f |
+ } else if (u[1] != '\0') {
|
|
|
58251f |
+ /* Skip the two-char escape sequence */
|
|
|
58251f |
+ ++u;
|
|
|
58251f |
+ }
|
|
|
58251f |
}
|
|
|
58251f |
- if (u[1] == '\0')
|
|
|
58251f |
- break;
|
|
|
58251f |
}
|
|
|
58251f |
find_off = u - mtree->line.s;
|
|
|
58251f |
}
|
|
|
58251f |
diff --git a/libarchive/test/test_read_format_mtree.c b/libarchive/test/test_read_format_mtree.c
|
|
|
58251f |
index efedc41..85a0e2e 100644
|
|
|
58251f |
--- a/libarchive/test/test_read_format_mtree.c
|
|
|
58251f |
+++ b/libarchive/test/test_read_format_mtree.c
|
|
|
58251f |
@@ -110,6 +110,10 @@ test_read_format_mtree1(void)
|
|
|
58251f |
assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b");
|
|
|
58251f |
|
|
|
58251f |
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae);;
|
|
|
58251f |
+ assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/filename\\with_esc\b\t\fapes");
|
|
|
58251f |
+ assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
|
58251f |
+
|
|
|
58251f |
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae);;
|
|
|
58251f |
assertEqualString(archive_entry_pathname(ae), "notindir");
|
|
|
58251f |
|
|
|
58251f |
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae);;
|
|
|
58251f |
@@ -151,7 +155,7 @@ test_read_format_mtree1(void)
|
|
|
58251f |
assertEqualInt(archive_entry_mtime(ae), min_time);
|
|
|
58251f |
|
|
|
58251f |
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae);;
|
|
|
58251f |
- assertEqualInt(19, archive_file_count(a));
|
|
|
58251f |
+ assertEqualInt(20, archive_file_count(a));
|
|
|
58251f |
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
58251f |
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
|
58251f |
}
|
|
|
58251f |
diff --git a/libarchive/test/test_read_format_mtree.mtree.uu b/libarchive/test/test_read_format_mtree.mtree.uu
|
|
|
58251f |
index a0dff18..f1c9d60 100644
|
|
|
58251f |
--- a/libarchive/test/test_read_format_mtree.mtree.uu
|
|
|
58251f |
+++ b/libarchive/test/test_read_format_mtree.mtree.uu
|
|
|
58251f |
@@ -5,14 +5,16 @@ M92!U:60],3@*("XN"F9I;&5<,#0P=VET:%PP-#!S<&%C92!T>7!E/69I;&4*
|
|
|
58251f |
M9&ER,B!T>7!E/61I<@H@9&ER,V$@='EP93UD:7(*("!I;F1I
|
|
|
58251f |
M9FEL90ID:7(R+V9U;&QI;F1I
|
|
|
58251f |
M"B!I;F1I<C(@='EP93UF:6QE"B!D:7(S8B!T>7!E/61I<@H@(&EN9&ER,V(@
|
|
|
58251f |
-M='EP93UF:6QE"B`@+BX*("XN"FYO=&EN9&ER('1Y<&4]9FEL90ID:7(R+V9U
|
|
|
58251f |
-M;&QI;F1I
|
|
|
58251f |
-M:7IE/3!X,`ID:7(R+W-M86QL9FEL92!T>7!E/69I;&4@
|
|
|
58251f |
-M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#$*9&ER,B]T;V]S;6%L;&9;;&4@='EP
|
|
|
58251f |
-M93UF:6QE('-I>F4]+3$*9&ER,B]B:6=F:6QE('1Y<&4]9FEL92!S:7IE/3DR
|
|
|
58251f |
-M,C,S-S(P,S8X-30W-S4X,#<*9&ER,B]T;V]B:6=F:6QE('1Y<&4]9FEL92!S
|
|
|
58251f |
-M:7IE/3DR,C,S-S(P,S8X-30W-S4X,#@*9&ER,B]V97)Y;VQD9FEL92!T>7!E
|
|
|
58251f |
-M/69I;&4@=&EM93TM.3(R,S,W,C`S-C@U-#
|
|
|
58251f |
-H;&4@='EP93UF:6QE('1I;64]+3DR,C,S-S(P,S8X-30W-S4X,#D*"@``
|
|
|
58251f |
+M='EP93UF:6QE"B`@9FEL96YA;65<7'=I=&A<"E]E
|
|
|
58251f |
+M<&4]9FEL92!M;V1E/3`T-#0@
|
|
|
58251f |
+M<&4]9FEL90ID:7(R+V9U;&QI;F1I
|
|
|
58251f |
+M:6QE('1Y<&4]9FEL92!S:7IE/3!X,`ID:7(R+W-M86QL9FEL92!T>7!E/69I
|
|
|
58251f |
+M;&4@
|
|
|
58251f |
+M;V]S;6%L;&9;;&4@='EP93UF:6QE('-I>F4]+3$*9&ER,B]B:6=F:6QE('1Y
|
|
|
58251f |
+M<&4]9FEL92!S:7IE/3DR,C,S-S(P,S8X-30W-S4X,#<*9&ER,B]T;V]B:6=F
|
|
|
58251f |
+M:6QE('1Y<&4]9FEL92!S:7IE/3DR,C,S-S(P,S8X-30W-S4X,#@*9&ER,B]V
|
|
|
58251f |
+M97)Y;VQD9FEL92!T>7!E/69I;&4@=&EM93TM.3(R,S,W,C`S-C@U-#
|
|
|
58251f |
+M.`ID:7(R+W1O;V]L9&9;;&4@='EP93UF:6QE('1I;64]+3DR,C,S-S(P,S8X
|
|
|
58251f |
+*-30W-S4X,#D*"@``
|
|
|
58251f |
`
|
|
|
58251f |
end
|
|
|
58251f |
--
|
|
|
58251f |
2.7.4
|
|
|
58251f |
|