Imported Upstream version 1.8.1 36/156136/1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 17 Oct 2017 08:09:42 +0000 (17:09 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 17 Oct 2017 08:09:45 +0000 (17:09 +0900)
Change-Id: I03853b10dfe1e474bc32669e7a8948e3bf71605d
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
NEWS
configure.ac
src/pathx.c
tests/test-xpath.c

diff --git a/NEWS b/NEWS
index 7240677..9f6ba44 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+1.8.1 - 2017-08-17
+  - General changes/addition
+    * Fix error in handling escaped whitespace at the end of path expressions
+      (addresses CVE-2017-7555)
+
 1.8.0 - 2017-03-20
   - General changes/additions
     * augtool: add a 'source' command exposing the aug_source API call
index bbdfdf1..8b28d36 100644 (file)
@@ -1,4 +1,4 @@
-AC_INIT(augeas, 1.8.0)
+AC_INIT(augeas, 1.8.1)
 AC_CONFIG_SRCDIR([src/augeas.c])
 AC_CONFIG_AUX_DIR([build/ac-aux])
 AM_CONFIG_HEADER([config.h])
@@ -65,7 +65,7 @@ if test x"$enable_debug" = x"yes"; then
 fi
 
 dnl Version info in libtool's notation
-AC_SUBST([LIBAUGEAS_VERSION_INFO], [22:0:22])
+AC_SUBST([LIBAUGEAS_VERSION_INFO], [22:1:22])
 AC_SUBST([LIBFA_VERSION_INFO], [5:4:4])
 
 AC_GNU_SOURCE
index d292cb3..9a2f9c7 100644 (file)
@@ -1710,6 +1710,16 @@ int pathx_escape_name(const char *in, char **out) {
     return 0;
 }
 
+/* Return true if POS is preceded by an odd number of backslashes, i.e., if
+ * POS is escaped. Stop the search when we get to START */
+static bool backslash_escaped(const char *pos, const char *start) {
+    bool result=false;
+    while (pos-- > start && *pos == '\\') {
+        result = !result;
+    }
+    return result;
+}
+
 /*
  * NameNoWS ::= [^][|/\= \t\n] | \\.
  * NameWS   ::= [^][|/\=] | \\.
@@ -1719,11 +1729,14 @@ static char *parse_name(struct state *state) {
     const char *s = state->pos;
     char *result;
 
+    /* Advance state->pos until it points to the first character that is
+     * not part of a name. */
     while (*state->pos != '\0' && strchr(name_follow, *state->pos) == NULL) {
-        /* This is a hack: since we allow spaces in names, we need to avoid
-         * gobbling up stuff that is in follow(Name), e.g. 'or' so that
-         * things like [name1 or name2] still work.
-         */
+        /* Since we allow spaces in names, we need to avoid gobbling up
+         * stuff that is in follow(Name), e.g. 'or' so that things like
+         * [name1 or name2] still work. In other words, we'll parse 'x frob
+         * y' as one name, but for 'x or y', we consider 'x' a name in its
+         * own right. */
         if (STREQLEN(state->pos, " or ", strlen(" or ")) ||
             STREQLEN(state->pos, " and ", strlen(" and ")))
             break;
@@ -1738,10 +1751,12 @@ static char *parse_name(struct state *state) {
         state->pos += 1;
     }
 
-    /* Strip trailing white space */
+    /* Strip trailing white space. Make sure we respect escaped whitespace
+     * and don't strip it as in "x\\ " */
     if (state->pos > s) {
         state->pos -= 1;
-        while (isspace(*state->pos) && state->pos >= s)
+        while (isspace(*state->pos) && state->pos > s
+               && !backslash_escaped(state->pos, s))
             state->pos -= 1;
         state->pos += 1;
     }
index 3e418e5..8298647 100644 (file)
@@ -355,6 +355,62 @@ static int test_wrong_regexp_flag(struct augeas *aug) {
     return -1;
 }
 
+static int test_trailing_ws_in_name(struct augeas *aug) {
+    int r;
+
+    printf("%-30s ... ", "trailing_ws_in_name");
+
+    /* We used to incorrectly lop escaped whitespace off the end of a
+     * name. Make sure that we really create a tree node with label 'x '
+     * with the below set, and look for it in a number of ways to ensure we
+     * are not lopping off trailing whitespace. */
+    r = aug_set(aug, "/ws\\ ", "1");
+    if (r < 0) {
+        fprintf(stderr, "failed to set '/ws ': %d\n", r);
+        goto fail;
+    }
+    /* We did not create a node with label 'ws' */
+    r = aug_get(aug, "/ws", NULL);
+    if (r != 0) {
+        fprintf(stderr, "created '/ws' instead: %d\n", r);
+        goto fail;
+    }
+
+    /* We did not create a node with label 'ws\t' (this also checks that we
+     * don't create something like 'ws\\' by dropping the last whitespace
+     * character. */
+    r = aug_get(aug, "/ws\\\t", NULL);
+    if (r != 0) {
+        fprintf(stderr, "found '/ws\\t': %d\n", r);
+        goto fail;
+    }
+
+    /* But we did create 'ws ' */
+    r = aug_get(aug, "/ws\\ ", NULL);
+    if (r != 1) {
+        fprintf(stderr, "could not find '/ws ': %d\n", r);
+        goto fail;
+    }
+
+    /* If the whitespace is preceded by an even number of '\\' chars,
+     * whitespace must be stripped */
+    r = aug_set(aug, "/nows\\\\ ", "1");
+    if (r < 0) {
+        fprintf(stderr, "set of '/nows' failed: %d\n", r);
+        goto fail;
+    }
+    r = aug_get(aug, "/nows\\\\", NULL);
+    if (r != 1) {
+        fprintf(stderr, "could not get '/nows\\'\n");
+        goto fail;
+    }
+    printf("PASS\n");
+    return 0;
+ fail:
+    printf("FAIL\n");
+    return -1;
+}
+
 static int run_tests(struct test *tests, int argc, char **argv) {
     char *lensdir;
     struct augeas *aug = NULL;
@@ -398,6 +454,9 @@ static int run_tests(struct test *tests, int argc, char **argv) {
 
         if (test_wrong_regexp_flag(aug) < 0)
             result = EXIT_FAILURE;
+
+        if (test_trailing_ws_in_name(aug) < 0)
+            result = EXIT_FAILURE;
     }
     aug_close(aug);
     free(lensdir);