[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
(ITS#7828) LMDB crash in mdb_cursor_put(MDB_CURRENT)
Full_Name: Dmitri Shubin
Version: LMDB 0.9.11 (2727e97)
OS: Linux (CentOS 6)
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (80.239.140.98)
Hi!
I got a crash inside LMDB in mdb_cursor_put() functions when I trying to modify
the record under cursor.
Simple test:
$ cat test-mdb_current.c
#include <stdio.h>
#include <stdlib.h>
#include "lmdb.h"
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
#define DBDIR "./testdb"
int main()
{
int rc;
MDB_env *env;
MDB_dbi dbi;
MDB_txn *txn;
MDB_val key, data;
MDB_cursor *cursor;
int key_v = 17;
char data_v[] = "0123456789";
E(system("rm -rf " DBDIR " && mkdir " DBDIR));
E(mdb_env_create(&env));
E(mdb_env_open(env, DBDIR, 0, 0664));
E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_dbi_open(txn, NULL, 0, &dbi));
/* put some data */
key.mv_data = &key_v;
key.mv_size = sizeof(key_v);
data.mv_data = data_v;
data.mv_size = sizeof(data_v);
E(mdb_put(txn, dbi, &key, &data, 0));
E(mdb_txn_commit(txn));
/* replace using cursor */
E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_cursor_open(txn, dbi, &cursor));
E(mdb_cursor_get(cursor, &key, &data, MDB_SET));
data.mv_data = data_v;
data.mv_size = sizeof(data_v) - 1;
E(mdb_cursor_put(cursor, &key, &data, MDB_CURRENT));
mdb_cursor_close(cursor);
E(mdb_txn_commit(txn));
mdb_dbi_close(env, dbi);
mdb_env_close(env);
return 0;
}
$ gcc -g test-mdb_current.c -llmdb -L. -Wl,-rpath,.
$ ./a.out
Segmentation fault (core dumped)
$ gdb a.out
...
Program terminated with signal 11, Segmentation fault.
#0 0x00007fefaba9895c in mdb_leaf_size (env=0xbd8010, key=0x0,
data=0x7fff59e6a830) at mdb.c:6430
6430 sz = LEAFSIZE(key, data);
(gdb) bt
#0 0x00007fefaba9895c in mdb_leaf_size (env=0xbd8010, key=0x0,
data=0x7fff59e6a830) at mdb.c:6430
#1 0x00007fefaba97c53 in mdb_cursor_put (mc=0xbda2f0, key=0x0,
data=0x7fff59e6a830, flags=64) at mdb.c:6178
#2 0x0000000000400ee0 in main () at test-mdb_current.c:51
(gdb) l
6425 static size_t
6426 mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data)
6427 {
6428 size_t sz;
6429
6430 sz = LEAFSIZE(key, data);
6431 if (sz > env->me_nodemax) {
6432 /* put on overflow page */
6433 sz -= data->mv_size - sizeof(pgno_t);
6434 }
(gdb) p key
$1 = (MDB_val *) 0x0
If I remove MDB_CURRENT flag from mdb_cursor_put() call it works fine.
Thanks!