diff --git a/include/zone.h b/include/zone.h index b7e27a8..d0a0bb3 100644 --- a/include/zone.h +++ b/include/zone.h @@ -437,6 +437,10 @@ typedef struct { a secondary as data may have been transferred over AXFR/IXFR that would have triggered an error otherwise. */ bool secondary; + /** Programs that process zones that do not need the zone to be in perfect + order (for example programs that count the number of delegations), + may be even more lenient and allow syntax errors. */ + bool skip_syntax_errors; /** Disable $INCLUDE directive. */ /** Useful in setups where untrusted input may be offered. */ bool no_includes; diff --git a/src/bench.c b/src/bench.c index 9c0aac7..3fcf621 100644 --- a/src/bench.c +++ b/src/bench.c @@ -157,6 +157,8 @@ static void help(const char *program) "\n" "Options:\n" " -h Display available options.\n" + " -s Continue parsing after a semantic error\n" + " -S Continue parsing after a semantic or syntax error\n" " -t target Select target (default:%s)\n" "\n" "Kernels:\n"; @@ -183,7 +185,16 @@ int main(int argc, char *argv[]) if (*slash == '/' || *slash == '\\') program = slash + 1; - for (int option; (option = getopt(argc, argv, "ht:")) != -1;) { + zone_options_t options; + memset(&options, 0, sizeof(options)); + options.pretty_ttls = true; + options.origin.octets = root; + options.origin.length = 1; + options.accept.callback = &bench_accept; + options.default_ttl = 3600; + options.default_class = 1; + + for (int option; (option = getopt(argc, argv, "ht:sS")) != -1;) { switch (option) { case 'h': help(program); @@ -191,6 +202,13 @@ int main(int argc, char *argv[]) case 't': name = optarg; break; + case 's': + options.secondary = true; + break; + case 'S': + options.secondary = true; + options.skip_syntax_errors = true; + break; default: usage(program); } @@ -213,14 +231,6 @@ int main(int argc, char *argv[]) zone_parser_t parser; memset(&parser, 0, sizeof(parser)); - zone_options_t options; - memset(&options, 0, sizeof(options)); - options.pretty_ttls = true; - options.origin.octets = root; - options.origin.length = 1; - options.accept.callback = &bench_accept; - options.default_ttl = 3600; - options.default_class = 1; zone_name_buffer_t owner; zone_rdata_buffer_t rdata; diff --git a/src/generic/format.h b/src/generic/format.h index 76542c2..8ad29c0 100644 --- a/src/generic/format.h +++ b/src/generic/format.h @@ -389,8 +389,10 @@ static inline int32_t parse(parser_t *parser) if ((code = parse_owner(parser, &rr, &fields[0], &token)) < 0) return code; - if ((code = take_contiguous(parser, &rr, &fields[0], &token)) < 0) - return code; + if ((code = take_contiguous(parser, &rr, &fields[0], &token)) < 0) { + if(code == ZONE_SYNTAX_ERROR && !parser->options.skip_syntax_errors) + return code; + } } else if (unlikely(!parser->owner->length)) { SYNTAX_ERROR(parser, "No last stated owner"); } diff --git a/src/generic/parser.h b/src/generic/parser.h index 34a90e5..574e0cc 100644 --- a/src/generic/parser.h +++ b/src/generic/parser.h @@ -209,7 +209,8 @@ static never_inline int32_t raise_error( { va_list arguments; uint32_t category = ZONE_ERROR; - if (code == ZONE_SEMANTIC_ERROR && parser->options.secondary) + if ((code == ZONE_SEMANTIC_ERROR && parser->options.secondary) + || (code == ZONE_SYNTAX_ERROR && parser->options.skip_syntax_errors)) category = ZONE_WARNING; va_start(arguments, format); zone_vlog(parser, category, format, arguments); diff --git a/tests/semantics.c b/tests/semantics.c index 7fcfe9d..df85a35 100644 --- a/tests/semantics.c +++ b/tests/semantics.c @@ -100,13 +100,13 @@ void ds_digest_lengths(void **state) { 4, 47, ZONE_SEMANTIC_ERROR }, { 4, 49, ZONE_SEMANTIC_ERROR }, // 5: GOST R 34.10-2012 - { 5, 48, ZONE_SUCCESS }, - { 5, 47, ZONE_SEMANTIC_ERROR }, - { 5, 49, ZONE_SEMANTIC_ERROR }, + { 5, 32, ZONE_SUCCESS }, + { 5, 31, ZONE_SEMANTIC_ERROR }, + { 5, 33, ZONE_SEMANTIC_ERROR }, // 6: SM3 - { 6, 48, ZONE_SUCCESS }, - { 6, 47, ZONE_SEMANTIC_ERROR }, - { 6, 49, ZONE_SEMANTIC_ERROR } + { 6, 32, ZONE_SUCCESS }, + { 6, 31, ZONE_SEMANTIC_ERROR }, + { 6, 33, ZONE_SEMANTIC_ERROR } }; (void)state;