Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -1945,8 +1945,12 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser)

if (!CACHE(parser, 1)) return 0;

if (parser->mark.column == 0 && IS_BOM(parser->buffer))
if (parser->mark.column == 0 && IS_BOM(parser->buffer)) {
SKIP(parser);
/* A BOM is not content, so it must not advance the column: SKIP()
increments mark.column, so reset it here (#334). */
parser->mark.column = 0;
}

/*
* Eat whitespaces.
Expand Down
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ foreach(name IN ITEMS
run-parser
run-parser-test-suite
run-scanner
test-bom
test-nesting
test-reader
test-version
Expand All @@ -26,4 +27,5 @@ endforeach()
add_test(NAME version COMMAND test-version)
add_test(NAME reader COMMAND test-reader)
add_test(NAME nesting COMMAND test-nesting)
add_test(NAME bom COMMAND test-bom)

4 changes: 2 additions & 2 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
AM_CPPFLAGS = -I$(top_srcdir)/include -Wall
#AM_CFLAGS = -Wno-pointer-sign
LDADD = $(top_builddir)/src/libyaml.la
TESTS = test-version test-reader test-nesting
check_PROGRAMS = test-version test-reader test-nesting
TESTS = test-version test-reader test-nesting test-bom
check_PROGRAMS = test-version test-reader test-nesting test-bom
noinst_PROGRAMS = run-scanner run-parser run-loader run-emitter run-dumper \
example-reformatter example-reformatter-alt \
example-deconstructor example-deconstructor-alt \
Expand Down
67 changes: 67 additions & 0 deletions tests/test-bom.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <yaml.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef NDEBUG
#undef NDEBUG
#endif
#include <assert.h>

/*
* Regression test for a leading BOM being counted as a column when the input
* encoding is set explicitly (https://github.com/yaml/libyaml/issues/334).
*
* With an explicit encoding the reader does not strip the BOM, so the scanner
* skips it instead. That skip must not advance the column: otherwise the first
* token starts at column 1 and a root-level block mapping fails to parse with
* "did not find expected <document start>".
*/

static int
parse_scalars(const char *input, size_t length, yaml_encoding_t encoding)
{
yaml_parser_t parser;
yaml_event_t event;
int scalars = 0;
int done = 0;

assert(yaml_parser_initialize(&parser));
yaml_parser_set_encoding(&parser, encoding);
yaml_parser_set_input_string(&parser, (const unsigned char *)input, length);

while (!done) {
if (!yaml_parser_parse(&parser, &event)) {
scalars = -1;
break;
}
if (event.type == YAML_SCALAR_EVENT)
scalars++;
done = (event.type == YAML_STREAM_END_EVENT);
yaml_event_delete(&event);
}

yaml_parser_delete(&parser);
return scalars;
}

int
main(void)
{
/* UTF-8 BOM followed by a root-level block mapping with two entries. */
const char input[] = "\xEF\xBB\xBF" "a: b\nc: d\n";
size_t length = sizeof(input) - 1;

printf("BOM + explicit UTF-8 encoding ... ");
fflush(stdout);
assert(parse_scalars(input, length, YAML_UTF8_ENCODING) == 4);
printf("OK\n");

printf("BOM + detected encoding ... ");
fflush(stdout);
assert(parse_scalars(input, length, YAML_ANY_ENCODING) == 4);
printf("OK\n");

return 0;
}