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 <[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
