diff --git a/CHANGES b/CHANGES index 475207a99f..9ff294055c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.1-195 | 2012-12-03 14:50:33 -0800 + + * Catching out-of-memory in patricia tree code. (Bill Parker) + 2.1-194 | 2012-12-03 14:36:26 -0800 * Renaming ASCII writer filter option 'only_single_header_row' to diff --git a/VERSION b/VERSION index 57be098d90..5f2036da97 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-194 +2.1-195 diff --git a/src/patricia.c b/src/patricia.c index 1dbc795ab7..6998576fdb 100644 --- a/src/patricia.c +++ b/src/patricia.c @@ -2,7 +2,7 @@ * Dave Plonka * * This product includes software developed by the University of Michigan, - * Merit Network, Inc., and their contributors. + * Merit Network, Inc., and their contributors. * * This file had been called "radix.c" in the MRT sources. * @@ -12,28 +12,28 @@ */ /* From copyright.txt: - * + * * Copyright (c) 1997, 1998, 1999 - * - * + * + * * The Regents of the University of Michigan ("The Regents") and Merit Network, * Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the * following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other * materials provided with the distribution. - * 3. All advertising materials mentioning features or use of - * this software must display the following acknowledgement: + * 3. All advertising materials mentioning features or use of + * this software must display the following acknowledgement: * This product includes software developed by the University of Michigan, Merit - * Network, Inc., and their contributors. + * Network, Inc., and their contributors. * 4. Neither the name of the University, Merit Network, nor the - * names of their contributors may be used to endorse or - * promote products derived from this software without + * names of their contributors may be used to endorse or + * promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -44,7 +44,7 @@ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static char copyright[] = @@ -66,6 +66,9 @@ static char copyright[] = #define Delete free +// From Bro for reporting memory exhaustion. +extern void out_of_memory(const char* where); + /* { from prefix.c */ /* prefix_tochar @@ -80,7 +83,7 @@ prefix_tochar (prefix_t * prefix) return ((u_char *) & prefix->add.sin); } -int +int comp_with_mask (void *addr, void *dest, u_int mask) { @@ -95,15 +98,15 @@ comp_with_mask (void *addr, void *dest, u_int mask) } /* inet_pton substitute implementation - * Uses inet_addr to convert an IP address in dotted decimal notation into + * Uses inet_addr to convert an IP address in dotted decimal notation into * unsigned long and copies the result to dst. - * Only supports AF_INET. Follows standard error return conventions of + * Only supports AF_INET. Follows standard error return conventions of * inet_pton. */ int local_inet_pton (int af, const char *src, void *dst) { - u_long result; + u_long result; if (af == AF_INET) { result = inet_addr(src); @@ -166,7 +169,7 @@ my_inet_pton (int af, const char *src, void *dst) } } -/* +/* * convert prefix information to ascii string with length * thread safe and (almost) re-entrant implementation */ @@ -251,6 +254,9 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) default_bitlen = 128; if (prefix == NULL) { prefix = calloc(1, sizeof (prefix_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); + dynamic_allocated++; } memcpy (&prefix->add.sin6, dest, 16); @@ -260,12 +266,16 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) if (prefix == NULL) { #ifndef NT prefix = calloc(1, sizeof (prefix4_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); #else //for some reason, compiler is getting //prefix4_t size incorrect on NT - prefix = calloc(1, sizeof (prefix_t)); + prefix = calloc(1, sizeof (prefix_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); #endif /* NT */ - + dynamic_allocated++; } memcpy (&prefix->add.sin, dest, 4); @@ -368,7 +378,7 @@ Ref_Prefix (prefix_t * prefix) return (prefix); } -void +void Deref_Prefix (prefix_t * prefix) { if (prefix == NULL) @@ -396,6 +406,8 @@ patricia_tree_t * New_Patricia (int maxbits) { patricia_tree_t *patricia = calloc(1, sizeof *patricia); + if (patricia == NULL) + out_of_memory("patrica/new_patricia: unable to allocate memory"); patricia->maxbits = maxbits; patricia->head = NULL; @@ -503,10 +515,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: take right %s/%d\n", + fprintf (stderr, "patricia_search_exact: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_exact: take right at %d\n", + fprintf (stderr, "patricia_search_exact: take right at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; @@ -514,10 +526,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) else { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: take left %s/%d\n", + fprintf (stderr, "patricia_search_exact: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_exact: take left at %d\n", + fprintf (stderr, "patricia_search_exact: take left at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; @@ -529,7 +541,7 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", + fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_exact: stop at %d\n", node->bit); @@ -541,7 +553,7 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), bitlen)) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_exact: found %s/%d\n", + fprintf (stderr, "patricia_search_exact: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -575,7 +587,7 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (node->prefix) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: push %s/%d\n", + fprintf (stderr, "patricia_search_best: push %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ stack[cnt++] = node; @@ -584,10 +596,10 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_best: take right %s/%d\n", + fprintf (stderr, "patricia_search_best: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_best: take right at %d\n", + fprintf (stderr, "patricia_search_best: take right at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; @@ -595,10 +607,10 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv else { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_best: take left %s/%d\n", + fprintf (stderr, "patricia_search_best: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_best: take left at %d\n", + fprintf (stderr, "patricia_search_best: take left at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; @@ -615,7 +627,7 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (node == NULL) fprintf (stderr, "patricia_search_best: stop at null\n"); else if (node->prefix) - fprintf (stderr, "patricia_search_best: stop at %s/%d\n", + fprintf (stderr, "patricia_search_best: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_best: stop at %d\n", node->bit); @@ -627,14 +639,14 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv while (--cnt >= 0) { node = stack[cnt]; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: pop %s/%d\n", + fprintf (stderr, "patricia_search_best: pop %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - if (comp_with_mask (prefix_tochar (node->prefix), + if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), node->prefix->bitlen)) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: found %s/%d\n", + fprintf (stderr, "patricia_search_best: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -665,6 +677,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) if (patricia->head == NULL) { node = calloc(1, sizeof *node); + if (node == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + node->bit = prefix->bitlen; node->prefix = Ref_Prefix (prefix); node->parent = NULL; @@ -672,7 +687,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) node->data = NULL; patricia->head = node; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", + fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ patricia->num_active_node++; @@ -691,7 +706,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) break; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: take right %s/%d\n", + fprintf (stderr, "patricia_lookup: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take right at %d\n", node->bit); @@ -703,7 +718,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) break; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: take left %s/%d\n", + fprintf (stderr, "patricia_lookup: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take left at %d\n", node->bit); @@ -716,7 +731,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) assert (node->prefix); #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: stop at %s/%d\n", + fprintf (stderr, "patricia_lookup: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ @@ -751,7 +766,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) parent = node->parent; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: up to %s/%d\n", + fprintf (stderr, "patricia_lookup: up to %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: up to %d\n", node->bit); @@ -760,8 +775,8 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) if (differ_bit == bitlen && node->bit == bitlen) { if (node->prefix) { -#ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: found %s/%d\n", +#ifdef PATRICIA_DEBUG + fprintf (stderr, "patricia_lookup: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -776,6 +791,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } new_node = calloc(1, sizeof *new_node); + if (new_node == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + new_node->bit = prefix->bitlen; new_node->prefix = Ref_Prefix (prefix); new_node->parent = NULL; @@ -795,7 +813,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) node->l = new_node; } #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", + fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (new_node); @@ -822,12 +840,15 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } node->parent = new_node; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", + fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } else { glue = calloc(1, sizeof *glue); + if (glue == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + glue->bit = differ_bit; glue->prefix = NULL; glue->parent = node->parent; @@ -856,7 +877,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } node->parent = glue; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", + fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } @@ -874,13 +895,13 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) if (node->r && node->l) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", + fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - + /* this might be a placeholder node -- have to check and make sure * there is a prefix aossciated with it ! */ - if (node->prefix != NULL) + if (node->prefix != NULL) Deref_Prefix (node->prefix); node->prefix = NULL; /* Also I needed to clear data pointer -- masaki */ @@ -890,7 +911,7 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) if (node->r == NULL && node->l == NULL) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", + fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ parent = node->parent; @@ -937,7 +958,7 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) } #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", + fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ if (node->r) { @@ -996,7 +1017,7 @@ try_search_exact (patricia_tree_t *tree, char *string) printf ("try_search_exact: not found\n"); } else { - printf ("try_search_exact: %s/%d found\n", + printf ("try_search_exact: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); } Deref_Prefix (prefix); @@ -1023,7 +1044,7 @@ try_search_best (patricia_tree_t *tree, char *string) if ((node = patricia_search_best (tree, prefix)) == NULL) printf ("try_search_best: not found\n"); else - printf ("try_search_best: %s/%d found\n", + printf ("try_search_best: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); Deref_Prefix (prefix); return 0; // [RS] What is supposed to be returned here? diff --git a/src/util.cc b/src/util.cc index 80cd3a0685..c36ff6a31c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1416,7 +1416,7 @@ void safe_close(int fd) } } -void out_of_memory(const char* where) +extern "C" void out_of_memory(const char* where) { fprintf(stderr, "out of memory in %s.\n", where); diff --git a/src/util.h b/src/util.h index 71b9c494e8..7d65f42fa8 100644 --- a/src/util.h +++ b/src/util.h @@ -303,7 +303,7 @@ extern bool safe_write(int fd, const char* data, int len); // Wraps close(2) to emit error messages and abort on unrecoverable errors. extern void safe_close(int fd); -extern void out_of_memory(const char* where); +extern "C" void out_of_memory(const char* where); inline void* safe_realloc(void* ptr, size_t size) {