diff --git a/src/scanner.c b/src/scanner.c index e7ffd83f..a4006fb4 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -2622,7 +2622,7 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int uri_char, int directive, * The set of characters that may appear in URI is as follows: * * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', - * '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%'. + * '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%', '#'. * * If we are inside a verbatim tag <...> (parameter uri_char is true) * then also the following flow indicators are allowed: @@ -2638,6 +2638,7 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int uri_char, int directive, || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~') || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'') || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')') + || CHECK(parser->buffer, '#') || (uri_char && ( CHECK(parser->buffer, ',') || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 17a9c671..902247f4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -18,6 +18,7 @@ foreach(name IN ITEMS run-scanner test-nesting test-reader + test-tag-uri test-version ) add_yaml_executable(${name}) @@ -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 tag-uri COMMAND test-tag-uri) diff --git a/tests/Makefile.am b/tests/Makefile.am index 8b8a456f..404f6034 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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-tag-uri +check_PROGRAMS = test-version test-reader test-nesting test-tag-uri noinst_PROGRAMS = run-scanner run-parser run-loader run-emitter run-dumper \ example-reformatter example-reformatter-alt \ example-deconstructor example-deconstructor-alt \ diff --git a/tests/test-tag-uri.c b/tests/test-tag-uri.c new file mode 100644 index 00000000..5d273f17 --- /dev/null +++ b/tests/test-tag-uri.c @@ -0,0 +1,74 @@ +#include + +#include +#include +#include + +#ifdef NDEBUG +#undef NDEBUG +#endif +#include + +static const struct { + const char *title; + const char *input; + const char *tag; +} cases[] = { + {"fragment in tag directive prefix", + "%TAG ! http://www.w3.org/2001/XMLSchema#\n---\n!foo bar\n", + "http://www.w3.org/2001/XMLSchema#foo"}, + {"fragment in verbatim tag", + "! bar\n", + "http://example.com/#foo"}, + {"fragment in local tag", + "!foo#fragment bar\n", + "!foo#fragment"}, + {"fragment in named handle suffix", + "%TAG !e! http://example.com/\n---\n!e!foo#fragment bar\n", + "http://example.com/foo#fragment"}, + {"escaped fragment in verbatim tag", + "! bar\n", + "http://example.com/#foo"}, + {"comments after directive and scalar", + "%TAG !e! http://example.com/ # comment\n" + "---\n!e!foo bar # comment\n", + "http://example.com/foo"}, + {"comment after local tag", + "!foo # comment\nbar\n", + "!foo"} +}; + +int +main(void) +{ + size_t i; + int failures = 0; + + for (i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) { + yaml_parser_t parser; + yaml_document_t document; + yaml_node_t *root; + + assert(yaml_parser_initialize(&parser)); + yaml_parser_set_input_string(&parser, + (const unsigned char *)cases[i].input, strlen(cases[i].input)); + + if (!yaml_parser_load(&parser, &document)) { + fprintf(stderr, "%s: %s\n", cases[i].title, + parser.problem ? parser.problem : "no error detail"); + failures++; + } + else { + root = yaml_document_get_root_node(&document); + assert(root && root->type == YAML_SCALAR_NODE); + assert(strcmp((const char *)root->tag, cases[i].tag) == 0); + assert(root->data.scalar.length == 3); + assert(memcmp(root->data.scalar.value, "bar", 3) == 0); + yaml_document_delete(&document); + } + + yaml_parser_delete(&parser); + } + + return failures ? EXIT_FAILURE : EXIT_SUCCESS; +}