From e2ab8ea481ab5652fbe954107a4958ecf162f453 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 4 Nov 2025 13:34:47 +0100 Subject: [PATCH 1/2] Allow skipping syntax errors with an option This can be useful for programs that process zones that do not need the zone to be in perfect order. For example programs that count the number of delegations. --- include/zone.h | 4 ++++ src/bench.c | 28 +++++++++++++++++++--------- src/generic/format.h | 6 ++++-- src/generic/parser.h | 3 ++- 4 files changed, 29 insertions(+), 12 deletions(-) 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); From fea0bd1231f06f043ef150539a074aa2c27b3db4 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 4 Nov 2025 13:47:50 +0100 Subject: [PATCH 2/2] Correct DS lengths in tests too --- tests/semantics.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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;