Commits

Kirill Simonov committed b77d422

Prevent node index overflow (Reported by Florian Weimer).

Comments (0)

Files changed (2)

     int index;
     yaml_char_t *tag = first_event->data.scalar.tag;
 
+    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
+
     if (!tag || strcmp((char *)tag, "!") == 0) {
         yaml_free(tag);
         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
     int index, item_index;
     yaml_char_t *tag = first_event->data.sequence_start.tag;
 
+    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
+
     if (!tag || strcmp((char *)tag, "!") == 0) {
         yaml_free(tag);
         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
     if (!yaml_parser_parse(parser, &event)) return 0;
 
     while (event.type != YAML_SEQUENCE_END_EVENT) {
+        if (!STACK_LIMIT(parser,
+                    parser->document->nodes.start[index-1].data.sequence.items,
+                    INT_MAX-1)) return 0;
         item_index = yaml_parser_load_node(parser, &event);
         if (!item_index) return 0;
         if (!PUSH(parser,
     yaml_node_pair_t pair;
     yaml_char_t *tag = first_event->data.mapping_start.tag;
 
+    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
+
     if (!tag || strcmp((char *)tag, "!") == 0) {
         yaml_free(tag);
         tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
     if (!yaml_parser_parse(parser, &event)) return 0;
 
     while (event.type != YAML_MAPPING_END_EVENT) {
+        if (!STACK_LIMIT(parser,
+                    parser->document->nodes.start[index-1].data.mapping.pairs,
+                    INT_MAX-1)) return 0;
         pair.key = yaml_parser_load_node(parser, &event);
         if (!pair.key) return 0;
         if (!yaml_parser_parse(parser, &event)) return 0;

src/yaml_private.h

 #define STACK_EMPTY(context,stack)                                              \
     ((stack).start == (stack).top)
 
+#define STACK_LIMIT(context,stack,size)                                         \
+    ((stack).top - (stack).start < (size) ?                                     \
+        1 :                                                                     \
+        ((context)->error = YAML_MEMORY_ERROR,                                  \
+         0))
+
 #define PUSH(context,stack,value)                                               \
     (((stack).top != (stack).end                                                \
       || yaml_stack_extend((void **)&(stack).start,                             \