summaryrefslogtreecommitdiff
path: root/app-admin/augeas/files/cve-2017-7555.patch
diff options
context:
space:
mode:
authorV3n3RiX <venerix@redcorelinux.org>2017-10-09 18:53:29 +0100
committerV3n3RiX <venerix@redcorelinux.org>2017-10-09 18:53:29 +0100
commit4f2d7949f03e1c198bc888f2d05f421d35c57e21 (patch)
treeba5f07bf3f9d22d82e54a462313f5d244036c768 /app-admin/augeas/files/cve-2017-7555.patch
reinit the tree, so we can have metadata
Diffstat (limited to 'app-admin/augeas/files/cve-2017-7555.patch')
-rw-r--r--app-admin/augeas/files/cve-2017-7555.patch159
1 files changed, 159 insertions, 0 deletions
diff --git a/app-admin/augeas/files/cve-2017-7555.patch b/app-admin/augeas/files/cve-2017-7555.patch
new file mode 100644
index 000000000000..aaacdc2674c0
--- /dev/null
+++ b/app-admin/augeas/files/cve-2017-7555.patch
@@ -0,0 +1,159 @@
+From 4cca923b732990bec0c699b2e69911c2221b2498 Mon Sep 17 00:00:00 2001
+From: David Lutterkort <lutter@watzmann.net>
+Date: Fri, 4 Aug 2017 17:13:52 -0700
+Subject: [PATCH] * src/pathx.c (parse_name): correctly handle trailing
+ whitespace in names
+
+When a name ended in whitespace, we incorrectly assumed it was always ok to
+trim that whitespace. That is not true if that whitespace is escaped,
+i.e. if the path expression is something like '/x\ '. In that case, the
+name really needs to be literally 'x ', i.e., we can not trim that
+whitespace.
+
+The incorrect behavior led to turning '/x\ ' first into 'x\' and then,
+because we assume that '\' is always followed by a character inside the
+string, when we removed the escaping '\', we would read beyond the end of
+the intermediate string result; if we were lucky, that would lead to a
+crash, otherwise we'd continue with junk.
+
+We now make sure that escaped whitespace at the end of a string does not
+get stripped, avoiding all these headaches.
+
+Fixes RHBZ https://bugzilla.redhat.com/show_bug.cgi?id=1475621
+---
+ src/pathx.c | 27 +++++++++++++++++++------
+ tests/test-xpath.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 80 insertions(+), 6 deletions(-)
+
+diff --git a/src/pathx.c b/src/pathx.c
+index d292cb30..9a2f9c76 100644
+--- a/src/pathx.c
++++ b/src/pathx.c
+@@ -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;
+ }
+diff --git a/tests/test-xpath.c b/tests/test-xpath.c
+index 3e418e5f..82986474 100644
+--- a/tests/test-xpath.c
++++ b/tests/test-xpath.c
+@@ -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);