X-Git-Url: http://andersk.mit.edu/gitweb/libyaml.git/blobdiff_plain/c83b67a678b13ebc7cc198ee8d0ed68225ac3e2b..HEAD:/src/scanner.c diff --git a/src/scanner.c b/src/scanner.c index b190c7e..ceee749 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -38,8 +38,8 @@ * BLOCK-END # Indentation decrease. * FLOW-SEQUENCE-START # '[' * FLOW-SEQUENCE-END # ']' - * BLOCK-SEQUENCE-START # '{' - * BLOCK-SEQUENCE-END # '}' + * FLOW-MAPPING-START # '{' + * FLOW-MAPPING-END # '}' * BLOCK-ENTRY # '-' * FLOW-ENTRY # ',' * KEY # '?' or nothing (simple keys). @@ -70,7 +70,7 @@ * %TAG !yaml! tag:yaml.org,2002: * --- * - * The correspoding sequence of tokens: + * The corresponding sequence of tokens: * * STREAM-START(utf-8) * VERSION-DIRECTIVE(1,1) @@ -615,11 +615,11 @@ yaml_parser_decrease_flow_level(yaml_parser_t *parser); */ static int -yaml_parser_roll_indent(yaml_parser_t *parser, int column, - int number, yaml_token_type_t type, yaml_mark_t mark); +yaml_parser_roll_indent(yaml_parser_t *parser, ptrdiff_t column, + ptrdiff_t number, yaml_token_type_t type, yaml_mark_t mark); static int -yaml_parser_unroll_indent(yaml_parser_t *parser, int column); +yaml_parser_unroll_indent(yaml_parser_t *parser, ptrdiff_t column); /* * Token fetchers. @@ -762,7 +762,7 @@ yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token) } /* Fetch the next token from the queue. */ - + *token = DEQUEUE(parser, parser->tokens); parser->token_available = 0; parser->tokens_parsed ++; @@ -1078,7 +1078,7 @@ yaml_parser_stale_simple_keys(yaml_parser_t *parser) if (simple_key->required) { return yaml_parser_set_scanner_error(parser, "while scanning a simple key", simple_key->mark, - "could not found expected ':'"); + "could not find expected ':'"); } simple_key->possible = 0; @@ -1103,14 +1103,7 @@ yaml_parser_save_simple_key(yaml_parser_t *parser) */ int required = (!parser->flow_level - && parser->indent == parser->mark.column); - - /* - * A simple key is required only when it is the first token in the current - * line. Therefore it is always allowed. But we add a check anyway. - */ - - assert(parser->simple_key_allowed || !required); /* Impossible. */ + && parser->indent == (ptrdiff_t)parser->mark.column); /* * If the current position may start a simple key, save it. @@ -1118,9 +1111,12 @@ yaml_parser_save_simple_key(yaml_parser_t *parser) if (parser->simple_key_allowed) { - yaml_simple_key_t simple_key = { 1, required, - parser->tokens_parsed + parser->tokens.tail - parser->tokens.head, - parser->mark }; + yaml_simple_key_t simple_key; + simple_key.possible = 1; + simple_key.required = required; + simple_key.token_number = + parser->tokens_parsed + (parser->tokens.tail - parser->tokens.head); + simple_key.mark = parser->mark; if (!yaml_parser_remove_simple_key(parser)) return 0; @@ -1146,7 +1142,7 @@ yaml_parser_remove_simple_key(yaml_parser_t *parser) if (simple_key->required) { return yaml_parser_set_scanner_error(parser, "while scanning a simple key", simple_key->mark, - "could not found expected ':'"); + "could not find expected ':'"); } } @@ -1173,6 +1169,11 @@ yaml_parser_increase_flow_level(yaml_parser_t *parser) /* Increase the flow level. */ + if (parser->flow_level == INT_MAX) { + parser->error = YAML_MEMORY_ERROR; + return 0; + } + parser->flow_level++; return 1; @@ -1187,7 +1188,7 @@ yaml_parser_decrease_flow_level(yaml_parser_t *parser) { if (parser->flow_level) { parser->flow_level --; - POP(parser, parser->simple_keys); + (void)POP(parser, parser->simple_keys); } return 1; @@ -1197,12 +1198,12 @@ yaml_parser_decrease_flow_level(yaml_parser_t *parser) * Push the current indentation level to the stack and set the new level * the current column is greater than the indentation level. In this case, * append or insert the specified token into the token queue. - * + * */ static int -yaml_parser_roll_indent(yaml_parser_t *parser, int column, - int number, yaml_token_type_t type, yaml_mark_t mark) +yaml_parser_roll_indent(yaml_parser_t *parser, ptrdiff_t column, + ptrdiff_t number, yaml_token_type_t type, yaml_mark_t mark) { yaml_token_t token; @@ -1221,6 +1222,11 @@ yaml_parser_roll_indent(yaml_parser_t *parser, int column, if (!PUSH(parser, parser->indents, parser->indent)) return 0; + if (column > INT_MAX) { + parser->error = YAML_MEMORY_ERROR; + return 0; + } + parser->indent = column; /* Create a token and insert it into the queue. */ @@ -1243,13 +1249,13 @@ yaml_parser_roll_indent(yaml_parser_t *parser, int column, /* * Pop indentation levels from the indents stack until the current level - * becomes less or equal to the column. For each intendation level, append + * becomes less or equal to the column. For each indentation level, append * the BLOCK-END token. */ static int -yaml_parser_unroll_indent(yaml_parser_t *parser, int column) +yaml_parser_unroll_indent(yaml_parser_t *parser, ptrdiff_t column) { yaml_token_t token; @@ -1258,7 +1264,7 @@ yaml_parser_unroll_indent(yaml_parser_t *parser, int column) if (parser->flow_level) return 1; - /* Loop through the intendation levels in the stack. */ + /* Loop through the indentation levels in the stack. */ while (parser->indent > column) { @@ -1630,7 +1636,7 @@ yaml_parser_fetch_key(yaml_parser_t *parser) if (!parser->flow_level) { - /* Check if we are allowed to start a new key (not nessesary simple). */ + /* Check if we are allowed to start a new key (not necessary simple). */ if (!parser->simple_key_allowed) { return yaml_parser_set_scanner_error(parser, NULL, parser->mark, @@ -1930,7 +1936,7 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) * * - in the flow context; * - in the block context, but not at the beginning of the line or - * after '-', '?', or ':' (complex value). + * after '-', '?', or ':' (complex value). */ if (!CACHE(parser, 1)) return 0; @@ -2045,7 +2051,7 @@ yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) else { yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found uknown directive name"); + start_mark, "found unknown directive name"); goto error; } @@ -2069,7 +2075,7 @@ yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) if (!IS_BREAKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "did not found expected comment or line break"); + start_mark, "did not find expected comment or line break"); goto error; } @@ -2123,7 +2129,7 @@ yaml_parser_scan_directive_name(yaml_parser_t *parser, if (string.start == string.pointer) { yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "cannot found expected directive name"); + start_mark, "could not find expected directive name"); goto error; } @@ -2393,7 +2399,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) { /* Set the handle to '' */ - handle = yaml_malloc(1); + handle = YAML_MALLOC(1); if (!handle) goto error; handle[0] = '\0'; @@ -2445,7 +2451,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) /* Set the handle to '!'. */ yaml_free(handle); - handle = yaml_malloc(2); + handle = YAML_MALLOC(2); if (!handle) goto error; handle[0] = '!'; handle[1] = '\0'; @@ -2469,7 +2475,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not found expected whitespace or line break"); + start_mark, "did not find expected whitespace or line break"); goto error; } @@ -2569,7 +2575,7 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, /* Resize the string to include the head. */ - while (string.end - string.start <= length) { + while ((size_t)(string.end - string.start) <= length) { if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) { parser->error = YAML_MEMORY_ERROR; goto error; @@ -2614,6 +2620,9 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, /* Check if it is a URI-escape sequence. */ if (CHECK(parser->buffer, '%')) { + if (!STRING_EXTEND(parser, string)) + goto error; + if (!yaml_parser_scan_uri_escapes(parser, directive, start_mark, &string)) goto error; } @@ -2764,15 +2773,15 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (IS_DIGIT(parser->buffer)) { - /* Check that the intendation is greater than 0. */ + /* Check that the indentation is greater than 0. */ if (CHECK(parser->buffer, '0')) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an intendation indicator equal to 0"); + start_mark, "found an indentation indicator equal to 0"); goto error; } - /* Get the intendation level and eat the indicator. */ + /* Get the indentation level and eat the indicator. */ increment = AS_DIGIT(parser->buffer); @@ -2786,7 +2795,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, { if (CHECK(parser->buffer, '0')) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an intendation indicator equal to 0"); + start_mark, "found an indentation indicator equal to 0"); goto error; } @@ -2823,7 +2832,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!IS_BREAKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "did not found expected comment or line break"); + start_mark, "did not find expected comment or line break"); goto error; } @@ -2836,7 +2845,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, end_mark = parser->mark; - /* Set the intendation level if it was specified. */ + /* Set the indentation level if it was specified. */ if (increment) { indent = parser->indent >= 0 ? parser->indent+increment : increment; @@ -2851,7 +2860,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 1)) goto error; - while (parser->mark.column == indent && !IS_Z(parser->buffer)) + while ((int)parser->mark.column == indent && !(IS_Z(parser->buffer))) { /* * We are at the beginning of a non-empty line. @@ -2902,7 +2911,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!READ_LINE(parser, leading_break)) goto error; - /* Eat the following intendation spaces and line breaks. */ + /* Eat the following indentation spaces and line breaks. */ if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark)) goto error; @@ -2937,8 +2946,8 @@ error: } /* - * Scan intendation spaces and line breaks for a block scalar. Determine the - * intendation level if needed. + * Scan indentation spaces and line breaks for a block scalar. Determine the + * indentation level if needed. */ static int @@ -2950,29 +2959,29 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, *end_mark = parser->mark; - /* Eat the intendation spaces and line breaks. */ + /* Eat the indentation spaces and line breaks. */ while (1) { - /* Eat the intendation spaces. */ + /* Eat the indentation spaces. */ if (!CACHE(parser, 1)) return 0; - while ((!*indent || parser->mark.column < *indent) + while ((!*indent || (int)parser->mark.column < *indent) && IS_SPACE(parser->buffer)) { SKIP(parser); if (!CACHE(parser, 1)) return 0; } - if (parser->mark.column > max_indent) - max_indent = parser->mark.column; + if ((int)parser->mark.column > max_indent) + max_indent = (int)parser->mark.column; - /* Check for a tab character messing the intendation. */ + /* Check for a tab character messing the indentation. */ - if ((!*indent || parser->mark.column < *indent) + if ((!*indent || (int)parser->mark.column < *indent) && IS_TAB(parser->buffer)) { return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found a tab character where an intendation space is expected"); + start_mark, "found a tab character where an indentation space is expected"); } /* Have we found a non-empty line? */ @@ -2996,7 +3005,7 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, *indent = 1; } - return 1; + return 1; } /* @@ -3098,7 +3107,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, else if (!single && CHECK(parser->buffer, '\\')) { - int code_length = 0; + size_t code_length = 0; if (!STRING_EXTEND(parser, string)) goto error; @@ -3151,8 +3160,8 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, *(string.pointer++) = '"'; break; - case '\'': - *(string.pointer++) = '\''; + case '/': + *(string.pointer++) = '/'; break; case '\\': @@ -3207,7 +3216,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, if (code_length) { unsigned int value = 0; - int k; + size_t k; /* Scan the character value. */ @@ -3269,6 +3278,11 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check if we are at the end of the scalar. */ + /* Fix for crash unitialized value crash + * Credit for the bug and input is to OSS Fuzz + * Credit for the fix to Alex Gaynor + */ + if (!CACHE(parser, 1)) goto error; if (CHECK(parser->buffer, single ? '\'' : '"')) break; @@ -3416,11 +3430,22 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) while (!IS_BLANKZ(parser->buffer)) { - /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */ + /* Check for "x:" + one of ',?[]{}' in the flow context. TODO: Fix the test "spec-08-13". + * This is not completely according to the spec + * See http://yaml.org/spec/1.1/#id907281 9.1.3. Plain + */ if (parser->flow_level && CHECK(parser->buffer, ':') - && !IS_BLANKZ_AT(parser->buffer, 1)) { + && ( + CHECK_AT(parser->buffer, ',', 1) + || CHECK_AT(parser->buffer, '?', 1) + || CHECK_AT(parser->buffer, '[', 1) + || CHECK_AT(parser->buffer, ']', 1) + || CHECK_AT(parser->buffer, '{', 1) + || CHECK_AT(parser->buffer, '}', 1) + ) + ) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", start_mark, "found unexpected ':'"); goto error; @@ -3430,7 +3455,7 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1)) || (parser->flow_level && - (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':') + (CHECK(parser->buffer, ',') || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') || CHECK(parser->buffer, '}')))) @@ -3493,12 +3518,12 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) { if (IS_BLANK(parser->buffer)) { - /* Check for tab character that abuse intendation. */ + /* Check for tab character that abuse indentation. */ - if (leading_blanks && parser->mark.column < indent + if (leading_blanks && (int)parser->mark.column < indent && IS_TAB(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violate intendation"); + start_mark, "found a tab character that violate indentation"); goto error; } @@ -3531,9 +3556,9 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) if (!CACHE(parser, 1)) goto error; } - /* Check intendation level. */ + /* Check indentation level. */ - if (!parser->flow_level && parser->mark.column < indent) + if (!parser->flow_level && (int)parser->mark.column < indent) break; } @@ -3562,4 +3587,3 @@ error: return 0; } -