]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: ebtree: ebmb_insert() must not call cmp_bits on full-length matches
authorWilly Tarreau <w@1wt.eu>
Sat, 9 Jun 2012 13:43:36 +0000 (15:43 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 9 Jun 2012 16:48:22 +0000 (18:48 +0200)
Otherwise we end up comparing the byte past the end, resulting
in duplicate values still being inserted into the tree even if
undesired.

This generally has low impact, though it can sometimes cause one new entry
to be added next to an existing one for stick tables, preventing the results
from being merged.

(cherry picked from commit 12e54ac493a91bb02064568f410592c2700d3933)

ebtree/ebimtree.h
ebtree/ebmbtree.h

index b40e490b4ea453cf5fee7578416a7627d943c316..1fe9fa0acba5caa80f240210f6344cf5dc8eb7ad 100644 (file)
@@ -198,7 +198,14 @@ __ebim_insert(struct eb_root *root, struct ebpt_node *new, unsigned int len)
                         * The last two cases can easily be partially merged.
                         */
                        bit = equal_bits(new->key, old->key, bit, len);
-                       diff = cmp_bits(new->key, old->key, bit);
+
+                       /* Note: we can compare more bits than the current node's because as
+                        * long as they are identical, we know we descend along the correct
+                        * side. However we don't want to start to compare past the end.
+                        */
+                       diff = 0;
+                       if (((unsigned)bit >> 3) < len)
+                               diff = cmp_bits(new->key, old->key, bit);
 
                        if (diff < 0) {
                                new->node.leaf_p = new_left;
@@ -263,7 +270,14 @@ __ebim_insert(struct eb_root *root, struct ebpt_node *new, unsigned int len)
 
                        new->node.node_p = old->node.node_p;
 
-                       diff = cmp_bits(new->key, old->key, bit);
+                       /* Note: we can compare more bits than the current node's because as
+                        * long as they are identical, we know we descend along the correct
+                        * side. However we don't want to start to compare past the end.
+                        */
+                       diff = 0;
+                       if (((unsigned)bit >> 3) < len)
+                               diff = cmp_bits(new->key, old->key, bit);
+
                        if (diff < 0) {
                                new->node.leaf_p = new_left;
                                old->node.node_p = new_rght;
index 121c59fa12ed1e61bd83f5f482dc9d572e7d1c7b..fa25ac58aa2bb7673e4e54b220c252d06f7207c0 100644 (file)
@@ -306,12 +306,16 @@ __ebmb_insert(struct eb_root *root, struct ebmb_node *new, unsigned int len)
        new_rght = eb_dotag(&new->node.branches, EB_RGHT);
        new_leaf = eb_dotag(&new->node.branches, EB_LEAF);
 
-       /* Note: we can compare more bits than
-        * the current node's because as long as they are identical, we
-        * know we descend along the correct side.
-        */
        new->node.bit = bit;
-       diff = cmp_bits(new->key, old->key, bit);
+
+       /* Note: we can compare more bits than the current node's because as
+        * long as they are identical, we know we descend along the correct
+        * side. However we don't want to start to compare past the end.
+        */
+       diff = 0;
+       if (((unsigned)bit >> 3) < len)
+               diff = cmp_bits(new->key, old->key, bit);
+
        if (diff == 0) {
                new->node.bit = -1; /* mark as new dup tree, just in case */