1212#include <string.h>
1313#include <stdlib.h>
1414#include <cmocka.h>
15+ #include <limits.h>
1516#if !_WIN32
1617#include <unistd.h>
1718#endif
@@ -125,6 +126,42 @@ int setup(void **state)
125126 return -1 ;
126127}
127128
129+ static char * generate_include (const char * text )
130+ {
131+ char * path = tempnam (NULL , "zone" );
132+ if (path ) {
133+ FILE * handle = fopen (path , "wbx" );
134+ if (handle ) {
135+ int result = fputs (text , handle );
136+ (void )fclose (handle );
137+ if (result != EOF )
138+ return path ;
139+ }
140+ free (path );
141+ }
142+ return NULL ;
143+ }
144+
145+ static int32_t parse (
146+ const zone_options_t * options , const char * text , void * user_data )
147+ {
148+ zone_parser_t parser = { 0 };
149+ zone_name_buffer_t name ;
150+ zone_rdata_buffer_t rdata ;
151+ zone_buffers_t buffers = { 1 , & name , & rdata };
152+
153+ int32_t code ;
154+ size_t length = strlen (text );
155+ char * string = malloc (length + 1 + ZONE_PADDING_SIZE );
156+ assert_non_null (string );
157+ memcpy (string , text , length );
158+ string [length ] = '\0' ;
159+
160+ code = zone_parse_string (& parser , options , & buffers , string , length , user_data );
161+ free (string );
162+ return code ;
163+ }
164+
128165diagnostic_pop ()
129166
130167static int32_t add_rr (
@@ -216,12 +253,12 @@ static int32_t no_such_file_accept(
216253
217254static void no_such_file_log (
218255 zone_parser_t * parser ,
219- uint32_t category ,
256+ uint32_t priority ,
220257 const char * message ,
221258 void * user_data )
222259{
223260 (void )parser ;
224- (void )category ;
261+ (void )priority ;
225262 if (!strstr (message , "no such file" ))
226263 return ;
227264 no_file_test_t * test = (no_file_test_t * )user_data ;
@@ -232,10 +269,6 @@ static void no_such_file_log(
232269void the_include_that_wasnt (void * * state )
233270{
234271 // test $INCLUDE of nonexistent file is handled gracefully
235- zone_parser_t parser = { 0 };
236- zone_name_buffer_t name ;
237- zone_rdata_buffer_t rdata ;
238- zone_buffers_t buffers = { 1 , & name , & rdata };
239272 zone_options_t options = { 0 };
240273 no_file_test_t test = { 0 };
241274 int32_t code ;
@@ -245,7 +278,7 @@ void the_include_that_wasnt(void **state)
245278 options .origin .octets = origin ;
246279 options .origin .length = sizeof (origin );
247280 options .default_ttl = 3600 ;
248- options .default_class = ZONE_IN ;
281+ options .default_class = 1 ;
249282
250283 (void )state ;
251284
@@ -256,16 +289,139 @@ void the_include_that_wasnt(void **state)
256289 int length = snprintf (buffer , sizeof (buffer ), "$INCLUDE %s" , non_include );
257290 assert_true (length >= 0 && (size_t )length < SIZE_MAX - (ZONE_PADDING_SIZE + 1 ));
258291
259- char * include = malloc ((size_t )length + 1 + ZONE_PADDING_SIZE );
292+ char * include = malloc ((size_t )length + 1 );
260293 assert_non_null (include );
261294 (void )snprintf (include , (size_t )length + 1 , "$INCLUDE %s" , non_include );
262295
263- code = zone_parse_string (& parser , & options , & buffers , include , (size_t )length , & test );
296+ code = parse (& options , include , & test );
297+ free (include );
298+ free (non_include );
264299 assert_int_equal (code , ZONE_NOT_A_FILE );
265300 assert_true (test .log_count == 1 );
266301 assert_true (test .accept_count == 0 );
302+ }
303+
304+ static int32_t in_too_deep_accept (
305+ zone_parser_t * parser ,
306+ const zone_name_t * owner ,
307+ uint16_t type ,
308+ uint16_t class ,
309+ uint32_t ttl ,
310+ uint16_t rdlength ,
311+ const uint8_t * rdata ,
312+ void * user_data )
313+ {
314+ (void )parser ;
315+ (void )owner ;
316+ (void )type ;
317+ (void )class ;
318+ (void )ttl ;
319+ (void )rdlength ;
320+ (void )rdata ;
321+ (* (size_t * )user_data )++ ;
322+ return 0 ;
323+ }
324+
325+ static void in_too_deep_log (
326+ zone_parser_t * parser ,
327+ uint32_t priority ,
328+ const char * message ,
329+ void * user_data )
330+ {
331+ (void )parser ;
332+ (void )priority ;
333+
334+ if (strstr (message , "nested too deeply" ))
335+ * (size_t * )user_data |= 1u << 7 ;
336+ }
337+
338+ /*!cmocka */
339+ void in_too_deep (void * * state )
340+ {
341+ (void )state ;
342+
343+ int32_t code ;
344+ size_t records ;
345+ zone_options_t options = { 0 };
346+
347+ options .accept .callback = & in_too_deep_accept ;
348+ options .log .callback = & in_too_deep_log ;
349+ options .origin .octets = origin ;
350+ options .origin .length = sizeof (origin );
351+ options .default_ttl = 3600 ;
352+ options .default_class = 1 ;
353+ options .include_limit = 1 ;
354+
355+ #define INCLUDE "$INCLUDE %s\n"
356+
357+ char * deeper = generate_include ("foo. TXT \"bar\"" );
358+ assert_non_null (deeper );
359+ char buffer [16 ];
360+ int length = snprintf (buffer , sizeof (buffer ), INCLUDE , deeper );
361+ assert_true (length > 0 );
362+ char * inception = malloc ((size_t )length + 1 );
363+ assert_non_null (inception );
364+ (void )snprintf (inception , (size_t )length + 1 , INCLUDE , deeper );
365+ char * deep = generate_include (inception );
366+ assert_non_null (deep );
367+ free (inception );
368+ length = snprintf (buffer , sizeof (buffer ), INCLUDE , deep );
369+ assert_true (length > 0 );
370+ inception = malloc ((size_t )length + 1 );
371+ (void )snprintf (inception , (size_t )length + 1 , INCLUDE , deep );
372+
373+ #undef INCLUDE
374+
375+ records = 0 ;
376+ code = parse (& options , inception , & records );
377+ assert_int_equal (code , ZONE_SEMANTIC_ERROR );
378+ assert_int_equal (records , (1u << 7 ));
379+
380+ options .include_limit = 0 ;
381+ records = 0 ;
382+ code = parse (& options , inception , & records );
383+ assert_int_equal (code , ZONE_SUCCESS );
384+ assert_int_equal (records , 1u );
385+
386+ free (inception );
387+ free (deep );
388+ free (deeper );
389+ }
390+
391+ /*!cmocka */
392+ void been_there_done_that (void * * state )
393+ {
394+ (void )state ;
395+
396+ zone_options_t options = { 0 };
397+ options .accept .callback = & in_too_deep_accept ;
398+ options .log .callback = & in_too_deep_log ;
399+ options .origin .octets = origin ;
400+ options .origin .length = sizeof (origin );
401+ options .default_ttl = 3600 ;
402+ options .default_class = 1 ;
403+ options .include_limit = 1 ;
404+
405+ int32_t code ;
406+ size_t count = 0 ;
407+
408+ char * path = generate_include (" " );
409+ assert_non_null (path );
410+ FILE * handle = fopen (path , "wb" );
411+ assert_non_null (handle );
412+ char dummy [16 ];
413+ int length = snprintf (dummy , sizeof (dummy ), "$INCLUDE \"%s\"\n" , path );
414+ assert_true (length > 0 && length < INT_MAX - ZONE_PADDING_SIZE );
415+ char * include = malloc ((size_t )length + 1 + ZONE_PADDING_SIZE );
416+ assert_non_null (include );
417+ (void )snprintf (include , (size_t )length + 1 , "$INCLUDE \"%s\"\n" , path );
418+ int result = fputs (include , handle );
419+ assert_true (result >= 0 );
420+ (void )fclose (handle );
421+ free (path );
422+ code = parse (& options , include , & count );
267423 free (include );
268- free ( non_include );
424+ assert_int_equal ( code , ZONE_SEMANTIC_ERROR );
269425}
270426
271427//
0 commit comments