NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/47144: rbtree itteration is broken



>Number:         47144
>Category:       lib
>Synopsis:       rbtree itteration is broken
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 30 21:50:00 +0000 2012
>Originator:     Jeremy Huddleston Sequoia
>Release:        6.0
>Organization:
Apple Inc
>Environment:
NetBSD netbsd6.apple.com 6.0_RC2 NetBSD 6.0_RC2 (GENERIC) amd64

>Description:
rbtree itteration is broken

rb_tree_iterate(&rbt, NULL, RB_DIR_RIGHT); returns the last node in the tree.  
It should return the first.

rb_tree_iterate(&rbt, NULL, RB_DIR_LEFT); returns the first node in the tree.  
It should return the last.


>How-To-Repeat:
#include <sys/rbtree.h>
#include <sys/types.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    struct rb_node      rbnode;
    char                *value;
} rbtest_node_t;

static int
_rbtest_compare_nodes(__unused void *context, const void *_node1, const void 
*_node2) {
    rbtest_node_t *node1 = (rbtest_node_t *) _node1;
    rbtest_node_t *node2 = (rbtest_node_t *) _node2;

    return strcmp(node1->value, node2->value);
}

static int
_rbtest_compare_key(__unused void *context, const void *_node, const void 
*value)
{
    rbtest_node_t *node = (rbtest_node_t *) _node;

    return strcmp(node->value, value);
}

static const rb_tree_ops_t ops = {
    .rbto_compare_nodes = _rbtest_compare_nodes,
    .rbto_compare_key = _rbtest_compare_key,
    .rbto_node_offset = offsetof(rbtest_node_t, rbnode),
    .rbto_context = NULL
};

/* Generate a pseudorandom string */
static void
_rbtest_random_string(char *str, size_t len) {
    size_t i;

    for (i=0; i < len - 2; i++) {
        str[i] = 'a' + random() % 26;
    }
    str[len - 1] = '\0';
}

static void
_rbtest_insert_random_string_node(rb_tree_t *rbt) {
    rbtest_node_t *node;

    node = calloc(1, sizeof(*node));

    node->value = malloc(32 * sizeof(char));
    _rbtest_random_string(node->value, 32);

    printf("Inserting %s\n", node->value);
    rb_tree_insert_node(rbt, node);
}

int main() {
    rb_tree_t rbt;
    rbtest_node_t *it;
    size_t i;

    rb_tree_init(&rbt, &ops);

    srandom(0);

    for (i=0; i < 100; i++) {
        _rbtest_insert_random_string_node(&rbt);
    }

    it = rb_tree_iterate(&rbt, NULL, RB_DIR_RIGHT);
    while (it != NULL) {
        printf("%s\n", it->value);
        it = rb_tree_iterate(&rbt, it, RB_DIR_RIGHT);
    }

    return 0;
}

>Fix:
I have not tested if the RBSMALL path is also affected by this issue.




Home | Main Index | Thread Index | Old Index