antirez/rax

Iteration fails with a zero-length key

unixwitch opened this issue · 2 comments

When the trie contains a single zero-length key, iteration will not return the correct data value.

Minimal test case:

% cat raxtest.c
#include        <stdio.h>
#include        <assert.h>
#include        "rax.h"

int 
main()
{
rax             *rt;
raxIterator      it;

        rt = raxNew();
        raxInsert(rt, "", 0, (void *)-1, NULL);
        assert(raxFind(rt, "", 0) == (void *)-1);

        raxStart(&it, rt);
        raxSeek(&it, "^", NULL, 0);

        assert(raxNext(&it));
        assert(it.key_len == 0);
        assert(it.data == (void *)-1);
        raxFree(rt);

        return 0;
}
% cc -Icontrib/rax raxtest.c contrib/rax/rax.c -o raxtest -lm
% ./raxtest                                                  
raxtest: raxtest.c:20: main: Assertion `it.data == (void *)-1' failed.
zsh: abort      ./raxtest

Changing the key length to 1 (so the key is { '\0' }) fixes the problem.

Tested with:

gcc version 6.3.0 20170516 (Debian 6.3.0-18)
clang version 4.0.0-svn297204-1~exp1 (branches/release_40)

The following patch fixes this for me (at least enough for my application's tests to pass):

--- contrib/rax/rax.c.old       2017-06-01 14:29:53.545927300 +0100
+++ contrib/rax/rax.c   2017-06-01 14:30:08.977442400 +0100
@@ -1179,6 +1179,7 @@
         return 0;
     } else if (it->flags & RAX_ITER_JUST_SEEKED) {
         it->flags &= ~RAX_ITER_JUST_SEEKED;
+        it->data = raxGetData(it->node);
         return 1;
     }

Hello, thank you. I fixed the bug with a different patch, since what is happening is actually not related to the empty string but is a general bug: raxSeek() when seeking with an exact match, will not populate the iterator .data field. Now should be ok, thanks.