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 <[email protected]> --- parser/libapparmor_re/parse.y | 122 +++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 37 deletions(-) --- 2.9-test.orig/parser/libapparmor_re/parse.y +++ 2.9-test/parser/libapparmor_re/parse.y @@ -156,29 +156,100 @@ %% +int isodigit(char c) +{ + return (c >= '0' && c <= '7') ? 1 : 0; +} + int octdigit(char c) { - if (c >= '0' && c <= '7') + if (isodigit(c)) + return c - '0'; + return -1; +} + +int decdigit(char c) +{ + if (isdigit(c)) return c - '0'; return -1; } int hexdigit(char c) { - if (c >= '0' && c <= '9') + if (isdigit(c)) 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; + return -1; } -int regex_lex(YYSTYPE *val, const char **pos) +/* take the largest sequence of character that is in range of 0-255 + * - will consume at most 3 digits. + * - if a 3 digit sequence has value greater than 255 it will take + * the first 2 digits. + * eg. for the sequence \444, \44 will be taken as the octal number + * and the third 4 will not be consumed (ie pos will point to it) + */ +int convert_octseq(const char **pos) { - int c; + int val, c; + + for (val = 0; (c = octdigit(**pos)) >= 0; (*pos)++) { + int tmp = (val << 3) + c; + if (tmp > 255) + break; + val = tmp; + } + + return val; +} + +/* take the largest sequence of character that is in range of 0-255 + * - will consume at most 3 digits. + * - if a 3 digit sequence has value greater than 255 it will take + * the first 2 digits. + * eg. for the sequence \d444, \d44 will be taken as the decimal number + * and the third 4 will not be consumed (ie pos will point to it) + */ +int convert_decseq(const char **pos) +{ + int val, c; + + for (val = 0; (c = decdigit(**pos)) >= 0; (*pos)++) { + int tmp = (val * 10) + c; + if (tmp > 255) + break; + val = tmp; + } + + return val; +} +/* take the largest sequence of character that is in range of 0-255 + * - will consume at most 2 digits. + * - if there is not two valid hex characters only the first will be taken + * eg. for the sequence \x4z, \x4 will be taken as the hex number + */ +int convert_hexseq(const char **pos) +{ + int val, c; + + for (val = 0; (c = hexdigit(**pos)) >= 0; (*pos)++) { + int tmp = (val << 4) + c; + if (tmp > 255) + break; + val = tmp; + } + + return val; +} + + +int regex_lex(YYSTYPE *val, const char **pos) +{ val->c = **pos; switch(*(*pos)++) { case '\0': @@ -191,6 +262,11 @@ case '\\': val->c = **pos; + if (isodigit(**pos)) { + val->c = convert_octseq(pos); + break; + } + switch(*(*pos)++) { case '\0': (*pos)--; @@ -198,55 +274,27 @@ 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)++; - } + case 'd': + val->c = convert_decseq(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)++; - } + val->c = convert_hexseq(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; -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
