Skip to content

Commit 88a6bfd

Browse files
committed
Add yet more include tests
1 parent 3c0a14d commit 88a6bfd

File tree

3 files changed

+265
-15
lines changed

3 files changed

+265
-15
lines changed

src/generic/format.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ static really_inline int32_t parse_dollar_include(
259259

260260
// $INCLUDE directive MAY specify an origin
261261
take(parser, token);
262-
if (is_contiguous_or_quoted(token)) {
262+
if (is_contiguous(token)) {
263263
if (scan_name(token->data, token->length, name.octets, &name.length) != 0) {
264264
zone_close_file(parser, file);
265265
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(&include));
@@ -376,8 +376,14 @@ static inline int32_t parse(parser_t *parser)
376376

377377
code = parse_rr(parser, &token);
378378
} else if (is_end_of_file(&token)) {
379-
if (parser->file->end_of_file == NO_MORE_DATA)
380-
break;
379+
if (parser->file->end_of_file == NO_MORE_DATA) {
380+
if (!parser->file->includer)
381+
break;
382+
file_t *file = parser->file;
383+
parser->file = parser->file->includer;
384+
parser->owner = &parser->file->owner;
385+
zone_close_file(parser, file);
386+
}
381387
} else if (is_line_feed(&token)) {
382388
assert(token.code == LINE_FEED);
383389
adjust_line_count(parser->file);

src/generic/parser.h

-12
Original file line numberDiff line numberDiff line change
@@ -443,12 +443,6 @@ static never_inline void maybe_take(parser_t *parser, token_t *token)
443443
SYNTAX_ERROR(parser, token, "Missing closing brace");
444444
token->data = end_of_file;
445445
token->length = 1;
446-
if (!parser->file->includer)
447-
return;
448-
file_t *file = parser->file;
449-
parser->file = parser->file->includer;
450-
parser->owner = &parser->file->owner;
451-
zone_close_file(parser, file);
452446
return;
453447
} else if (unlikely((code = advance(parser)) < 0)) {
454448
ERROR(parser, token, code);
@@ -912,12 +906,6 @@ static never_inline int32_t maybe_take_delimiter(
912906
SYNTAX_ERROR(parser, token, "Missing closing brace");
913907
token->data = end_of_file;
914908
token->length = 1;
915-
if (!parser->file->includer)
916-
return 0;
917-
file_t *file = parser->file;
918-
parser->file = parser->file->includer;
919-
parser->owner = &parser->file->owner;
920-
zone_close_file(parser, file);
921909
return 0;
922910
}
923911

tests/syntax.c

+256
Original file line numberDiff line numberDiff line change
@@ -715,11 +715,14 @@ void bad_origins(void **state)
715715

716716
static const char *no_origin = PAD("$ORIGIN ; no origin");
717717
static const char *extra_origin = PAD("$ORIGIN a. b.");
718+
static const char *relative_origin = PAD("$ORIGIN foo");
718719

719720
code = parse(no_origin, &count);
720721
assert_int_equal(code, ZONE_SYNTAX_ERROR);
721722
code = parse(extra_origin, &count);
722723
assert_int_equal(code, ZONE_SYNTAX_ERROR);
724+
code = parse(relative_origin, &count);
725+
assert_int_equal(code, ZONE_SYNTAX_ERROR);
723726
}
724727

725728
/*!cmocka */
@@ -753,3 +756,256 @@ void bad_includes(void **state)
753756
free(include);
754757
assert_int_equal(code, ZONE_SYNTAX_ERROR);
755758
}
759+
760+
static int32_t include_origin_callback(
761+
zone_parser_t *parser,
762+
const zone_name_t *owner,
763+
uint16_t type,
764+
uint16_t class,
765+
uint32_t ttl,
766+
uint16_t rdlength,
767+
const uint8_t *rdata,
768+
void *user_data)
769+
{
770+
(void)parser;
771+
(void)type;
772+
(void)class;
773+
(void)ttl;
774+
(void)rdlength;
775+
(void)rdata;
776+
(void)user_data;
777+
778+
static const uint8_t foobaz[] = { 3, 'f', 'o', 'o', 3, 'b', 'a', 'z', 0 };
779+
780+
assert(owner);
781+
if (owner->length != 9 || memcmp(owner->octets, foobaz, 9) != 0)
782+
return ZONE_SEMANTIC_ERROR;
783+
784+
return 0;
785+
}
786+
787+
/*!cmocka */
788+
void include_with_origin(void **state)
789+
{
790+
(void)state;
791+
792+
char *path = generate_include("foo TXT bar");
793+
assert_non_null(path);
794+
char dummy[32];
795+
int length = snprintf(dummy, sizeof(dummy), "$INCLUDE \"%s\" baz.", path);
796+
assert_true(length > 0 && length < INT_MAX - ZONE_PADDING_SIZE);
797+
char *include = malloc((size_t)length + 1 + ZONE_PADDING_SIZE);
798+
assert_non_null(include);
799+
(void)snprintf(include, (size_t)length + 1, "$INCLUDE \"%s\" baz.", path);
800+
801+
zone_parser_t parser;
802+
zone_name_buffer_t name;
803+
zone_rdata_buffer_t rdata;
804+
zone_buffers_t buffers = { 1, &name, &rdata };
805+
zone_options_t options = { 0 };
806+
static const uint8_t origin[] = { 3, 'b', 'a', 'r', 0 };
807+
808+
options.accept.callback = &include_origin_callback;
809+
options.origin.octets = origin;
810+
options.origin.length = sizeof(origin);
811+
options.default_ttl = 3600;
812+
options.default_class = 1;
813+
814+
int32_t code = zone_parse_string(&parser, &options, &buffers, include, strlen(include), NULL);
815+
816+
remove_include(path);
817+
free(path);
818+
free(include);
819+
820+
assert_int_equal(code, ZONE_SUCCESS);
821+
}
822+
823+
static int32_t no_origin_callback(
824+
zone_parser_t *parser,
825+
const zone_name_t *owner,
826+
uint16_t type,
827+
uint16_t class,
828+
uint32_t ttl,
829+
uint16_t rdlength,
830+
const uint8_t *rdata,
831+
void *user_data)
832+
{
833+
(void)parser;
834+
(void)type;
835+
(void)class;
836+
(void)ttl;
837+
(void)rdlength;
838+
(void)rdata;
839+
(void)user_data;
840+
841+
static const uint8_t foobar[] = { 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
842+
843+
assert(owner);
844+
if (owner->length != 9 || memcmp(owner->octets, foobar, 9) != 0)
845+
return ZONE_SEMANTIC_ERROR;
846+
847+
return 0;
848+
}
849+
850+
/*!cmocka */
851+
void include_without_origin(void **state)
852+
{
853+
(void)state;
854+
855+
char *path = generate_include("foo TXT bar");
856+
assert_non_null(path);
857+
char dummy[32];
858+
#define FMT "$INCLUDE \"%s\""
859+
int length = snprintf(dummy, sizeof(dummy), "$INCLUDE \"%s\"", path);
860+
assert_true(length > 0 && length < INT_MAX - ZONE_PADDING_SIZE);
861+
char *include = malloc((size_t)length + 1 + ZONE_PADDING_SIZE);
862+
assert_non_null(include);
863+
(void)snprintf(include, (size_t)length + 1, "$INCLUDE \"%s\"", path);
864+
#undef FMT
865+
866+
zone_parser_t parser;
867+
zone_name_buffer_t name;
868+
zone_rdata_buffer_t rdata;
869+
zone_buffers_t buffers = { 1, &name, &rdata };
870+
zone_options_t options = { 0 };
871+
static const uint8_t origin[] = { 3, 'b', 'a', 'r', 0 };
872+
873+
options.accept.callback = &no_origin_callback;
874+
options.origin.octets = origin;
875+
options.origin.length = sizeof(origin);
876+
options.default_ttl = 3600;
877+
options.default_class = 1;
878+
879+
int32_t code = zone_parse_string(&parser, &options, &buffers, include, strlen(include), NULL);
880+
881+
remove_include(path);
882+
free(path);
883+
free(include);
884+
885+
assert_int_equal(code, ZONE_SUCCESS);
886+
}
887+
888+
static int32_t reinstate_callback(
889+
zone_parser_t *parser,
890+
const zone_name_t *owner,
891+
uint16_t type,
892+
uint16_t class,
893+
uint32_t ttl,
894+
uint16_t rdlength,
895+
const uint8_t *rdata,
896+
void *user_data)
897+
{
898+
size_t *count = (size_t *)user_data;
899+
900+
static const uint8_t foobar[] = { 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
901+
static const uint8_t foobaz[] = { 3, 'f', 'o', 'o', 3, 'b', 'a', 'z', 0 };
902+
903+
(void)parser;
904+
(void)type;
905+
(void)class;
906+
(void)ttl;
907+
(void)rdlength;
908+
(void)rdata;
909+
910+
switch (*count) {
911+
case 0:
912+
if (owner->length != 9 || memcmp(owner->octets, foobar, 9) != 0)
913+
return ZONE_SYNTAX_ERROR;
914+
break;
915+
case 1: // include
916+
if (owner->length != 9 || memcmp(owner->octets, foobaz, 9) != 0)
917+
return ZONE_SYNTAX_ERROR;
918+
break;
919+
case 2:
920+
if (owner->length != 9 || memcmp(owner->octets, foobar, 9) != 0)
921+
return ZONE_SYNTAX_ERROR;
922+
break;
923+
}
924+
925+
(*count)++;
926+
return 0;
927+
}
928+
929+
/*!cmocka */
930+
void owner_is_reinstated(void **state)
931+
{
932+
// check closing of include reinstates owner
933+
934+
(void)state;
935+
char *path = generate_include("foo.baz. TXT foobar");
936+
assert_non_null(path);
937+
char dummy[64];
938+
#define FMT \
939+
"foo.bar. TXT foobar\n" \
940+
"$INCLUDE \"%s\" baz.\n" \
941+
" TXT foobar"
942+
int length = snprintf(dummy, sizeof(dummy), FMT, path);
943+
assert_true(length > 0 && length < INT_MAX - ZONE_PADDING_SIZE);
944+
char *include = malloc((size_t)length + 1 + ZONE_PADDING_SIZE);
945+
assert_non_null(include);
946+
(void)snprintf(include, (size_t)length + 1, FMT, path);
947+
#undef FMT
948+
949+
size_t count = 0;
950+
zone_parser_t parser;
951+
zone_name_buffer_t name;
952+
zone_rdata_buffer_t rdata;
953+
zone_buffers_t buffers = { 1, &name, &rdata };
954+
zone_options_t options = { 0 };
955+
static const uint8_t origin[] = { 3, 'b', 'a', 'r', 0 };
956+
957+
options.accept.callback = &reinstate_callback;
958+
options.origin.octets = origin;
959+
options.origin.length = sizeof(origin);
960+
options.default_ttl = 3600;
961+
options.default_class = 1;
962+
963+
int32_t code = zone_parse_string(&parser, &options, &buffers, include, strlen(include), &count);
964+
remove_include(path);
965+
free(path);
966+
free(include);
967+
assert_int_equal(code, ZONE_SUCCESS);
968+
assert_true(count == 3);
969+
}
970+
971+
/*!cmocka */
972+
void origin_is_reinstated(void **state)
973+
{
974+
// check closing of include reinstates origin
975+
976+
(void)state;
977+
char *path = generate_include("foo.baz. TXT foobar");
978+
assert_non_null(path);
979+
char dummy[64];
980+
#define FMT \
981+
"foo.bar. TXT foobar\n" \
982+
"$INCLUDE \"%s\" baz.\n" \
983+
"foo TXT foobar"
984+
int length = snprintf(dummy, sizeof(dummy), FMT, path);
985+
assert_true(length > 0 && length < INT_MAX - ZONE_PADDING_SIZE);
986+
char *include = malloc((size_t)length + 1 + ZONE_PADDING_SIZE);
987+
assert_non_null(include);
988+
(void)snprintf(include, (size_t)length + 1, FMT, path);
989+
#undef FMT
990+
991+
size_t count = 0;
992+
zone_parser_t parser;
993+
zone_name_buffer_t name;
994+
zone_rdata_buffer_t rdata;
995+
zone_buffers_t buffers = { 1, &name, &rdata };
996+
zone_options_t options = { 0 };
997+
static const uint8_t origin[] = { 3, 'b', 'a', 'r', 0 };
998+
999+
options.accept.callback = &reinstate_callback;
1000+
options.origin.octets = origin;
1001+
options.origin.length = sizeof(origin);
1002+
options.default_ttl = 3600;
1003+
options.default_class = 1;
1004+
1005+
int32_t code = zone_parse_string(&parser, &options, &buffers, include, strlen(include), &count);
1006+
remove_include(path);
1007+
free(path);
1008+
free(include);
1009+
assert_int_equal(code, ZONE_SUCCESS);
1010+
assert_true(count == 3);
1011+
}

0 commit comments

Comments
 (0)