[apparmor] [patch 05/26] cleanup/fix escape sequences in the backend and add support for \d

Seth Arnold seth.arnold at canonical.com
Tue Apr 15 00:49:00 UTC 2014


On Mon, Apr 14, 2014 at 01:25:27PM -0700, John Johansen wrote:
> Alright here is a new revision of the patch. It folds in steve's test
> patch, but moves it to the lib.c file.
> 
> In addition this patch unifies escape sequence handling (backend,
> processunqoted, processquoted), and adds a few lib routines and unit tests
> that are used by the escape sequence handling.
> 
> It does not yet eliminate the double escape sequence handling that happens
> to items that pass through the lexer and then the backend. There is more
> work to be done before we can fix this properly.
> 
> ---
> 
> cleanup/fix escape sequences in the backend and add support for \d
> 
> the octal escape sequence was broken, so that short escapes \0, \00 \xa,
> didn't work and actually resulted in some encoding bugs.
> 
> Also we were missing support for the decimal # conversion \d123
> 
> Signed-off-by: John Johansen <john.johansen at canonical.com>

Very nice cleanup, a few comments inline

> 
> ---
>  parser/Makefile                |    4 
>  parser/lib.c                   |  289 +++++++++++++++++++++++++++++++++++++++++
>  parser/lib.h                   |   13 +
>  parser/libapparmor_re/Makefile |    2 
>  parser/libapparmor_re/parse.h  |    1 
>  parser/libapparmor_re/parse.y  |   92 +------------
>  parser/parser_misc.c           |  243 +++++++++++++++++++---------------
>  7 files changed, 457 insertions(+), 187 deletions(-)
> 
> --- 2.9-test.orig/parser/Makefile
> +++ 2.9-test/parser/Makefile
> @@ -111,7 +111,7 @@
>  LEX_C_FILES	= parser_lex.c
>  YACC_C_FILES	= parser_yacc.c parser_yacc.h
>  
> -TESTS = tst_regex tst_misc tst_symtab tst_variable
> +TESTS = tst_regex tst_misc tst_symtab tst_variable tst_lib
>  TEST_CFLAGS = $(EXTRA_CFLAGS) -DUNIT_TEST -Wno-unused-result
>  TEST_OBJECTS = $(filter-out \
>  			parser_lex.o \
> @@ -262,6 +262,8 @@
>  cap_names.h: /usr/include/linux/capability.h
>  	echo "$(CAPABILITIES)" | LC_ALL=C sed -n -e "s/[ \\t]\\?CAP_\\([A-Z0-9_]\\+\\)/\{\"\\L\\1\", \\UCAP_\\1\},\\n/pg" > $@
>  
> +tst_lib: lib.c parser.h $(filter-out lib.o, ${TEST_OBJECTS})
> +	$(CXX) $(TEST_CFLAGS) -o $@ $< $(filter-out $(<:.c=.o), ${TEST_OBJECTS}) $(TEST_LDFLAGS)
>  tst_%: parser_%.c parser.h $(filter-out parser_%.o, ${TEST_OBJECTS})
>  	$(CXX) $(TEST_CFLAGS) -o $@ $< $(filter-out $(<:.c=.o), ${TEST_OBJECTS}) $(TEST_LDFLAGS)
>  
> --- 2.9-test.orig/parser/lib.c
> +++ 2.9-test/parser/lib.c
> @@ -29,6 +29,7 @@
>  #include <sys/stat.h>
>  #include <sys/types.h>
>  
> +#include "lib.h"
>  #include "parser.h"
>  
>  /**
> @@ -135,3 +136,291 @@
>  
>  	return -1;
>  }
> +
> +/**
> + * isodigit - test if a character is an octal digit
> + * @c: character to test
> + *
> + * Returns: true if an octal digit, else false
> + */
> +bool isodigit(char c)
> +{
> +	return (c >= '0' && c <= '7') ? true : false;
> +}
> +
> +/* convert char character 0..9a..z into a number 0-35
> + *
> + * Returns: digit value of character or -1 if character is invalid
> + */
> +static int chrtoi(char c, int base)
> +{
> +	int val = -1;
> +
> +	if (base < 2 || base > 36)
> +		return -1;
> +
> +	if (isdigit(c))
> +		val = c - '0';
> +	else if (isalpha(c) && isascii(c))
> +		val = tolower(c) - 'a' + 10;
> +
> +	if (val >= base)
> +		return -1;
> +
> +	return val;
> +}
> +
> +/**
> + * strntol - convert a sequence of characters as a hex number
> + * @str: pointer to a string of character to convert
> + * @endptr: RETURNS: if not NULL, the first char after converted chars.
> + * @base: base of convertion
> + * @maxval: maximum value. don't consume next char if value will exceed @maxval
> + * @n: maximum number of characters to consume doing the conversion
> + *
> + * Returns: converted number. If there is no conversion 0 is returned and
> + *          *@endptr = @str
> + *
> + * Not a complete replacement for strtol yet, Does not process base prefixes,
> + * nor +/- sign yet.
> + *
> + * - take the largest sequence of character that is in range of 0- at maxval
> + * - will consume the minimum of @maxlen or @base digits in @maxval
> + * - if there is not n valid characters for the base only the n-1 will be taken
> + *   eg. for the sequence string 4z with base 16 only 4 will be taken as the
> + *   hex number
> + */
> +long strntol(const char *str, const char **endptr, int base, long maxval,
> +	     size_t n)
> +{
> +	long c, val = 0;
> +
> +	if (base > 1 && base < 37) {
> +		for (; n && (c = chrtoi(*str, base)) != -1; str++, n--) {
> +			long tmp = (val * base) + c;
> +			if (tmp > maxval)
> +				break;
> +			val = tmp;
> +		}
> +	}
> +
> +	if (endptr)
> +		*endptr = str;
> +
> +	return val;
> +}
> +
> +/**
> + * strn_escseq -
> + * @pos: position of first character in esc sequence
> + * @n: maximum length of string to processes
> + *
> + * Returns: character for escape sequence or -1 if an error
> + *
> + * pos will point to first character after esc sequence
> + * OR
> + * pos will point to first character where an error was discovered
> + * errors can be unrecognized esc character, octal, decimal, or hex
> + * character encoding with no valid number. eg. \xT
> + */
> +int strn_escseq(const char **pos, size_t n)
> +{
> +	const char *end;
> +	long tmp;
> +
> +	if (n < 1)
> +		return -1;
> +
> +	if (isodigit(**pos)) {
> +		tmp = strntol(*pos, &end, 8, 255, min(3ul, n));
> +		if (tmp == 0 && end == *pos) {
> +			/* this should never happen because of isodigit test */
> +			return -1;
> +		}
> +		*pos = end;
> +		return tmp;
> +	}
> +
> +	switch(*(*pos)++) {
> +	case '\0':
> +		(*pos)--;
> +		/* fall through */
> +	case '\\':
> +		return '\\';

I don't care much for falling through, especially when the thing
falled-through-to is shorter and easier than the /* fall through */
comment itself.

> +	case '"':
> +		return '"';
> +	case 'd':
> +		tmp = strntol(*pos, &end, 10, 255, min(3ul, n));
> +		if (tmp == 0 && end == *pos) {
> +			/* \d no valid encoding */
> +			return -1;
> +		}
> +		*pos = end;
> +		return tmp;
> +	case 'x':
> +		tmp = strntol(*pos, &end, 16, 255, min(2ul, n));
> +		if (tmp == 0 && end == *pos) {
> +			/* \x no valid encoding */
> +			return -1;
> +		}
> +		*pos = end;
> +		return tmp;
> +	case 'a':
> +		return '\a';
> +	case 'e':
> +		return 033  /* ESC */;
> +	case 'f':
> +		return '\f';
> +	case 'n':
> +		return '\n';
> +	case 'r':
> +		return '\r';
> +	case 't':
> +		return '\t';
> +	}
> +	/* unsupported escap sequence, backup to return that char */
> +	pos--;
> +	return -1;
> +}
> +
> +int str_escseq(const char **pos)
> +{
> +	/* no len limit just use end of string */
> +	return strn_escseq(pos, SIZE_MAX);
> +}
> +
> +#ifdef UNIT_TEST
> +
> +#include "lib.h"
> +#include "parser.h"
> +#include "unit_test.h"
> +
> +static int test_oct(const char *str)
> +{
> +	const char *end;
> +	long retval = strntol(str, &end, 8, 255, 3);
> +	if (retval == 0 && str == end)
> +		return -1;
> +	return retval;
> +}
> +
> +static int test_dec(const char *str)
> +{
> +	const char *end;
> +	long retval = strntol(str, &end, 10, 255, 3);
> +	if (retval == 0 && str == end)
> +		return -1;
> +	return retval;
> +}
> +
> +static int test_hex(const char *str)
> +{
> +	const char *end;
> +	long retval = strntol(str, &end, 16, 255, 2);
> +	if (retval == 0 && str == end)
> +		return -1;
> +	return retval;
> +}
> +
> +int main(void)
> +{
> +        int rc = 0;
> +	int retval;

The indenting of 'int rc' is different than expected.


> +
> +	struct test_struct {
> +		const char *test;	/* test string */
> +		int expected;		/* expected result */
> +		const char *msg;	/* failure message */
> +	};
> +
> +	struct test_struct oct_tests[] = {
> +	  { "0a", 0, "oct conversion of \\0a failed" },
> +	  { "00000003a", 0, "oct conversion of \\00000003a failed" },
> +	  { "62", 50, "oct conversion of \\62 failed" },
> +	  { "623", 50, "oct conversion of \\623 failed" },
> +	  { "123", 83, "oct conversion of \\123 failed" },
> +	  { "123;", 83, "oct conversion of \\123; failed" },
> +	  { "2234", 147, "oct conversion of \\2234 failed" },
> +	  { "xx", -1, "oct conversion of \\xx failed" },
> +	  { NULL, 0, NULL }
> +	};
> +
> +	struct test_struct dec_tests[] = {
> +	  { "0a", 0, "dec conversion of \\d0a failed" },
> +	  { "00000003a", 0, "dec conversion of \\d00000003a failed" },
> +	  { "62", 62, "dec conversion of \\d62 failed" },
> +	  { "623", 62, "dec conversion of \\d623 failed" },
> +	  { "132", 132, "dec conversion of \\d132 failed" },
> +	  { "132UL", 132, "dec conversion of \\d132UL failed" },
> +	  { "255", 255, "dec conversion of \\d255 failed" },
> +	  { "256", 25, "dec conversion of \\d256 failed" },
> +	  { "2234", 223, "dec conversion of \\d2234 failed" },
> +	  { "xx", -1, "dec conversion of \\dxx failed" },
> +	  { NULL, 0, NULL }
> +	};
> +
> +	struct test_struct hex_tests[] = {
> +	  { "0", 0x0, "hex conversion of 0x0 failed" },
> +	  { "0x1", 0x0, "hex conversion of 0x0x1 failed" },
> +	  { "1x", 0x1, "hex conversion of 0x1x failed" },
> +	  { "00", 0x0, "hex conversion of 0x00 failed" },
> +	  { "00x", 0x0, "hex conversion of 0x00x failed" },
> +	  { "01", 0x1, "hex conversion of 0x01 failed" },
> +	  { "01x", 0x1, "hex conversion of 0x01x failed" },
> +	  { "ab", 0xab, "hex conversion of 0xAb failed" },
> +	  { "AB", 0xab, "hex conversion of 0xAB failed" },
> +	  { "Ab", 0xab, "hex conversion of 0xAb failed" },
> +	  { "aB", 0xab, "hex conversion of 0xaB failed" },
> +	  { "4z", 0x4, "hex conversion of 0x4z failed" },
> +	  { "123", 0x12, "hex conversion of 0x123 failed" },
> +	  { "12M", 0x12, "hex conversion of 0x12M failed" },
> +	  { "ff", 0xff, "hex conversion of 0x255 failed" },
> +	  { "FF", 0xff, "hex conversion of 0x255 failed" },
> +	  { "XX", -1, "hex conversion of 0xXX failed" },
> +	  { NULL, 0, NULL }
> +	};
> +
> +	/* test chrtoi */
> +	for (int base = -1; base < 38; base++) {
> +		for (int c = 0; c < 256; c++) {
> +			int expected;
> +			int i = chrtoi(c, base);
> +			if (base < 2 || base > 36 || !isascii(c) || !(isdigit(c) || isalpha(c)))
> +				expected = -1;
> +			else if (isdigit(c) && (c - '0') < base)
> +				expected = toupper(c) - '0';

toupper(c) of a digit is a noop; might as well remove it.

> +			else if (isalpha(c) && (toupper(c) - 'A') + 10 < base)
> +				expected = (toupper(c) - 'A') + 10;
> +			else
> +				expected = -1;
> +			if (i != expected)
> +				printf("   chrtoi test: convert base %d '%c'(%d)\texpected %d\tresult: %d\n", base, c, c, expected, i);
> +			MY_TEST(i == expected, "failed");
> +		}
> +	}
> +
> +	/* test strntol */
> +	for (struct test_struct *t = oct_tests; t->test; t++) {
> +		retval = test_oct(t->test);
> +		printf("  oct test: %s\texpected %d\tresult: %d\n", t->test, t->expected, retval);
> +		MY_TEST(retval == t->expected, t->msg);
> +	}
> +
> +	for (struct test_struct *t = dec_tests; t->test; t++) {
> +		retval = test_dec(t->test);
> +		printf("  dec test: %s\texpected %d\tresult: %d\n", t->test, t->expected, retval);
> +		MY_TEST(retval == t->expected, t->msg);
> +	}
> +
> +	for (struct test_struct *t = hex_tests; t->test; t++) {
> +		retval = test_hex(t->test);
> +		printf("  hex test: %s\texpected %d\tresult: %d\n", t->test, t->expected, retval);
> +		MY_TEST(retval == t->expected, t->msg);
> +	}
> +
> +	/* test strn_escseq */
> +	/* TODO: */
> +	return rc;
> +}
> +
> +#endif /* UNIT_TEST */
> --- 2.9-test.orig/parser/lib.h
> +++ 2.9-test/parser/lib.h
> @@ -1,7 +1,20 @@
>  #ifndef __AA_LIB_H_
>  #define __AA_LIB_H_
>  
> +#include <dirent.h>
> +
> +#define min(a,b) \
> +   ({ __typeof__ (a) _a = (a); \
> +       __typeof__ (b) _b = (b); \
> +     _a < _b ? _a : _b; })
> +
>  int dirat_for_each(DIR *dir, const char *name, void *data,
>  		   int (* cb)(DIR *, const char *, struct stat *, void *));
>  
> +bool isodigit(char c);
> +long strntol(const char *str, const char **endptr, int base, long maxval,
> +	     size_t n);
> +int strn_escseq(const char **pos, size_t n);
> +int str_escseq(const char **pos);
> +
>  #endif /* __AA_LIB_H_ */
> --- 2.9-test.orig/parser/libapparmor_re/Makefile
> +++ 2.9-test/parser/libapparmor_re/Makefile
> @@ -12,6 +12,8 @@
>  
>  all : ${TARGET}
>  
> +UNITTESTS = tst_parse
> +
>  libapparmor_re.a: parse.o expr-tree.o hfa.o chfa.o aare_rules.o
>  	ar ${ARFLAGS} $@ $^
>  
> --- 2.9-test.orig/parser/libapparmor_re/parse.h
> +++ 2.9-test/parser/libapparmor_re/parse.h
> @@ -24,4 +24,5 @@
>  
>  int regex_parse(Node **tree, const char *rule);
>  
> +
>  #endif /* __LIBAA_RE_PARSE_H */

The above newline doesn't do much, unless you really want the extra space.

> --- 2.9-test.orig/parser/libapparmor_re/parse.y
> +++ 2.9-test/parser/libapparmor_re/parse.y
> @@ -155,30 +155,13 @@
>  
>  %%
>  
> -
> -int octdigit(char c)
> -{
> -	if (c >= '0' && c <= '7')
> -		return c - '0';
> -	return -1;
> -}
> -
> -int hexdigit(char c)
> -{
> -	if (c >= '0' && c <= '9')
> -		return c - '0';
> -	else if (c >= 'A' && c <= 'F')
> -		return 10 + c - 'A';
> -	else if (c >= 'a' && c <= 'f')
> -		return 10 + c - 'a';
> -	else
> -		return -1;
> -}
> +#include "../lib.h"
>  
>  int regex_lex(YYSTYPE *val, const char **pos)
>  {
> -	int c;
> +	int tmp;
>  
> +start:
>  	val->c = **pos;
>  	switch(*(*pos)++) {
>  	case '\0':
> @@ -190,67 +173,14 @@
>  		return *(*pos - 1);
>  
>  	case '\\':
> -		val->c = **pos;
> -		switch(*(*pos)++) {
> -		case '\0':
> -			(*pos)--;
> -			/* fall through */
> -		case '\\':
> -			val->c = '\\';
> -			break;
> -
> -		case '0':
> -			val->c = 0;
> -			if ((c = octdigit(**pos)) >= 0) {
> -				val->c = c;
> -				(*pos)++;
> -			}
> -			if ((c = octdigit(**pos)) >= 0) {
> -				val->c = (val->c << 3) + c;
> -				(*pos)++;
> -			}
> -			if ((c = octdigit(**pos)) >= 0) {
> -				val->c = (val->c << 3) + c;
> -				(*pos)++;
> -			}
> -			break;
> -
> -		case 'x':
> -			val->c = 0;
> -			if ((c = hexdigit(**pos)) >= 0) {
> -				val->c = c;
> -				(*pos)++;
> -			}
> -			if ((c = hexdigit(**pos)) >= 0) {
> -				val->c = (val->c << 4) + c;
> -				(*pos)++;
> -			}
> -			break;
> -
> -		case 'a':
> -			val->c = '\a';
> -			break;
> -
> -		case 'e':
> -			val->c = 033  /* ESC */;
> -			break;
> -
> -		case 'f':
> -			val->c = '\f';
> -			break;
> -
> -		case 'n':
> -			val->c = '\n';
> -			break;
> -
> -		case 'r':
> -			val->c = '\r';
> -			break;
> -
> -		case 't':
> -			val->c = '\t';
> -			break;
> -		}
> +		tmp = str_escseq(pos);
> +		if (tmp == -1)
> +			/* bad escape sequence, just skip it for now
> +			 * TODO: output error message
> +			 */
> +			goto start;
> +		val->c = tmp;
> +		break;
>  	}
>  	return CHAR;
>  }
> --- 2.9-test.orig/parser/parser_misc.c
> +++ 2.9-test/parser/parser_misc.c
> @@ -39,6 +39,7 @@
>  #include <unistd.h>
>  #include <sys/apparmor.h>
>  
> +#include "lib.h"
>  #include "parser.h"
>  #include "profile.h"
>  #include "parser_yacc.h"
> @@ -443,38 +444,70 @@
>  
>  char *processunquoted(const char *string, int len)
>  {
> -	char *tmp, *s;
> -	int l;
> +	char *buffer, *s;
>  
> -	tmp = (char *)malloc(len + 1);
> -	if (!tmp)
> +	s = buffer = (char *) malloc(len + 1);
> +	if (!buffer)
>  		return NULL;
>  
> -	s = tmp;
> -	for (l = 0; l < len; l++) {
> -		if (string[l] == '\\' && l < len - 3) {
> -			if (strchr("0123", string[l + 1]) &&
> -			    strchr("0123456789", string[l + 2]) &&
> -			    strchr("0123456789", string[l + 3])) {
> -				/* three digit octal */
> -				int res = (string[l + 1] - '0') * 64 +
> -				    	  (string[l + 2] - '0') * 8 +
> -					  (string[l + 3] - '0');
> -				*s = res;
> -				l += 3;
> +	while (len > 0) {
> +		const char *pos = string + 1;
> +		long c;
> +		if (*string == '\\' && len > 1 &&
> +		    (c = strn_escseq(&pos, len)) != -1) {
> +			*s++ = c;
> +			len -= pos - string;
> +			string = pos;
> +		} else {
> +			/* either unescaped char OR
> +			 * unsupported escape sequence resulting in char being
> +			 * copied.
> +			 */
> +			*s++ = *string++;
> +			len--;
> +		}
> +#if 0
> +		if (*string == '\\' && len > 1) {
> +			string++;
> +			len--;
> +			const char *pos = string;
> +			long c;
> +			if ((c = strn_escseq(&pos, len)) != -1) {
> +				*s++ = c;
> +				len -= pos - string;
> +				string = pos;
>  			} else {
> -				*s = string[l];
> +				*s++ = '\\';
>  			}
> -			s++;
>  		} else {
> -			*s = string[l];
> -			s++;
> +			/* either unescaped char OR
> +			 * unsupported escape sequence resulting in char being
> +			 * copied.
> +			 */
> +			*s++ = *string++;
> +			len--;
>  		}
> +#endif
>  	}
> -
>  	*s = 0;
>  
> -	return tmp;
> +	return buffer;
> +}
> +
> +/* rewrite a quoted string substituting escaped characters for the
> + * real thing.  Strip the quotes around the string */
> +char *processquoted(const char *string, int len)
> +{
> +	/* skip leading " and eat trailing " */
> +	if (*string == '"') {
> +		len -= 2;
> +		if (len < 0)	/* start and end point to same quote */
> +			len = 0;
> +		return processunquoted(string + 1, len);
> +	}
> +
> +	/* no quotes? treat as unquoted */
> +	return processunquoted(string, len);
>  }
>  
>  char *processid(const char *string, int len)
> @@ -487,72 +520,6 @@
>  	return processunquoted(string, len);
>  }
>  
> -/* rewrite a quoted string substituting escaped characters for the
> - * real thing.  Strip the quotes around the string */
> -
> -char *processquoted(const char *string, int len)
> -{
> -	char *tmp, *s;
> -	int l;
> -	/* the result string will be shorter or equal in length */
> -	tmp = (char *)malloc(len + 1);
> -	if (!tmp)
> -		return NULL;
> -
> -	s = tmp;
> -	for (l = 1; l < len - 1; l++) {
> -		if (string[l] == '\\' && l < len - 2) {
> -			switch (string[l + 1]) {
> -			case 't':
> -				*s = '\t';
> -				l++;
> -				break;
> -			case 'n':
> -				*s = '\n';
> -				l++;
> -				break;
> -			case 'r':
> -				*s = '\r';
> -				l++;
> -				break;
> -			case '"':
> -				*s = '"';
> -				l++;
> -				break;
> -			case '\\':
> -				*s = '\\';
> -				l++;
> -				break;
> -			case '0': case '1': case '2': case '3':
> -				if ((l < len - 4) &&
> -				    strchr("0123456789", string[l + 2]) &&
> -				    strchr("0123456789", string[l + 3])) {
> -					/* three digit octal */
> -					int res = (string[l + 1] - '0') * 64 +
> -					    (string[l + 2] - '0') * 8 +
> -					    (string[l + 3] - '0');
> -					*s = res;
> -					l += 3;
> -					break;
> -				}
> -				/* fall through */
> -			default:
> -				/* any unsupported escape sequence results in all
> -				   chars being copied. */
> -				*s = string[l];
> -			}
> -			s++;
> -		} else {
> -			*s = string[l];
> -			s++;
> -		}
> -	}
> -
> -	*s = 0;
> -
> -	return tmp;
> -}
> -
>  /* strip off surrounding delimiters around variables */
>  char *process_var(const char *var)
>  {
> @@ -1270,27 +1237,82 @@
>  int test_processunquoted(void)
>  {
>  	int rc = 0;
> -	const char *teststring, *processedstring;
> +	const char *teststring;
> +	const char *resultstring;
>  
>  	teststring = "";
>  	MY_TEST(strcmp(teststring, processunquoted(teststring, strlen(teststring))) == 0,
>  			"processunquoted on empty string");
>  
> +	teststring = "\\1";
> +	resultstring = "\001";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on one digit octal");
> +
> +	teststring = "\\8";
> +	resultstring = "\\8";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on invalid octal digit \\8");
> +
> +	teststring = "\\18";
> +	resultstring = "\0018";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on one digit octal followed by invalid octal digit");
> +
> +	teststring = "\\1a";
> +	resultstring = "\001a";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on one digit octal followed by hex digit a");
> +
> +	teststring = "\\1z";
> +	resultstring = "\001z";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on one digit octal follow by char z");
> +
> +	teststring = "\\11";
> +	resultstring = "\011";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on two digit octal");
> +
> +	teststring = "\\118";
> +	resultstring = "\0118";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on two digit octal followed by invalid octal digit");
> +
> +	teststring = "\\11a";
> +	resultstring = "\011a";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on two digit octal followed by hex digit a");
> +
> +	teststring = "\\11z";
> +	resultstring = "\011z";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on two digit octal followed by char z");
> +
> +	teststring = "\\111";
> +	resultstring = "\111";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on three digit octal");
> +
> +	teststring = "\\378";
> +	resultstring = "\0378";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on three digit octal two large, taken as 2 digit octal plus trailing char");
> +
>  	teststring = "123\\421123";
> -	MY_TEST(strcmp(teststring, processunquoted(teststring, strlen(teststring))) == 0,
> -			"processunquoted on invalid octal");
> +	resultstring = "123\0421123";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on two character octal followed by valid octal digit \\421");
>  
> -/* Oh wow, our octal processing is busticated - FIXME
>  	teststring = "123\\109123";
> -	processedstring = "123\109123";
> -	MY_TEST(strcmp(processedstring, processunquoted(teststring, strlen(teststring))) == 0,
> -			"processunquoted on octal 10");
> +	resultstring = "123\109123";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on octal 109");
>  
>  	teststring = "123\\189123";
> -	processedstring = "123\189123";
> -	MY_TEST(strcmp(processedstring, processunquoted(teststring, strlen(teststring))) == 0,
> -			"processunquoted on octal 10");
> -*/
> +	resultstring = "123\189123";
> +	MY_TEST(strcmp(resultstring, processunquoted(teststring, strlen(teststring))) == 0,
> +			"processunquoted on octal 108");

The error message says "108" but teststring doesn't have "108".

>  
>  	return rc;
>  }
> @@ -1377,19 +1399,30 @@
>  			"processquoted on quoted octal \\176");
>  	free(out);
>  
> -	/* yes, our octal processing is lame; patches accepted */
> -	teststring = "\"abc\\42defg\"";
> -	processedstring = "abc\\42defg";
> +	teststring = "\"abc\\429defg\"";
> +	processedstring = "abc\0429defg";
>  	out = processquoted(teststring, strlen(teststring));
>  	MY_TEST(strcmp(processedstring, out) == 0,
> -			"processquoted passthrough quoted invalid octal \\42");
> +			"processquoted passthrough quoted invalid octal \\429");
>  	free(out);
>  
> +	teststring = "\"abcdefg\\4\"";
> +	processedstring = "abcdefg\004";
> +	out = processquoted(teststring, strlen(teststring));
> +	MY_TEST(strcmp(processedstring, out) == 0,
> +			"processquoted passthrough quoted one digit trailing octal \\4");
> +
>  	teststring = "\"abcdefg\\04\"";
> -	processedstring = "abcdefg\\04";
> +	processedstring = "abcdefg\004";
> +	out = processquoted(teststring, strlen(teststring));
> +	MY_TEST(strcmp(processedstring, out) == 0,
> +			"processquoted passthrough quoted two digit trailing octal \\04");
> +
> +	teststring = "\"abcdefg\\004\"";
> +	processedstring = "abcdefg\004";
>  	out = processquoted(teststring, strlen(teststring));
>  	MY_TEST(strcmp(processedstring, out) == 0,
> -			"processquoted passthrough quoted invalid trailing octal \\04");
> +			"processquoted passthrough quoted three digit trailing octal \\004");
>  	free(out);
>  
>  	return rc;
> 

Thanks
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20140414/87b72b08/attachment-0001.pgp>


More information about the AppArmor mailing list