Dear List,
I have run CodeSonar on a project using lmdb. I have downloaded lmdb-0.9.70.tar.gz. These warnings are a “Copy-Paste” error and “Use of memory after free”. I would like to share the details to help find out whether these
are real or false positives.
The copy-paste warning is generated by code around lines 8870f in mdb.c. In the first block, csrc-> is used throughout, in the second block cdst-> is used, except in one line:
/* Update the parent separators.
|
*/
|
if (csrc->mc_ki[csrc->mc_top] == 0) {
|
if (csrc->mc_ki[csrc->mc_top-1] !=
0) { |
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
|
} else {
|
srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0);
|
key.mv_size = NODEKSZ(srcnode);
|
key.mv_data = NODEKEY(srcnode);
|
}
|
DPRINTF(("update separator for source page %"Yu" to [%s]",
|
csrc->mc_pg[csrc->mc_top]->mp_pgno, DKEY(&key)));
|
mdb_cursor_copy(csrc, &mn);
|
mn.mc_snum--;
|
mn.mc_top--;
|
/* We want mdb_rebalance to find mn when doing fixups */
|
WITH_CURSOR_TRACKING(mn,
|
rc = mdb_update_key(&mn, &key));
|
if (rc)
|
return rc;
|
}
|
if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
|
MDB_val nullkey;
|
indx_t ix = csrc->mc_ki[csrc->mc_top];
|
nullkey.mv_size = 0;
|
csrc->mc_ki[csrc->mc_top] = 0;
|
rc = mdb_update_key(csrc, &nullkey);
|
csrc->mc_ki[csrc->mc_top] = ix;
|
mdb_cassert(csrc, rc == MDB_SUCCESS);
|
} |
}
|
|
if (cdst->mc_ki[cdst->mc_top] == 0) {
|
if (cdst->mc_ki[cdst->mc_top-1] !=
0) { |
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { /*
|
||
key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size);
|
} else {
|
srcnode = NODEPTR(cdst->mc_pg[cdst->mc_top], 0);
|
key.mv_size = NODEKSZ(srcnode);
|
key.mv_data = NODEKEY(srcnode);
|
}
|
DPRINTF(("update separator for destination page %"Yu" to [%s]",
|
cdst->mc_pg[cdst->mc_top]->mp_pgno, DKEY(&key)));
|
mdb_cursor_copy(cdst, &mn);
|
mn.mc_snum--;
|
mn.mc_top--;
|
/* We want mdb_rebalance to find mn when doing fixups */
|
WITH_CURSOR_TRACKING(mn,
|
rc = mdb_update_key(&mn, &key));
|
if (rc)
|
return rc;
|
}
|
if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) {
|
MDB_val nullkey;
|
indx_t ix = cdst->mc_ki[cdst->mc_top];
|
nullkey.mv_size = 0;
|
cdst->mc_ki[cdst->mc_top] = 0;
|
rc = mdb_update_key(cdst, &nullkey);
|
cdst->mc_ki[cdst->mc_top] = ix;
|
mdb_cassert(cdst, rc == MDB_SUCCESS);
|
} |
}
The second error is triggered by the loop freeing loose pages at line 3451 in mdb.c: NEXT_LOOSE_PAGE(mp) would access memory that is freed before, if mp points to an overflow page with more than one page allocated. If
this is never the case, then maybe mdb_page_free() should be called on mp directly?
for (;
mp;
mp =
NEXT_LOOSE_PAGE(mp))
{
|
||||
mdb_midl_xappend(txn->mt_free_pgs,
mp->mp_pgno);
|
/*
must also
remove from
dirty list
*/
|
if
(txn->mt_flags
& MDB_TXN_WRITEMAP) {
|
for (x=1;
x<=dl[0].mid;
x++)
|
if (dl[x].mid
== mp->mp_pgno)
|
break;
|
mdb_tassert(txn,
x <=
dl[0].mid);
|
}
else {
|
x =
mdb_mid2l_search(dl,
mp->mp_pgno);
|
mdb_tassert(txn,
dl[x].mid
== mp->mp_pgno);
|
}
|
dl[x].mptr
= NULL;
|
mdb_dpage_free(env,
mp);
|
|
mdb_dpage_free(MDB_env
*env,
MDB_page *dp)
|
{
|
if (!IS_OVERFLOW(dp)
|| dp->mp_pages
== 1) {
|
mdb_page_free(env,
dp);
|
}
else {
|
/*
large pages
just get
freed directly
*/
|
VGMEMP_FREE(env,
dp);
|
free(dp);
|
}
|
}
I hope you can follow these descriptions, I can provide more detail if needed. I would like to get some help figuring out how to resolve these warnings.
Best regards,
Christian Wendt
Software developer
Ext: +45 7217 5943
______________________________________
SKOV A/S
Hedelund 4, Glyngoere, 7870 Roslev, Denmark
Tel.: +45 7217 5555 – Fax: +45 7217 5959