Fix: octal and hex string handling
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 17 Apr 2013 17:05:21 +0000 (13:05 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 18 Apr 2013 14:24:59 +0000 (10:24 -0400)
Following C99:

Octal does not start by \o, but rather is in the form:

  \n \nn or \nnn

  where n is octal.

Hexadecimal is:

  \xH \xHH or \xHHH

  where H is hexadecimal.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
formats/ctf/metadata/ctf-parser.y

index 40cf65e9a03605922d631a83bcb7b0bc49dccdd1..61ec47dd28fe80fcfc0674674233a819a2d272d3 100644 (file)
@@ -135,6 +135,56 @@ int str_check(size_t str_len, size_t offset, size_t len)
        return 0;
 }
 
+static
+int bt_isodigit(int c)
+{
+       switch (c) {
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static
+int parse_base_sequence(const char *src, size_t len, size_t pos,
+               char *buffer, size_t *buf_len, int base)
+{
+       const size_t max_char = 3;
+       int nr_char = 0;
+
+       while (!str_check(len, pos, 1) && nr_char < max_char) {
+               char c = src[pos++];
+
+               if (base == 8) {
+                       if (bt_isodigit(c))
+                               buffer[nr_char++] = c;
+                       else
+                               break;
+               } else if (base == 16) {
+                       if (isxdigit(c))
+                               buffer[nr_char++] = c;
+                       else
+                               break;
+
+               } else {
+                       /* Unsupported base */
+                       return -1;
+               }
+       }
+       assert(nr_char > 0);
+       buffer[nr_char] = '\0';
+       *buf_len = nr_char;
+       return 0;
+}
+
 static
 int import_basic_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
                size_t len, const char *src, char delim)
@@ -158,9 +208,6 @@ int import_basic_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
                        c = src[pos++];
 
                        switch (c) {
-                       case '0':
-                               c = '\0';
-                               break;
                        case 'a':
                                c = '\a';
                                break;
@@ -194,28 +241,33 @@ int import_basic_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
                        case '?':
                                c = '?';
                                break;
-                       case 'o':
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
                        {
-                               size_t oct_len = 3;
+                               char oct_buffer[4];
+                               size_t oct_len;
 
-                               if (str_check(len, pos, oct_len))
-                                       return -1;
-                               if (!isdigit((int) src[pos]) || !isdigit((int) src[pos+1]) || !isdigit((int) src[pos+2]))
+                               if (parse_base_sequence(src, len, pos - 1,
+                                               oct_buffer, &oct_len, 8))
                                        return -1;
-                               char oct_buffer[4] = { src[pos], src[pos+1], src[pos+2], '\0' };
                                c = strtoul(&oct_buffer[0], NULL, 8);
-                               pos += oct_len;
+                               pos += oct_len - 1;
                                break;
                        }
                        case 'x':
                        {
-                               size_t hex_len = 2;
+                               char hex_buffer[4];
+                               size_t hex_len;
 
-                               if (str_check(len, pos, hex_len))
-                                       return -1;
-                               if (!isxdigit((int) src[pos]) || !isxdigit((int) src[pos+1]))
+                               if (parse_base_sequence(src, len, pos,
+                                               hex_buffer, &hex_len, 16))
                                        return -1;
-                               char hex_buffer[3] = { src[pos], src[pos+1], '\0' };
                                c = strtoul(&hex_buffer[0], NULL, 16);
                                pos += hex_len;
                                break;
This page took 0.026733 seconds and 4 git commands to generate.