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

john.johansen at canonical.com john.johansen at canonical.com
Fri Mar 7 17:31:26 UTC 2014


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>

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




More information about the AppArmor mailing list