From: TCY16 Date: Fri, 22 Apr 2022 11:08:09 +0000 (+0200) Subject: change the ends_option_list growing logic to be in line with rr_list X-Git-Tag: 1.8.2-rc.1~3^2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5faa6bd5957e5e3a3de1446ea3f61d2467af50a8;p=thirdparty%2Fldns.git change the ends_option_list growing logic to be in line with rr_list --- diff --git a/edns.c b/edns.c index 5b11f562..10f39d99 100644 --- a/edns.c +++ b/edns.c @@ -12,8 +12,10 @@ #include +#define LDNS_OPTIONLIST_INIT 8 + /* - * Access functions + * Access functions * functions to get and set type checking */ @@ -173,6 +175,7 @@ ldns_edns_option_list_new() } option_list->_option_count = 0; + option_list->_option_capacity = 0; option_list->_options_size = 0; option_list->_options = NULL; return option_list; @@ -297,34 +300,58 @@ bool ldns_edns_option_list_push(ldns_edns_option_list *option_list, ldns_edns_option *option) { + size_t cap; + size_t option_count; + assert(option_list != NULL); - if (option != NULL) { + if (option == NULL) { + return false; + } + + cap = option_list->_option_capacity; + option_count = ldns_edns_option_list_get_count(option_list); + + /* verify we need to grow the array to fit the new option */ + if (option_count+1 > cap) { + ldns_edns_option **new_list; + + /* initialize the capacity if needed, otherwise grow by doubling */ + if (cap == 0) { + cap = LDNS_OPTIONLIST_INIT; /* initial list size */ + } else { + cap *= 2; + } + + new_list = LDNS_XREALLOC(option_list->_options, + ldns_edns_option *, cap); - /* grow the array */ - option_list->_options = LDNS_XREALLOC(option_list->_options, - ldns_edns_option *, option_list->_option_count + 1); - if (!option_list) { + if (!new_list) { return false; } - ldns_edns_option_list_set_option(option_list, option, - option_list->_option_count); - option_list->_option_count += 1; - return true; + option_list->_options = new_list; + option_list->_option_capacity = cap; } - return false; + + /* add the new option */ + ldns_edns_option_list_set_option(option_list, option, + option_list->_option_count); + option_list->_option_count += 1; + + return true; } ldns_edns_option * ldns_edns_option_list_pop(ldns_edns_option_list *option_list) { - ldns_edns_option ** new_list; ldns_edns_option* pop; size_t count; + size_t cap; assert(option_list != NULL); + cap = option_list->_option_capacity; count = ldns_edns_option_list_get_count(option_list); if (count == 0){ @@ -334,12 +361,20 @@ ldns_edns_option_list_pop(ldns_edns_option_list *option_list) pop = ldns_edns_option_list_get_option(option_list, count-1); /* shrink the array */ - new_list = LDNS_XREALLOC(option_list->_options, ldns_edns_option *, count -1); - if (new_list){ - option_list->_options = new_list; + if (cap > LDNS_OPTIONLIST_INIT && count-1 <= cap/2) { + ldns_edns_option **new_list; + + cap /= 2; + + new_list = LDNS_XREALLOC(option_list->_options, + ldns_edns_option *, cap); + if (new_list) { + option_list->_options = new_list; + } + /* if the realloc fails, the capacity for the list remains unchanged */ } - /* shrink the total EDNS size if the popped EDNS option exists */ + /* shrink the total EDNS size of the options if the popped EDNS option exists */ if (pop != NULL) { option_list->_options_size -= (ldns_edns_get_size(pop) + 4); } diff --git a/ldns/edns.h b/ldns/edns.h index b121581c..553b3447 100644 --- a/ldns/edns.h +++ b/ldns/edns.h @@ -108,6 +108,7 @@ typedef struct ldns_struct_edns_option ldns_edns_option; struct ldns_struct_edns_option_list { size_t _option_count; /* the number of EDNS options in the list */ + size_t _option_capacity; /* the amount of options that fit into the list */ size_t _options_size; /* the total size of the options serialized */ ldns_edns_option **_options; };