[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#8819) LMDB seg fault with MDB_DUPSORT on -O3



Full_Name: Nic Watson
Version: LMDB v 0.9.21
OS: Ubuntu 17.04
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (108.56.136.246)


I'm getting a seg fault in using LMDB on a database opened with MDB_DUPSORT.

Here's a minimal set of operations that will cause the problem:

#include <stdio.h>
#include "lmdb.h"

#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))

void cause_crash()
{
    MDB_env *env;
    MDB_txn *txn;
    MDB_dbi dbi;
    int rc;
    int line_fail = 0;
    MDB_val key = {.mv_size = 1, .mv_data = "a"};
    MDB_val vals[] = {
        { .mv_size = 8, .mv_data = "\x00\x00\x00\x00\x00\x00\x00\x00" },
        { .mv_size = 1, .mv_data = "\x05" },
        { .mv_size = 1, .mv_data = "\t" },
        { .mv_size = 1, .mv_data = "\r" },
        { .mv_size = 1, .mv_data = "\x11" },
        { .mv_size = 1, .mv_data = "\x15" },
        { .mv_size = 1, .mv_data = "\x19" },
        { .mv_size = 1, .mv_data = "\x1d" },
        { .mv_size = 1, .mv_data = "!" },
        { .mv_size = 1, .mv_data = "%" },
        { .mv_size = 1, .mv_data = ")" },
        { .mv_size = 1, .mv_data = "-" },
        { .mv_size = 1, .mv_data = "1" },
        { .mv_size = 1, .mv_data = "5" },
    };

    rc = mdb_env_create(&env);
    if (rc) { line_fail = __LINE__; goto fail; }

    rc = mdb_env_set_maxdbs(env, 2);
    if (rc) { line_fail = __LINE__; goto fail; }

    rc = mdb_env_open(env, "foo.lmdb", 0, 0777);
    if (rc) { line_fail = __LINE__; goto fail; }

    rc = mdb_txn_begin(env, NULL, 0, &txn);
    if (rc) { line_fail = __LINE__; goto fail; }

    rc = mdb_dbi_open(txn, "another_db", MDB_CREATE | MDB_DUPSORT, &dbi);
    if (rc) { line_fail = __LINE__; goto fail; }

    rc = mdb_txn_commit(txn);
    if (rc) { line_fail = __LINE__; goto fail; }

    rc = mdb_txn_begin(env, NULL, 0, &txn);
    if (rc) { line_fail = __LINE__; goto fail; }

    for (int i = 0; i < ARRAY_SIZE(vals); i++) {
        rc = mdb_put(txn, dbi, &key, &vals[i], 0);
        if (rc) { line_fail = __LINE__; goto fail; }
    }

    rc = mdb_txn_commit(txn);
    if (rc) { line_fail = __LINE__; goto fail; }

    mdb_dbi_close(env, dbi);
    mdb_env_close(env);

    return;

fail:
    printf("Failed with error %d on line %d\n", rc, line_fail);
}

int main(int argc, char **argv)
{
    printf("Running %s\n", MDB_VERSION_STRING);
    cause_crash();
    printf("Didn't crash!\n");
    return 0;
}

Here's a simple sh make script:

LMDB_DIR=~/src/lmdb/libraries/liblmdb
gcc-6 -O3 -ggdb -std=c11 -Wall -I $LMDB_DIR  lmdb_crash2.c
$LMDB_DIR/{mdb.c,midl.c} -lpthread -o mdb_c_exe
mkdir -p foo.lmdb

Here's a basic stack trace:
Program received signal SIGSEGV, Segmentation fault.
0x000055555555ee7c in mdb_cursor_put (mc=mc@entry=0x7fffffffcfa0,
key=key@entry=0x7fffffffd380, data=data@entry=0x7fffffffd460,
flags=flags@entry=0)
    at /home/nic/src/lmdb/libraries/liblmdb/mdb.c:6792
6792                                                    mp->mp_ptrs[i] =
fp->mp_ptrs[i] + offset;
(gdb) bt
#0  0x000055555555ee7c in mdb_cursor_put (mc=mc@entry=0x7fffffffcfa0,
key=key@entry=0x7fffffffd380, data=data@entry=0x7fffffffd460,
flags=flags@entry=0)
    at /home/nic/src/lmdb/libraries/liblmdb/mdb.c:6792
#1  0x00005555555635d0 in mdb_cursor_put (flags=0, data=0x7fffffffd460,
key=0x7fffffffd380, mc=0x7fffffffcfa0) at
/home/nic/src/lmdb/libraries/liblmdb/mdb.c:8984
#2  mdb_put (txn=0x55555576e8d0,


It will *not* crash under debug.  In fact, -O3 -fvect-cost-model=cheap will
*not* crash.  This makes some sense since it is crashing on an SSE instruction.

I tried gcc versions (Ubuntu 7.2.0-8ubuntu3.2) and (Ubuntu 6.4.0-8ubuntu1) with
the same result.  I also tried with the mdb.master branch (0.9.70) with the same
result.

I'm not convinced this a fault in your code.  It may be a gcc bug.