+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
-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])
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
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 ::= [^][|/\=] | \\.
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;
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;
}
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;
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);