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

Reply via email to