lib/classifier: Fix use of uninitialized memory.
authorJarno Rajahalme <jrajahalme@nicira.com>
Fri, 13 Jun 2014 21:52:59 +0000 (14:52 -0700)
committerJarno Rajahalme <jrajahalme@nicira.com>
Fri, 13 Jun 2014 21:55:19 +0000 (14:55 -0700)
When reaching the end of a prefix trie, we checked one bit off the end
to the intended data.  However, since the trie node in that case has
NULLs for both edge links, this did not result in incorrect
functionality.

Found via check-valgrind.

Reported-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/classifier.c

index 140d9e3..d8aa88e 100644 (file)
@@ -173,6 +173,7 @@ static unsigned int trie_lookup(const struct cls_trie *, const struct flow *,
                                 unsigned int *checkbits);
 static unsigned int trie_lookup_value(const struct trie_node *,
                                       const ovs_be32 value[],
+                                      unsigned int value_bits,
                                       unsigned int *checkbits);
 static void trie_destroy(struct trie_node *);
 static void trie_insert(struct cls_trie *, const struct cls_rule *, int mlen);
@@ -1825,7 +1826,7 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
 
         mask = MINIFLOW_GET_BE32(&subtable->mask.masks, tp_src);
         value = ((OVS_FORCE ovs_be32 *)flow)[TP_PORTS_OFS32] & mask;
-        trie_lookup_value(subtable->ports_trie, &value, &mbits);
+        trie_lookup_value(subtable->ports_trie, &value, 32, &mbits);
 
         ((OVS_FORCE ovs_be32 *)&wc->masks)[TP_PORTS_OFS32] |=
             mask & htonl(~0 << (32 - mbits));
@@ -2132,7 +2133,7 @@ trie_next_node(const struct trie_node *node, const ovs_be32 value[],
  */
 static unsigned int
 trie_lookup_value(const struct trie_node *node, const ovs_be32 value[],
-                  unsigned int *checkbits)
+                  unsigned int n_bits, unsigned int *checkbits)
 {
     unsigned int ofs = 0, match_len = 0;
     const struct trie_node *prev = NULL;
@@ -2151,8 +2152,13 @@ trie_lookup_value(const struct trie_node *node, const ovs_be32 value[],
         if (node->n_rules > 0) {
             match_len = ofs;
         }
+        if (ofs >= n_bits) {
+            *checkbits = n_bits; /* Full prefix. */
+            return match_len;
+        }
     }
-    /* Dead end, exclude the other branch if it exists. */
+    /* node == NULL.  Full match so far, but we came to a dead end.
+     * need to exclude the other branch if it exists. */
     *checkbits = !prev || trie_is_leaf(prev) ? ofs : ofs + 1;
     return match_len;
 }
@@ -2169,7 +2175,7 @@ trie_lookup(const struct cls_trie *trie, const struct flow *flow,
     if (mf_are_prereqs_ok(mf, flow)) {
         return trie_lookup_value(trie->root,
                                  &((ovs_be32 *)flow)[mf->flow_be32ofs],
-                                 checkbits);
+                                 mf->n_bits, checkbits);
     }
     *checkbits = 0; /* Value not used in this case. */
     return UINT_MAX;