Saurabh Suman
Saurabh Suman

Reputation: 19

Address in pointer passed as argument changed in receiving function

I am traversing a HB tree. I am passing a pointer that contains root node address. In subsequent function call my argument (root) is modified.

Can someone help what could be a possible reason for this?

static inline hbt_node_t *
hbt_descendent (hbt_node_t *node, uintptr_t dir)
{
    hbt_node_t *desc;
    uintptr_t  value;

    switch (dir) {
    case HBT_MINUS:
        desc = (hbt_node_t *)(node->hbt_data[0] & ~HBT_SIGN_MASK);
        break;

    case HBT_PLUS:
        value = node->hbt_data[1];
        if (!BIT_ISSET(value, HBT_NEXT)) {
            desc = (hbt_node_t *)(value);
        } else {
            desc = NULL;
        }
        break;

    default:
        assert(FALSE);
        desc = NULL;
    }

    return (desc);
}

/*
 * hbt_find_leftmost
 *
 */
static inline hbt_node_t *
hbt_find_leftmost (hbt_node_t *node)
{
    hbt_node_t *next;

    while (TRUE) {
        next = hbt_descendent(node, HBT_MINUS);
        if (next == NULL) {
            break;
        }
        node = next;
    }

    return (node);
}

/*
 * hbt_iterate_next
 *
 * Find the successor of a given node. Node must be present in the tree.
 */
hbt_node_t *
hbt_iterate_next (hbt_node_t *root, hbt_node_t *current)
{
    hbt_node_t *node;
    boolean climb;

    if (current == NULL) {
        if (root == NULL) {
            return (NULL);
        }
        node = hbt_find_leftmost(root);
        if (node) {
            return (node);
        }
    }

    node = hbt_node_next(current, &climb);
    if (node && !climb) {
        node = hbt_find_leftmost(node);
    }

    return (node);
}

As per backtrace:

(gdb) bt
#0  hbt_descendent (node=0x5a5a5a58, dir=3) at ../../../../../../src/dsa/lib/hbtree/hbtree.c:59
#1  hbt_find_leftmost (node=0x5a5a5a58) at ../../../../../../src/dsa/lib/hbtree/hbtree.c:775
#2  hbt_iterate_next (root=0x3494224, current=0x0) at ../../../../../../src/dsa/lib/hbtree/hbtree.c:800
#3  0x00b43ca2 in vlan_config_delete_one (vconf=0x37b9738) at ../../../../../../src/junos/usr.sbin/l2cpd/stp/vlan_config.c:803
(gdb) f 3
#3  0x00b43ca2 in vlan_config_delete_one (vconf=0x37b9738) at ../../../../../../src/junos/usr.sbin/l2cpd/stp/vlan_config.c:803
803         hnode = hbt_iterate_next(vconf->vc_voipiflist, NULL);
(gdb) p vconf->vc_voipiflist
$8 = (hbt_node_t *) 0x3494224

This is how application is using this

 hnode = hbt_iterate_next(vconf->vc_voipiflist, NULL);

vc_voipiflist is of type hbt_node_t

Root = 0x3494224 , same root is passed to hbt_find_leftmost with argument as node = 0x5a5a5a58. This is corrupted causing SIGSEGV.

PS: This HB tree implementation is part of the library and has been there for years ~20 yrs. Don't think there is an issue with this code.

Upvotes: 0

Views: 45

Answers (0)

Related Questions