Fix: octal and hex string handling
[babeltrace.git] / formats / ctf / metadata / ctf-parser.y
index a31e9637e24b930d8060fffe988035a282d2e6bf..61ec47dd28fe80fcfc0674674233a819a2d272d3 100644 (file)
@@ -83,6 +83,15 @@ static const char *node_type_to_str[] = {
 #undef ENTRY
 };
 
+/*
+ * Static node for out of memory errors. Only "type" is used. lineno is
+ * always left at 0. The rest of the node content can be overwritten,
+ * but is never used.
+ */
+static struct ctf_node error_node = {
+       .type = NODE_ERROR,
+};
+
 BT_HIDDEN
 const char *node_type(struct ctf_node *node)
 {
@@ -109,41 +118,6 @@ static struct gc_string *gc_string_alloc(struct ctf_scanner *scanner,
        return gstr;
 }
 
-/*
- * note: never use gc_string_append on a string that has external references.
- * gsrc will be garbage collected immediately, and gstr might be.
- * Should only be used to append characters to a string literal or constant.
- */
-BT_HIDDEN
-struct gc_string *gc_string_append(struct ctf_scanner *scanner,
-                                  struct gc_string *gstr,
-                                  struct gc_string *gsrc)
-{
-       size_t newlen = strlen(gsrc->s) + strlen(gstr->s) + 1;
-       size_t alloclen;
-
-       /* TODO: could be faster with find first bit or glib Gstring */
-       /* sizeof long to account for malloc header (int or long ?) */
-       for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + newlen;
-            alloclen *= 2);
-
-       if (alloclen > gstr->alloclen) {
-               struct gc_string *newgstr;
-
-               newgstr = gc_string_alloc(scanner, newlen);
-               strcpy(newgstr->s, gstr->s);
-               strcat(newgstr->s, gsrc->s);
-               bt_list_del(&gstr->gc);
-               free(gstr);
-               gstr = newgstr;
-       } else {
-               strcat(gstr->s, gsrc->s);
-       }
-       bt_list_del(&gsrc->gc);
-       free(gsrc);
-       return gstr;
-}
-
 void setstring(struct ctf_scanner *scanner, YYSTYPE *lvalp, const char *src)
 {
        lvalp->gs = gc_string_alloc(scanner, strlen(src) + 1);
@@ -161,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)
@@ -184,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;
@@ -220,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))
+                               if (parse_base_sequence(src, len, pos - 1,
+                                               oct_buffer, &oct_len, 8))
                                        return -1;
-                               if (!isdigit((int) src[pos]) || !isdigit((int) src[pos+1]) || !isdigit((int) src[pos+2]))
-                                       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;
@@ -362,8 +388,10 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner,
        struct ctf_node *node;
 
        node = malloc(sizeof(*node));
-       if (!node)
-               return NULL;
+       if (!node) {
+               printfl_fatal(yyget_lineno(scanner->scanner), "out of memory");
+               return &error_node;
+       }
        memset(node, 0, sizeof(*node));
        node->type = type;
        node->lineno = yyget_lineno(scanner->scanner);
@@ -373,6 +401,7 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner,
 
        switch (type) {
        case NODE_ROOT:
+               node->type = NODE_ERROR;
                printfn_fatal(node, "trying to create root node");
                break;
 
@@ -453,6 +482,7 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner,
 
        case NODE_UNKNOWN:
        default:
+               node->type = NODE_ERROR;
                printfn_fatal(node, "unknown node type '%d'", (int) type);
                break;
        }
@@ -1234,9 +1264,7 @@ postfix_expression:
                }
        |       LPAREN unary_expression RPAREN
                {
-                       $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
-                       $$->u.unary_expression.type = UNARY_NESTED;
-                       $$->u.unary_expression.u.nested_exp = $2;
+                       $$ = $2;
                }
        |       postfix_expression LSBRAC unary_expression RSBRAC
                {
This page took 0.025969 seconds and 4 git commands to generate.