@ -26,6 +26,8 @@
# include <stddef.h>
# include <stdio.h>
# include "ares.h"
# include "ares__buf.h"
# include "ares_mem.h"
int LLVMFuzzerTestOneInput ( const unsigned char * data , unsigned long size ) ;
@ -127,6 +129,11 @@ int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size)
int LLVMFuzzerTestOneInput ( const unsigned char * data , unsigned long size )
{
ares_dns_record_t * dnsrec = NULL ;
char * printdata = NULL ;
ares__buf_t * printmsg = NULL ;
size_t i ;
unsigned char * datadup = NULL ;
size_t datadup_len = 0 ;
/* There is never a reason to have a size > 65535, it is immediately
* rejected by the parser */
@ -134,11 +141,155 @@ int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size)
return - 1 ;
}
ares_dns_parse ( data , size , 0 , & dnsrec ) ;
if ( dnsrec ) {
ares_dns_record_destroy ( dnsrec ) ;
if ( ares_dns_parse ( data , size , 0 , & dnsrec ) ! = ARES_SUCCESS ) {
goto done ;
}
/* Lets test the message fetchers */
printmsg = ares__buf_create ( ) ;
if ( printmsg = = NULL ) {
goto done ;
}
ares__buf_append_str ( printmsg , " ;; ->>HEADER<<- opcode: " ) ;
ares__buf_append_str ( printmsg , ares_dns_opcode_tostr ( ares_dns_record_get_opcode ( dnsrec ) ) ) ;
ares__buf_append_str ( printmsg , " , status: " ) ;
ares__buf_append_str ( printmsg , ares_dns_rcode_tostr ( ares_dns_record_get_rcode ( dnsrec ) ) ) ;
ares__buf_append_str ( printmsg , " , id: " ) ;
ares__buf_append_num_dec ( printmsg , ( size_t ) ares_dns_record_get_id ( dnsrec ) , 0 ) ;
ares__buf_append_str ( printmsg , " \n ;; flags: " ) ;
ares__buf_append_num_hex ( printmsg , ( size_t ) ares_dns_record_get_flags ( dnsrec ) , 0 ) ;
ares__buf_append_str ( printmsg , " ; QUERY: " ) ;
ares__buf_append_num_dec ( printmsg , ares_dns_record_query_cnt ( dnsrec ) , 0 ) ;
ares__buf_append_str ( printmsg , " , ANSWER: " ) ;
ares__buf_append_num_dec ( printmsg , ares_dns_record_rr_cnt ( dnsrec , ARES_SECTION_ANSWER ) , 0 ) ;
ares__buf_append_str ( printmsg , " , AUTHORITY: " ) ;
ares__buf_append_num_dec ( printmsg , ares_dns_record_rr_cnt ( dnsrec , ARES_SECTION_AUTHORITY ) , 0 ) ;
ares__buf_append_str ( printmsg , " , ADDITIONAL: " ) ;
ares__buf_append_num_dec ( printmsg , ares_dns_record_rr_cnt ( dnsrec , ARES_SECTION_ADDITIONAL ) , 0 ) ;
ares__buf_append_str ( printmsg , " \n \n " ) ;
ares__buf_append_str ( printmsg , " ;; QUESTION SECTION: \n " ) ;
for ( i = 0 ; i < ares_dns_record_query_cnt ( dnsrec ) ; i + + ) {
const char * name ;
ares_dns_rec_type_t qtype ;
ares_dns_class_t qclass ;
if ( ares_dns_record_query_get ( dnsrec , i , & name , & qtype , & qclass ) ! = ARES_SUCCESS ) {
goto done ;
}
ares__buf_append_str ( printmsg , " ; " ) ;
ares__buf_append_str ( printmsg , name ) ;
ares__buf_append_str ( printmsg , " . \t \t \t " ) ;
ares__buf_append_str ( printmsg , ares_dns_class_tostr ( qclass ) ) ;
ares__buf_append_str ( printmsg , " \t " ) ;
ares__buf_append_str ( printmsg , ares_dns_rec_type_tostr ( qtype ) ) ;
ares__buf_append_str ( printmsg , " \n " ) ;
}
ares__buf_append_str ( printmsg , " \n " ) ;
for ( i = ARES_SECTION_ANSWER ; i < ARES_SECTION_ADDITIONAL + 1 ; i + + ) {
size_t j ;
ares__buf_append_str ( printmsg , " ;; " ) ;
ares__buf_append_str ( printmsg , ares_dns_section_tostr ( ( ares_dns_section_t ) i ) ) ;
ares__buf_append_str ( printmsg , " SECTION: \n " ) ;
for ( j = 0 ; j < ares_dns_record_rr_cnt ( dnsrec , ( ares_dns_section_t ) i ) ; j + + ) {
size_t keys_cnt = 0 ;
const ares_dns_rr_key_t * keys = NULL ;
ares_dns_rr_t * rr = NULL ;
size_t k ;
rr = ares_dns_record_rr_get ( dnsrec , ( ares_dns_section_t ) i , j ) ;
ares__buf_append_str ( printmsg , ares_dns_rr_get_name ( rr ) ) ;
ares__buf_append_str ( printmsg , " . \t \t \t " ) ;
ares__buf_append_str ( printmsg , ares_dns_class_tostr ( ares_dns_rr_get_class ( rr ) ) ) ;
ares__buf_append_str ( printmsg , " \t " ) ;
ares__buf_append_str ( printmsg , ares_dns_rec_type_tostr ( ares_dns_rr_get_type ( rr ) ) ) ;
ares__buf_append_str ( printmsg , " \t " ) ;
ares__buf_append_num_dec ( printmsg , ares_dns_rr_get_ttl ( rr ) , 0 ) ;
ares__buf_append_str ( printmsg , " \t " ) ;
keys = ares_dns_rr_get_keys ( ares_dns_rr_get_type ( rr ) , & keys_cnt ) ;
for ( k = 0 ; k < keys_cnt ; k + + ) {
char buf [ 256 ] = " " ;
ares__buf_append_str ( printmsg , ares_dns_rr_key_tostr ( keys [ k ] ) ) ;
ares__buf_append_str ( printmsg , " = " ) ;
switch ( ares_dns_rr_key_datatype ( keys [ k ] ) ) {
case ARES_DATATYPE_INADDR :
ares_inet_ntop ( AF_INET , ares_dns_rr_get_addr ( rr , keys [ k ] ) , buf , sizeof ( buf ) ) ;
ares__buf_append_str ( printmsg , buf ) ;
break ;
case ARES_DATATYPE_INADDR6 :
ares_inet_ntop ( AF_INET6 , ares_dns_rr_get_addr6 ( rr , keys [ k ] ) , buf , sizeof ( buf ) ) ;
ares__buf_append_str ( printmsg , buf ) ;
break ;
case ARES_DATATYPE_U8 :
ares__buf_append_num_dec ( printmsg , ares_dns_rr_get_u8 ( rr , keys [ k ] ) , 0 ) ;
break ;
case ARES_DATATYPE_U16 :
ares__buf_append_num_dec ( printmsg , ares_dns_rr_get_u16 ( rr , keys [ k ] ) , 0 ) ;
break ;
case ARES_DATATYPE_U32 :
ares__buf_append_num_dec ( printmsg , ares_dns_rr_get_u32 ( rr , keys [ k ] ) , 0 ) ;
break ;
case ARES_DATATYPE_NAME :
case ARES_DATATYPE_STR :
ares__buf_append_byte ( printmsg , ' " ' ) ;
ares__buf_append_str ( printmsg , ares_dns_rr_get_str ( rr , keys [ k ] ) ) ;
ares__buf_append_byte ( printmsg , ' " ' ) ;
break ;
case ARES_DATATYPE_BIN :
/* TODO */
break ;
case ARES_DATATYPE_BINP :
{
size_t templen ;
ares__buf_append_byte ( printmsg , ' " ' ) ;
ares__buf_append_str ( printmsg , ( const char * ) ares_dns_rr_get_bin ( rr , keys [ k ] , & templen ) ) ;
ares__buf_append_byte ( printmsg , ' " ' ) ;
}
break ;
case ARES_DATATYPE_ABINP :
{
size_t a ;
for ( a = 0 ; a < ares_dns_rr_get_abin_cnt ( rr , keys [ k ] ) ; a + + ) {
size_t templen ;
if ( a ! = 0 ) {
ares__buf_append_byte ( printmsg , ' ' ) ;
}
ares__buf_append_byte ( printmsg , ' " ' ) ;
ares__buf_append_str ( printmsg , ( const char * ) ares_dns_rr_get_abin ( rr , keys [ k ] , a , & templen ) ) ;
ares__buf_append_byte ( printmsg , ' " ' ) ;
}
}
break ;
case ARES_DATATYPE_OPT :
/* TODO */
break ;
}
ares__buf_append_str ( printmsg , " " ) ;
}
ares__buf_append_str ( printmsg , " \n " ) ;
}
}
ares__buf_append_str ( printmsg , " ;; SIZE: " ) ;
ares__buf_append_num_dec ( printmsg , size , 0 ) ;
ares__buf_append_str ( printmsg , " \n \n " ) ;
printdata = ares__buf_finish_str ( printmsg , NULL ) ;
printmsg = NULL ;
/* Write it back out as a dns message to test writer */
if ( ares_dns_write ( dnsrec , & datadup , & datadup_len ) ! = ARES_SUCCESS ) {
goto done ;
}
done :
ares_dns_record_destroy ( dnsrec ) ;
ares__buf_destroy ( printmsg ) ;
ares_free ( printdata ) ;
return 0 ;
}