[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: (ITS#9037) observing crash in mdb_cursor_put()
--_000_MN2PR06MB55017A7261FA27380778753BAFEA0MN2PR06MB5501namp_
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<repost since the previous message came as 64 encoded, apologies>
Hello Howard,
we are not able to reproduce the issue consistently so test code is not ava=
ilable at this time, and I do believe this issue will be present in the lat=
est code as well since Myk also reported the same.. Attaching analysis fro=
m our side, hope it helps.
The call stack what we have seen is,
#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18, key=3D0xffe52e74, dat=
a=3D0xffe52e6c, flags=3D0) at mdb.c:6688
#1 0x0011c8ec in mdb_put (txn=3D0xdc13f008, dbi=3D2, key=3D0xffe52e74, =
data=3D0xffe52e6c, flags=3D0) at mdb.c:8771
#2 0x00b792b8 in LMDB::LMDBContext::createSession (this=3D0x80ca418, si=
d=3D0x8297be4 "sidebf3708f0fd9fcb8e062529da47adf51402dfc4600000000+") at lm=
dbint.cc:460
#3 0x08053564 in updateLMDB (request=3D..., forward=3D@0xffe5315f) at s=
essionserver.cc:1075
#4 processRequestWithoutResponse (request=3D..., forward=3D@0xffe5315f)=
at sessionserver.cc:1160
#5 0x08056a80 in processRequest (this=3D0x80b2ac0, fd=3D33) at sessions=
erver.cc:1189
#6 readFromSock (this=3D0x80b2ac0, fd=3D33) at sessionserver.cc:1342
#7 SockHandler::ioReady (this=3D0x80b2ac0, fd=3D33) at sessionserver.cc=
:1455
#8 0x00ba2592 in runCoreDispatcher (default_t=3D<value optimized out>, =
flags=3D-1) at fds.cc:889
#9 0x00ba2ff7 in DSEvntFds::runDispatcher () at fds.cc:945
#10 0x080559c6 in main () at sessionserver.cc:1739
Here it is helpful to examine frames #0 and #1 in detail in relation to the=
relevant source code /libraries/liblmdb/mdb.c.
Frame #1
#1 0x0011c8ec in mdb_put (txn=3D0xdc13f008, dbi=3D2, key=3D0xffe52e74, dat=
a=3D0xffe52e6c, flags=3D0) at mdb.c:8771
mc =3D {mc_next =3D 0x0, mc_backup =3D 0x0, mc_xcursor =3D 0x0, mc_=
txn =3D 0xdc13f008, mc_dbi =3D 2, mc_db =3D 0xdc13f088, mc_dbx =3D 0xe12150=
38, mc_dbflag =3D 0xdc1cf09a "\033", '\032' <repeats 51 times>, mc_snum =3D=
0, mc_top =3D 0, mc_flags =3D 0, mc_pg =3D {0x0, 0x80b2ac0, 0xffe52d68, 0x=
28afce, 0xdc13f008, 0x80ce9b0, 0xffe52dc8, 0x4c5ff4, 0x2b, 0x80b2ac0, 0xffe=
52d98, 0x49209a, 0x2b, 0x4c5ff4, 0x2121cb, 0x21576c, 0x8297d34, 0x3497af, 0=
x21576c, 0x21316a, 0x8297d34, 0x80ac7b0, 0x1e, 0x46eed6, 0x2b, 0x0, 0x80ce9=
b0, 0x4c5ff4, 0x80ac7b0, 0x8297d34, 0xffe52df8, 0x46fb96}, mc_ki =3D {0, 20=
89, 51120, 2058, 30, 0, 16796, 17, 11760, 65509, 3, 0, 32040, 2089, 30, 0, =
0, 0, 0, 0, 3, 0, 24564, 76, 51120, 2058, 10944, 2059, 11800, 65509, 64758,=
70}} <--------
mx =3D {mx_cursor =3D {mc_next =3D 0x38, mc_backup =3D 0x3, mc_xcur=
sor =3D 0x0, mc_txn =3D 0x0, mc_dbi =3D 0, mc_db =3D 0x28, mc_dbx =3D 0x0, =
mc_dbflag =3D 0x0, mc_snum =3D 3, mc_top =3D 0, mc_flags =3D 17, mc_pg =3D =
{0x3a93d8, 0x10, 0x0, 0x18, 0x3a93a0, 0x0, 0x3a93d0, 0x289abe, 0x3a93a0, 0x=
ffe52d3f, 0xffe52c68, 0x28afce, 0xffe52dbc, 0xffe52db4, 0x3, 0x4c5ff4, 0x11=
, 0x36c99b, 0x6e, 0x77, 0x7c, 0x5b, 0x38, 0x289abe, 0x0, 0x0, 0x0, 0x28, 0x=
0, 0x0, 0x3, 0x10}, mc_ki =3D {37848, 58, 51611, 54, 110, 0, 119, 0, 124, 0=
, 91, 0, 58, 0, 39614, 40, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 2, 0, 18, 0, 136=
, 0}}, mx_db =3D {md_pad =3D 3838936, md_flags =3D 51611, md_depth =3D 54, =
md_branch_pages =3D 110, md_leaf_pages =3D 119, md_overflow_pages =3D 124, =
md_entries =3D 91, md_root =3D 56}, mx_dbx =3D {md_name =3D {mv_size =3D 6,=
mv_data =3D 0x0}, md_cmp =3D 0, md_dcmp =3D 0, md_rel =3D 0x40, md_relctx =
=3D 0x0}, mx_dbflag =3D 0 '\000'}
rc =3D 0
And source code for mdb_put() is from mdb.c
int
mdb_put(MDB_txn *txn, MDB_dbi dbi,
MDB_val *key, MDB_val *data, unsigned int flags) {
MDB_cursor mc;
MDB_xcursor mx;
int rc;
if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
if (flags & ~(MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB=
_APPEND|MDB_APPENDDUP))
return EINVAL;
if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
return (txn->mt_flags & MDB_TXN_RDONLY) ? E=
ACCES : MDB_BAD_TXN;
mdb_cursor_init(&mc, txn, dbi, &mx); <-------- see source c=
ode below
mc.mc_next =3D txn->mt_cursors[dbi];
txn->mt_cursors[dbi] =3D &mc;
rc =3D mdb_cursor_put(&mc, key, data, flags); <-------- see=
Frame #0
txn->mt_cursors[dbi] =3D mc.mc_next;
return rc;
}
Source Code For mdb_cursor_init() From mdb.c
/** Initialize a cursor for a given transaction and database. */ static voi=
d mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *m=
x) {
mc->mc_next =3D NULL;
mc->mc_backup =3D NULL;
mc->mc_dbi =3D dbi;
mc->mc_txn =3D txn;
mc->mc_db =3D &txn->mt_dbs[dbi];
mc->mc_dbx =3D &txn->mt_dbxs[dbi];
mc->mc_dbflag =3D &txn->mt_dbflags[dbi];
mc->mc_snum =3D 0; <--------
mc->mc_top =3D 0; <--------
mc->mc_pg[0] =3D 0; <--------
mc->mc_ki[0] =3D 0;
mc->mc_flags =3D 0;
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
mdb_tassert(txn, mx !=3D NULL);
mc->mc_xcursor =3D mx;
mdb_xcursor_init0(mc);
} else {
mc->mc_xcursor =3D NULL;
}
if (*mc->mc_dbflag & DB_STALE) { <-------- false *mc->mc_db=
flag =3D 27, DB_STALE =3D 0x02 /**< Named-DB record is old=
er than txnID */
mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
}
}
>From this we know that when mdb_cursor_put() is called, the following value=
s remain assigned:
mc->mc_snum =3D 0; <--------
mc->mc_top =3D 0; <--------
mc->mc_pg[0] =3D 0; <--------
and its noted these two values still have their initial values at the time =
of the segmentation fault.
(gdb) fr 0
#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18, key=3D0xffe52e74, data=3D=
0xffe52e6c, flags=3D0) at mdb.c:6688
6688 in mdb.c
(gdb) p mc->mc_top
$1 =3D 0
(gdb) p mc->mc_pg[mc->mc_top]
$19 =3D (MDB_page *) 0x0
Let us consider how the path taken through mdb_cursor_put() could account f=
or these null variable values which result in a segmentation fault.
Frame #0
#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18, key=3D0xffe52e74, data=
=3D0xffe52e6c, flags=3D0) at mdb.c:6688 <-------- flags =3D 0
env =3D 0x80ce9b0
leaf =3D <value optimized out>
fp =3D <value optimized out>
mp =3D 0x38
sub_root =3D 0x0
fp_flags =3D <value optimized out>
xdata =3D {mv_size =3D 3838880, mv_data =3D 0xdc1cf09a}
rdata =3D 0xffe52e6c
dkey =3D {mv_size =3D 0, mv_data =3D 0x3a93cc}
olddata =3D {mv_size =3D 22, mv_data =3D 0x36c820}
dummy =3D {md_pad =3D 22, md_flags =3D 11128, md_depth =3D 65509, m=
d_branch_pages =3D 16, md_leaf_pages =3D 1507329, md_overflow_pages =3D 0, =
md_entries =3D 3838928, md_root =3D 3833844}
do_sub =3D 0
insert_key =3D -30798 <-------- #define MDB_NOTFOUND (-307=
98)
insert_data =3D -30798 <-------- #define MDB_NOTFOUND (-3079=
8)
mcount =3D 0
dcount =3D 0
nospill =3D 0 <--------
nsize =3D <value optimized out>
rc =3D 0
rc2 =3D <value optimized out>
nflags =3D 0 <--------
__func__ =3D "mdb_cursor_put"
We know that mc->mc_top and mc->mc_pg[0] were initialized to 0 in mdb_curso=
r_init(). As my annotations of the source code below suggest, careful analy=
sis reveals that the paths actually taken through mdb_cursor_put() do not m=
odify these assignments.
Excerpted Source Code For mdb_cursor_put() From mdb.c
int
mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
unsigned int flags)
{
MDB_env *env;
MDB_node *leaf =3D NULL;
MDB_page *fp, *mp, *sub_root =3D NULL;
uint16_t fp_flags;
MDB_val xdata, *rdata, dkey, o=
lddata;
MDB_db dummy;
int do_sub =3D 0, insert_key, insert_data;
unsigned int mcount =3D 0, dcount =3D 0, nospill;
size_t nsize;
int rc, rc2;
unsigned int nflags;
DKBUF;
if (mc =3D=3D NULL || key =3D=3D NULL)
return EINVAL;
env =3D mc->mc_txn->mt_env;
/* Check this first so counter will always be zero on any
* early failures.
*/
if (flags & MDB_MULTIPLE) {
dcount =3D data[1].mv_size;
data[1].mv_size =3D 0;
if (!F_ISSET(mc->mc_db->md_flags, MDB_DUPFI=
XED))
return MDB_INCOMPATIBLE;
}
nospill =3D flags & MDB_NOSPILL;
flags &=3D ~MDB_NOSPILL;
if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)=
)
return (mc->mc_txn->mt_flags & MDB_TXN_RDON=
LY) ? EACCES : MDB_BAD_TXN;
if (key->mv_size-1 >=3D ENV_MAXKEY(env))
return MDB_BAD_VALSIZE;
#if SIZE_MAX > MAXDATASIZE
if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? =
ENV_MAXKEY(env) : MAXDATASIZE))
return MDB_BAD_VALSIZE;
#else
if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > =
ENV_MAXKEY(env))
return MDB_BAD_VALSIZE;
#endif
DPRINTF(("=3D=3D> put db %d key [%s], size %"Z"u, data size=
%"Z"u",
DDBI(mc), DKEY(key), key ? key->mv_size : 0=
, data->mv_size));
dkey.mv_size =3D 0;
if (flags =3D=3D MDB_CURRENT) { <-------- false flags =3D 0
if (!(mc->mc_flags & C_INITIALIZED))
return EINVAL;
rc =3D MDB_SUCCESS;
} else if (mc->mc_db->md_root =3D=3D P_INVALID) { <--------=
false, mc->mc_db->md_root =3D 68
/* new database, cursor has nothing to poin=
t to */
mc->mc_snum =3D 0;
mc->mc_top =3D 0;
mc->mc_flags &=3D ~C_INITIALIZED;
rc =3D MDB_NO_ROOT;
} else { <-------- executed
int exact =3D 0;
MDB_val d2;
if (flags & MDB_APPEND) { <-------- false f=
lags =3D 0
MDB_val k2;
rc =3D mdb_cursor_last(mc, =
&k2, &d2);
if (rc =3D=3D 0) {
rc =3D mc->=
mc_dbx->md_cmp(key, &k2);
if (rc > 0)=
{
=
rc =3D MDB_NOTFOUND;
=
mc->mc_ki[mc->mc_top]++;
} else {
=
/* new key is <=3D last key */
=
rc =3D MDB_KEYEXIST;
}
}
} else {<-------- executed
rc =3D mdb_cursor_set(mc, k=
ey, &d2, MDB_SET, &exact); <-------- returns -30798 which is MDB_NOTFOUND
}<-------- executed
if ((flags & MDB_NOOVERWRITE) && rc =3D=3D =
0) { <-------- false flags =3D 0
DPRINTF(("duplicate key [%s=
]", DKEY(key)));
*data =3D d2;
return MDB_KEYEXIST;
}
if (rc && rc !=3D MDB_NOTFOUND) <-------- f=
alse rc =3D MDB_NOTFOUND
return rc;
}<-------- executed
if (mc->mc_flags & C_DEL)
mc->mc_flags ^=3D C_DEL;
/* Cursor is positioned, check for room in the dirty list *=
/
if (!nospill) { <-------- true
if (flags & MDB_MULTIPLE) {
rdata =3D &xdata;
xdata.mv_size =3D data->mv_=
size * dcount;
} else {
rdata =3D data; <-------- e=
xecuted
}
if ((rc2 =3D mdb_page_spill(mc, key, rdata)=
)) <-------- returned 0 or would have returned
return rc2;
}<-------- executed
if (rc =3D=3D MDB_NO_ROOT) { <-------- false
MDB_page *np;
/* new database, write a root leaf page */
DPUTS("allocating new root leaf page");
if ((rc2 =3D mdb_page_new(mc, P_LEAF, 1, &n=
p))) {
return rc2;
}
mdb_cursor_push(mc, np);
mc->mc_db->md_root =3D np->mp_pgno;
mc->mc_db->md_depth++;
*mc->mc_dbflag |=3D DB_DIRTY;
if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB=
_DUPFIXED))
=3D=3D MDB_DUPFIXED)
np->mp_flags |=3D P_LEAF2;
mc->mc_flags |=3D C_INITIALIZED;
} else {
/* make sure all cursor pages are writable =
*/
rc2 =3D mdb_cursor_touch(mc); <-------- is =
this called and returns 0 because it does not return
if (rc2)
return rc2;
} <-------- executed
insert_key =3D insert_data =3D rc; <-------- rc =3D -30798 =
or MDB_NOTFOUND!
if (insert_key) { <-------- true
/* The key does not exist */
DPRINTF(("inserting key at index %i", mc->m=
c_ki[mc->mc_top]));
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
LEAFSIZE(key, data) > env->=
me_nodemax) <-------- false since mc->mc_db->md_flags =3D 0
{
/* Too big for a node, inse=
rt in sub-DB. Set up an empty
* "old sub-page" for prep_s=
ubDB to expand to a full page.
*/
fp_flags =3D P_LEAF|P_DIRTY=
;
fp =3D env->me_pbuf;
fp->mp_pad =3D data->mv_siz=
e; /* used if MDB_DUPFIXED */
fp->mp_lower =3D fp->mp_upp=
er =3D (PAGEHDRSZ-PAGEBASE);
olddata.mv_size =3D PAGEHDR=
SZ;
goto prep_subDB;
} <-------- this was not executed, and the =
very long external else contingency below should be skipped!
} else {
/* there's only a key anyway, so this is a =
no-op */
if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
char *ptr;
unsigned int ksize =3D mc->=
mc_db->md_pad;
if (key->mv_size !=3D ksize=
)
return MDB_=
BAD_VALSIZE;
ptr =3D LEAF2KEY(mc->mc_pg[=
mc->mc_top], mc->mc_ki[mc->mc_top], ksize);
memcpy(ptr, key->mv_data, k=
size);
fix_parent:
/* if overwriting slot 0 of=
leaf, need to
* update branch key if ther=
e is a parent page
*/
if (mc->mc_top && !mc->mc_k=
i[mc->mc_top]) {
unsigned sh=
ort dtop =3D 1;
mc->mc_top-=
-;
/* slot 0 i=
s always an empty key, find real slot */
while (mc->=
mc_top && !mc->mc_ki[mc->mc_top]) {
=
mc->mc_top--;
=
dtop++;
}
if (mc->mc_=
ki[mc->mc_top])
=
rc2 =3D mdb_update_key(mc, key);
else
=
rc2 =3D MDB_SUCCESS;
mc->mc_top =
+=3D dtop;
if (rc2)
=
return rc2;
}
return MDB_SUCCESS;
}
more:
leaf =3D NODEPTR(mc->mc_pg[mc->mc_top], mc-=
>mc_ki[mc->mc_top]);
olddata.mv_size =3D NODEDSZ(leaf);
olddata.mv_data =3D NODEDATA(leaf);
/* DB has dups? */
if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSOR=
T)) {
/* Prepare (sub-)page/sub-D=
B to accept the new item,
* if needed. fp: old sub-p=
age or a header faking
* it. mp: new (sub-)page. =
offset: growth in page
* size. xdata: node data w=
ith new page or DB.
*/
unsigned i, off=
set =3D 0;
mp =3D fp =3D xdata.mv_data=
=3D env->me_pbuf;
mp->mp_pgno =3D mc->mc_pg[m=
c->mc_top]->mp_pgno;
/* Was a single item before=
, must convert now */
if (!F_ISSET(leaf->mn_flags=
, F_DUPDATA)) {
MDB_cmp_fun=
c *dcmp;
/* Just ove=
rwrite the current item */
if (flags =
=3D=3D MDB_CURRENT)
=
goto current;
dcmp =3D mc=
->mc_dbx->md_dcmp;
#if UINT_MAX < SIZE_MAX
if (dcmp =
=3D=3D mdb_cmp_int && olddata.mv_size =3D=3D sizeof(size_t))
=
dcmp =3D mdb_cmp_clong;
#endif
/* does dat=
a match? */
if (!dcmp(d=
ata, &olddata)) {
=
if (flags & (MDB_NODUPDATA|MDB_APPENDDUP))
=
return MDB_KEYEXIST;
=
/* overwrite it */
=
goto current;
}
/* Back up =
original data item */
dkey.mv_siz=
e =3D olddata.mv_size;
dkey.mv_dat=
a =3D memcpy(fp+1, olddata.mv_data, olddata.mv_size);
/* Make sub=
-page header for the dup items, with dummy body */
fp->mp_flag=
s =3D P_LEAF|P_DIRTY|P_SUBP;
fp->mp_lowe=
r =3D (PAGEHDRSZ-PAGEBASE);
xdata.mv_si=
ze =3D PAGEHDRSZ + dkey.mv_size + data->mv_size;
if (mc->mc_=
db->md_flags & MDB_DUPFIXED) {
=
fp->mp_flags |=3D P_LEAF2;
=
fp->mp_pad =3D data->mv_size;
=
xdata.mv_size +=3D 2 * data->mv_size; /* leave space for 2 more *=
/
} else {
=
xdata.mv_size +=3D 2 * (sizeof(indx_t) + NODESIZE) +
=
(dkey.mv_size & 1) + (data->mv_size & 1);
}
fp->mp_uppe=
r =3D xdata.mv_size - PAGEBASE;
olddata.mv_=
size =3D xdata.mv_size; /* pretend olddata is fp */
} else if (leaf->mn_flags &=
F_SUBDATA) {
/* Data is =
on sub-DB, just store it */
flags |=3D =
F_DUPDATA|F_SUBDATA;
goto put_su=
b;
} else {
/* Data is =
on sub-page */
fp =3D oldd=
ata.mv_data;
switch (fla=
gs) {
default:
=
if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
=
offset =3D EVEN(NODESIZE + sizeof(indx_t) +
=
data->mv_size);
=
break;
=
}
=
offset =3D fp->mp_pad;
=
if (SIZELEFT(fp) < offset) {
=
offset *=3D 4; /* space for 4 more */
=
break;
=
}
=
/* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
case MDB_CU=
RRENT:
=
fp->mp_flags |=3D P_DIRTY;
=
COPY_PGNO(fp->mp_pgno, mp->mp_pgno);
=
mc->mc_xcursor->mx_cursor.mc_pg[0] =3D fp;
=
flags |=3D F_DUPDATA;
=
goto put_sub;
}
xdata.mv_si=
ze =3D olddata.mv_size + offset;
}
fp_flags =3D fp->mp_flags;
if (NODESIZE + NODEKSZ(leaf=
) + xdata.mv_size > env->me_nodemax) {
=
/* Too big for a sub-page, convert to sub-DB */
=
fp_flags &=3D ~P_SUBP;
prep_subDB:
=
if (mc->mc_db->md_flags & MDB_DUPFIXED) {
=
fp_flags |=3D P_LEAF2;
=
dummy.md_pad =3D fp->mp_pad;
=
dummy.md_flags =3D MDB_DUPFIXED;
=
if (mc->mc_db->md_flags & MDB_INTEGERDUP)
=
dummy.md_flags |=3D MDB_INTEGERKEY;
=
} else {
=
dummy.md_pad =3D 0;
=
dummy.md_flags =3D 0;
=
}
=
dummy.md_depth =3D 1;
=
dummy.md_branch_pages =3D 0;
=
dummy.md_leaf_pages =3D 1;
=
dummy.md_overflow_pages =3D 0;
=
dummy.md_entries =3D NUMKEYS(fp);
=
xdata.mv_size =3D sizeof(MDB_db);
=
xdata.mv_data =3D &dummy;
=
if ((rc =3D mdb_page_alloc(mc, 1, &mp)))
=
return rc;
=
offset =3D env->me_psize - olddata.mv_size;
=
flags |=3D F_DUPDATA|F_SUBDATA;
=
dummy.md_root =3D mp->mp_pgno;
=
sub_root =3D mp;
}
if (mp !=3D fp) {
mp->mp_flag=
s =3D fp_flags | P_DIRTY;
mp->mp_pad =
=3D fp->mp_pad;
mp->mp_lowe=
r =3D fp->mp_lower;
mp->mp_uppe=
r =3D fp->mp_upper + offset;
if (fp_flag=
s & P_LEAF2) {
=
memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad);
} else {
=
memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper=
+ PAGEBASE,
=
olddata.mv_size - fp->mp_upper - PAGEBASE);
=
for (i=3D0; i<NUMKEYS(fp); i++)
=
mp->mp_ptrs[i] =3D fp->mp_ptrs[i] + offset;
}
}
rdata =3D &xdata;
flags |=3D F_DUPDATA;
do_sub =3D 1;
if (!insert_key)
mdb_node_de=
l(mc, 0);
goto new_sub;
}
current:
/* LMDB passes F_SUBDATA in 'flags' to writ=
e a DB record */
if ((leaf->mn_flags ^ flags) & F_SUBDATA)
return MDB_INCOMPATIBLE;
/* overflow page overwrites need special ha=
ndling */
if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { <=
-------- is this taken?
MDB_page *omp;
pgno_t pg;
int level, ovpages, dpages =
=3D OVPAGES(data->mv_size, env->me_psize);
memcpy(&pg, olddata.mv_data=
, sizeof(pg));
if ((rc2 =3D mdb_page_get(m=
c->mc_txn, pg, &omp, &level)) !=3D 0)
return rc2;
ovpages =3D omp->mp_pages;
/* Is the ov page large eno=
ugh? */
if (ovpages >=3D dpages) {
if (!(omp->mp_flags & P_D=
IRTY) &&
(level ||=
(env->me_flags & MDB_WRITEMAP)))
{
rc =3D mdb_=
page_unspill(mc->mc_txn, omp, &omp); <-------- is this taken?
if (rc)
=
return rc;
level =3D 0=
; /* dirty in this txn or clean */
}
/* Is it dirty? */
if (omp->mp_flags & P_DIR=
TY) {
/* yes, ove=
rwrite it. Note in this case we don't
* bother to=
try shrinking the page if the new data
* is smalle=
r than the overflow threshold.
*/
if (level >=
1) {
=
/* It is writable only in a parent txn */
=
size_t sz =3D (size_t) env->me_psize * ovpages, off;
=
MDB_page *np =3D mdb_page_malloc(mc->mc_txn, ovpages);
=
MDB_ID2 id2;
=
if (!np)
=
return ENOMEM;
=
id2.mid =3D pg;
=
id2.mptr =3D np;
=
/* Note - this page is already counted in parent's dirty_room */
=
rc2 =3D mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
=
mdb_cassert(mc, rc2 =3D=3D 0);
=
if (!(flags & MDB_RESERVE)) {
=
/* Copy end of page, adjusting alignment so
=
* compiler may copy words instead of bytes.
=
*/
=
off =3D (PAGEHDRSZ + data->mv_size) & -sizeof(size_t);
=
memcpy((size_t *)((char *)np + off),
=
(size_t *)((char *)omp + off), sz - of=
f);
=
sz =3D PAGEHDRSZ;
=
}
=
memcpy(np, omp, sz); /* Copy beginning of page */
=
omp =3D np;
}
SETDSZ(leaf=
, data->mv_size);
if (F_ISSET=
(flags, MDB_RESERVE))
=
data->mv_data =3D METADATA(omp);
else
=
memcpy(METADATA(omp), data->mv_data, data->mv_size);
return MDB_=
SUCCESS;
}
}
if ((rc2 =3D mdb_ovpage_fre=
e(mc, omp)) !=3D MDB_SUCCESS)
return rc2;
} else if (data->mv_size =3D=3D olddata.mv_=
size) {
/* same size, just replace =
it. Note that we could
* also reuse this node if t=
he new data is smaller,
* but instead we opt to shr=
ink the node in that case.
*/
if (F_ISSET(flags, MDB_RESE=
RVE))
data->mv_da=
ta =3D olddata.mv_data;
else if (!(mc->mc_flags & C=
_SUB))
memcpy(oldd=
ata.mv_data, data->mv_data, data->mv_size);
else {
memcpy(NODE=
KEY(leaf), key->mv_data, key->mv_size);
goto fix_pa=
rent;
}
return MDB_SUCCESS;
}
mdb_node_del(mc, 0);
} <-------- This entire else contingency was likely skipped=
!!
rdata =3D data;
new_sub:
nflags =3D flags & NODE_ADD_FLAGS;
nsize =3D IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : =
mdb_leaf_size(env, key, rdata); <-------- SEGV
...
This may be an identifiable bug in mdb_cursor_put() as It does not safely h=
andle the case when the noted call to mdb_cursor_set() returns MDB_NOTFOUND=
(-30798)!
It explicitly fails to preemptively exit by returning an error in this case=
.
The value of -30798 is in turn assigned to insert_key, which is therefore n=
on-null in the condition of the subsequent if statement.
insert_key =3D insert_data =3D rc; <-------- insert_key =3D=
-30798 or MDB_NOTFOUND!
if (insert_key) { <-------- true
/* The key does not exist */
DPRINTF(("inserting key at index %i", mc->m=
c_ki[mc->mc_top]));
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
LEAFSIZE(key, data) > env->=
me_nodemax) <-------- false since mc->mc_db->md_flags =3D 0
{
/* Too big for a node, inse=
rt in sub-DB. Set up an empty
* "old sub-page" for prep_s=
ubDB to expand to a full page.
*/
fp_flags =3D P_LEAF|P_DIRTY=
;
fp =3D env->me_pbuf;
fp->mp_pad =3D data->mv_siz=
e; /* used if MDB_DUPFIXED */
fp->mp_lower =3D fp->mp_upp=
er =3D (PAGEHDRSZ-PAGEBASE);
olddata.mv_size =3D PAGEHDR=
SZ;
goto prep_subDB;
} <-------- this was not executed, and the =
very long else contingency below is skipped!
} else {
Since mc->mc_db->md_flags =3D 0, the contingency in the embedded if stateme=
nt fails.
The segmentation fault occurs due to the call of IS_LEAF2 on the null point=
er mc->mc_pg[0].
rdata =3D data;
new_sub:
nflags =3D flags & NODE_ADD_FLAGS;
nsize =3D IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : =
mdb_leaf_size(env, key, rdata); <-------- SEGV
Regards,
Robins.
--_000_MN2PR06MB55017A7261FA27380778753BAFEA0MN2PR06MB5501namp_
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"=
>
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
{mso-style-priority:99;
mso-style-link:"Plain Text Char";
margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
span.PlainTextChar
{mso-style-name:"Plain Text Char";
mso-style-priority:99;
mso-style-link:"Plain Text";
font-family:"Calibri",sans-serif;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=3D"EN-US" link=3D"#0563C1" vlink=3D"#954F72">
<div class=3D"WordSection1">
<p class=3D"MsoPlainText"><repost since the previous message came as 64 =
encoded, apologies><o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Hello Howard,<o:p></o:p></p>
<p class=3D"MsoPlainText">we are not able to reproduce the issue consistent=
ly so test code is not available at this time, and I do believe this issue =
will be present in the latest code as well since Myk also reported the same=
.. Attaching analysis from our side,
hope it helps.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">The call stack what we have seen is,<o:p></o:p></=
p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> #0 0x0011b62e in mdb_cursor_pu=
t (mc=3D0xffe52d18, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.=
c:6688<o:p></o:p></p>
<p class=3D"MsoPlainText"> #1 0x0011c8ec in mdb_put (txn=
=3D0xdc13f008, dbi=3D2, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at =
mdb.c:8771<o:p></o:p></p>
<p class=3D"MsoPlainText"> #2 0x00b792b8 in LMDB::LMDBCon=
text::createSession (this=3D0x80ca418, sid=3D0x8297be4 "sidebf3708f0fd=
9fcb8e062529da47adf51402dfc4600000000+") at lmdbint.cc:460<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> #3 0x08053564 in updateLMDB (r=
equest=3D..., forward=3D@0xffe5315f) at sessionserver.cc:1075<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> #4 processRequestWithoutRespon=
se (request=3D..., forward=3D@0xffe5315f) at sessionserver.cc:1160<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> #5 0x08056a80 in processReques=
t (this=3D0x80b2ac0, fd=3D33) at sessionserver.cc:1189<o:p></o:p></p>
<p class=3D"MsoPlainText"> #6 readFromSock (this=3D0x80b2=
ac0, fd=3D33) at sessionserver.cc:1342<o:p></o:p></p>
<p class=3D"MsoPlainText"> #7 SockHandler::ioReady (this=
=3D0x80b2ac0, fd=3D33) at sessionserver.cc:1455<o:p></o:p></p>
<p class=3D"MsoPlainText"> #8 0x00ba2592 in runCoreDispat=
cher (default_t=3D<value optimized out>, flags=3D-1) at fds.cc:889<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> #9 0x00ba2ff7 in DSEvntFds::ru=
nDispatcher () at fds.cc:945<o:p></o:p></p>
<p class=3D"MsoPlainText"> #10 0x080559c6 in main () at s=
essionserver.cc:1739<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Here it is helpful to examine frames #0 and #1 in=
detail in relation to the relevant source code /libraries/liblmdb/mdb.c.<o=
:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Frame #1<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">#1 0x0011c8ec in mdb_put (txn=3D0xdc13f008,=
dbi=3D2, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.c:8771<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> mc =3D=
{mc_next =3D 0x0, mc_backup =3D 0x0, mc_xcursor =3D 0x0, mc_txn =3D 0xdc13=
f008, mc_dbi =3D 2, mc_db =3D 0xdc13f088, mc_dbx =3D 0xe1215038, mc_dbflag =
=3D 0xdc1cf09a "\033", '\032' <repeats 51 times>, mc_snum =
=3D 0, mc_top =3D 0, mc_flags =3D 0,
mc_pg =3D {0x0, 0x80b2ac0, 0xffe52d68, 0x28afce, 0xdc13f008, 0x80ce9b0, 0x=
ffe52dc8, 0x4c5ff4, 0x2b, 0x80b2ac0, 0xffe52d98, 0x49209a, 0x2b, 0x4c5ff4, =
0x2121cb, 0x21576c, 0x8297d34, 0x3497af, 0x21576c, 0x21316a, 0x8297d34, 0x8=
0ac7b0, 0x1e, 0x46eed6, 0x2b, 0x0,
0x80ce9b0, 0x4c5ff4, 0x80ac7b0, 0x8297d34, 0xffe52df8, 0x46fb96}, mc_ki =
=3D {0, 2089, 51120, 2058, 30, 0, 16796, 17, 11760, 65509, 3, 0, 32040, 208=
9, 30, 0, 0, 0, 0, 0, 3, 0, 24564, 76, 51120, 2058, 10944, 2059, 11800, 655=
09, 64758, 70}} <--------<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; <o:p></o:p></p>
<p class=3D"MsoPlainText"> mx =3D=
{mx_cursor =3D {mc_next =3D 0x38, mc_backup =3D 0x3, mc_xcursor =3D 0x0, m=
c_txn =3D 0x0, mc_dbi =3D 0, mc_db =3D 0x28, mc_dbx =3D 0x0, mc_dbflag =3D =
0x0, mc_snum =3D 3, mc_top =3D 0, mc_flags =3D 17, mc_pg =3D {0x3a93d8, 0x1=
0, 0x0, 0x18, 0x3a93a0,
0x0, 0x3a93d0, 0x289abe, 0x3a93a0, 0xffe52d3f, 0xffe52c68, 0x28afce, 0xffe=
52dbc, 0xffe52db4, 0x3, 0x4c5ff4, 0x11, 0x36c99b, 0x6e, 0x77, 0x7c, 0x5b, 0=
x38, 0x289abe, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x3, 0x10}, mc_ki =3D {37848,=
58, 51611, 54, 110, 0, 119, 0, 124,
0, 91, 0, 58, 0, 39614, 40, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 2, 0, 18, 0, 1=
36, 0}}, mx_db =3D {md_pad =3D 3838936, md_flags =3D 51611, md_depth =3D 54=
, md_branch_pages =3D 110, md_leaf_pages =3D 119, md_overflow_pages =3D 124=
, md_entries =3D 91, md_root =3D 56}, mx_dbx =3D {md_name
=3D {mv_size =3D 6, mv_data =3D 0x0}, md_cmp =3D 0, md_dcmp =3D 0, md_rel =
=3D 0x40, md_relctx =3D 0x0}, mx_dbflag =3D 0 '\000'}<o:p></o:p></p>
<p class=3D"MsoPlainText"> rc =3D=
0 <o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">And source code for mdb_put() is from mdb.c<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">int<o:p></o:p></p>
<p class=3D"MsoPlainText">mdb_put(MDB_txn *txn, MDB_dbi dbi,<o:p></o:p></p>
<p class=3D"MsoPlainText"> MDB_val *key, MDB_val *data, u=
nsigned int flags) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_cursor mc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_xcursor mx;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; int rc;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (!key || !data || !TXN_DBI_EXI=
ST(txn, dbi, DB_USRVALID))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return EINVA=
L;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (flags & ~(MDB_NOOVERWRITE=
|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return EINVA=
L;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (txn->mt_flags & (MDB_T=
XN_RDONLY|MDB_TXN_BLOCKED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return (txn-=
>mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mdb_cursor_init(&mc, txn, dbi=
, &mx); <-------- see source code below<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc.mc_next =3D txn->mt_cursors=
[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; txn->mt_cursors[dbi] =3D &=
mc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; rc =3D mdb_cursor_put(&mc, ke=
y, data, flags); <-------- see Frame #0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; txn->mt_cursors[dbi] =3D mc.mc=
_next;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; return rc;<o:p></o:p></p>
<p class=3D"MsoPlainText">}<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Source Code For mdb_cursor_init() From mdb.c<o:p>=
</o:p></p>
<p class=3D"MsoPlainText">/** Initialize a cursor for a given transaction a=
nd database. */ static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, M=
DB_dbi dbi, MDB_xcursor *mx) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_next =3D NULL;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_backup =3D NULL;<o:p></=
o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_dbi =3D dbi;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_txn =3D txn;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_db =3D &txn->mt_=
dbs[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_dbx =3D &txn->mt=
_dbxs[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_dbflag =3D &txn->=
;mt_dbflags[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_snum =3D 0; <-------=
- <o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_top =3D 0; <--------=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_pg[0] =3D 0; <------=
-- <o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_ki[0] =3D 0;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_flags =3D 0;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; if (txn->mt_dbs[dbi].md_flags =
& MDB_DUPSORT) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_tassert(=
txn, mx !=3D NULL);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_xc=
ursor =3D mx;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_xcursor_=
init0(mc);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_xc=
ursor =3D NULL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (*mc->mc_dbflag & DB_ST=
ALE) { <-------- false *mc->mc_dbflag =3D 27, DB_STALE =3D 0x02 =
&nb=
sp; /**< Named-DB record is older than txnID */<o:p></=
o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_page_sea=
rch(mc, NULL, MDB_PS_ROOTONLY);
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText">}<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">From this we know that when mdb_cursor_put() is c=
alled, the following values remain assigned:<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_snum =3D 0; <--------<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_top =3D 0; <--------=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_pg[0] =3D 0; <------=
-- <o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">and its noted these two values still have their i=
nitial values at the time of the segmentation fault.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">(gdb) fr 0<o:p></o:p></p>
<p class=3D"MsoPlainText">#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18,=
key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.c:6688<o:p></o:p></=
p>
<p class=3D"MsoPlainText">6688 in mdb.c<o:p></o:p></p>
<p class=3D"MsoPlainText">(gdb) p mc->mc_top<o:p></o:p></p>
<p class=3D"MsoPlainText">$1 =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText">(gdb) p mc->mc_pg[mc->mc_top]<o:p></o:p></p=
>
<p class=3D"MsoPlainText">$19 =3D (MDB_page *) 0x0<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Let us consider how the path taken through mdb_cu=
rsor_put() could account for these null variable values which result in a s=
egmentation fault.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Frame #0<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe=
52d18, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.c:6688 <--=
------ flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> env =
=3D 0x80ce9b0<o:p></o:p></p>
<p class=3D"MsoPlainText"> leaf =
=3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> fp =3D=
<value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> mp =3D=
0x38<o:p></o:p></p>
<p class=3D"MsoPlainText"> sub_ro=
ot =3D 0x0 <o:p></o:p></p>
<p class=3D"MsoPlainText"> f=
p_flags =3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> xdata =
=3D {mv_size =3D 3838880, mv_data =3D 0xdc1cf09a}<o:p></o:p></p>
<p class=3D"MsoPlainText"> rdata =
=3D 0xffe52e6c<o:p></o:p></p>
<p class=3D"MsoPlainText"> dkey =
=3D {mv_size =3D 0, mv_data =3D 0x3a93cc}<o:p></o:p></p>
<p class=3D"MsoPlainText"> olddat=
a =3D {mv_size =3D 22, mv_data =3D 0x36c820}<o:p></o:p></p>
<p class=3D"MsoPlainText"> dummy =
=3D {md_pad =3D 22, md_flags =3D 11128, md_depth =3D 65509, md_branch_pages=
=3D 16, md_leaf_pages =3D 1507329, md_overflow_pages =3D 0, md_entries =3D=
3838928, md_root =3D 3833844}<o:p></o:p></p>
<p class=3D"MsoPlainText"> do_sub=
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> insert=
_key =3D -30798 <-------- #define MDB_NOTFOUND &n=
bsp; (-30798)<o:p></o:p></p>
<p class=3D"MsoPlainText"> insert=
_data =3D -30798 <-------- #define MDB_NOTFOUND &=
nbsp; (-30798)<o:p></o:p></p>
<p class=3D"MsoPlainText"> mcount=
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> dcount=
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> nospil=
l =3D 0 <--------<o:p></o:p></p>
<p class=3D"MsoPlainText"> nsize =
=3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> rc =3D=
0 <o:p></o:p></p>
<p class=3D"MsoPlainText"> r=
c2 =3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> nflags=
=3D 0 <--------<o:p></o:p></p>
<p class=3D"MsoPlainText"> __func=
__ =3D "mdb_cursor_put" =
<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">We know that mc->mc_top and mc->mc_pg[0] we=
re initialized to 0 in mdb_cursor_init(). As my annotations of the source c=
ode below suggest, careful analysis reveals that the paths actually taken t=
hrough mdb_cursor_put() do not modify these
assignments.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Excerpted Source Code For mdb_cursor_put() From m=
db.c<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">int<o:p></o:p></p>
<p class=3D"MsoPlainText">mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_=
val *data,<o:p></o:p></p>
<p class=3D"MsoPlainText"> unsigned int flags)<o:p></o:p>=
</p>
<p class=3D"MsoPlainText">{<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_env &n=
bsp;  =
; *env;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_node &=
nbsp; *leaf =3D NULL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_page &=
nbsp; *fp, *mp, *sub_root =3D NULL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; uint16_t &=
nbsp; fp_flags;<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_val &n=
bsp;  =
; x=
data, *rdata, dkey, olddata;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_db dummy;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; int do_sub =3D 0, insert_key, ins=
ert_data;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; unsigned int mcount =3D 0, dcount=
=3D 0, nospill;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; size_t nsize;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; int rc, rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; unsigned int nflags;<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; DKBUF;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (mc =3D=3D NULL || key =3D=3D =
NULL)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return EINVA=
L;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; env =3D mc->mc_txn->mt_env;=
<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; /* Check this first so counter wi=
ll always be zero on any<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; * early failures.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (flags & MDB_MULTIPLE) {<o=
:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; dcount =3D d=
ata[1].mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; data[1].mv_s=
ize =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (!F_ISSET=
(mc->mc_db->md_flags, MDB_DUPFIXED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_INCOMPATIBLE;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nospill =3D flags & MDB_NOSPI=
LL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; flags &=3D ~MDB_NOSPILL;<o:p>=
</o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (mc->mc_txn->mt_flags &a=
mp; (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return (mc-&=
gt;mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;<o:p></=
o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (key->mv_size-1 >=3D ENV=
_MAXKEY(env))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return MDB_B=
AD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">#if SIZE_MAX > MAXDATASIZE<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (data->mv_size > ((mc-&g=
t;mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))<o=
:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return MDB_B=
AD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText">#else<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if ((mc->mc_db->md_flags &a=
mp; MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env))<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return MDB_B=
AD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText">#endif<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; DPRINTF(("=3D=3D> put db =
%d key [%s], size %"Z"u, data size %"Z"u",<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DDBI(mc), DK=
EY(key), key ? key->mv_size : 0, data->mv_size));<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; dkey.mv_size =3D 0;<o:p></o:p></p=
>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (flags =3D=3D MDB_CURRENT) { &=
lt;-------- false flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (!(mc->=
;mc_flags & C_INITIALIZED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; =
&nb=
sp; return EINVAL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; rc =3D MDB_S=
UCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else if (mc->mc_db->md_ro=
ot =3D=3D P_INVALID) { <-------- false, mc->mc_db->md_root =3D 68<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* new datab=
ase, cursor has nothing to point to */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_sn=
um =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_to=
p =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_fl=
ags &=3D ~C_INITIALIZED;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; rc =3D MDB_N=
O_ROOT; <o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else { <-------- executed<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; int exact =
=3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; MDB_val d2;<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (flags &a=
mp; MDB_APPEND) { <-------- false flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_val k2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D mdb_cursor_last(mc, &k2, &d2);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (rc =3D=3D 0) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; rc =3D mc->mc_dbx->md_cmp(key, &k2)=
;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (rc > 0) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D MDB_NOTFOUND;<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mc->mc_ki[mc->mc_t=
op]++;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* new key is <=3D la=
st key */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D MDB_KEYEXIST;<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } else {<=
-------- executed<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D mdb_cursor_set(mc, key, &d2, MDB_SET, &exact); <=
-------- returns -30798 which is MDB_NOTFOUND<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<-------=
- executed<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((flags &=
amp; MDB_NOOVERWRITE) && rc =3D=3D 0) { <-------- false flags =
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; DPRINTF(("duplicate key [%s]", DKEY(key)));<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; *data =3D d2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_KEYEXIST;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (rc &=
& rc !=3D MDB_NOTFOUND) <-------- false rc =3D MDB_NOTFOUND<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<-------- executed<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (mc->mc_flags & C_DEL)<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_fl=
ags ^=3D C_DEL;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; /* Cursor is positioned, check fo=
r room in the dirty list */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (!nospill) { <-------- true=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (flags &a=
mp; MDB_MULTIPLE) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rdata =3D &xdata;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size =3D data->mv_size * dcount;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } else {<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rdata =3D data; <-------- executed<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((rc2 =3D=
mdb_page_spill(mc, key, rdata))) <-------- returned 0 or would have ret=
urned<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<-------- executed<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (rc =3D=3D MDB_NO_ROOT) { <=
-------- false <o:p>
</o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; MDB_page *np=
;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* new datab=
ase, write a root leaf page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DPUTS("=
allocating new root leaf page");<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((rc2 =3D=
mdb_page_new(mc, P_LEAF, 1, &np))) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_cursor_p=
ush(mc, np);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_db=
->md_root =3D np->mp_pgno;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_db=
->md_depth++;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; *mc->mc_d=
bflag |=3D DB_DIRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((mc->=
mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; =3D=3D MDB_DUPFIXED)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; np->mp_flags |=3D P_LEAF2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_fl=
ags |=3D C_INITIALIZED;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* make sure=
all cursor pages are writable */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; rc2 =3D mdb_=
cursor_touch(mc); <-------- is this called and returns 0 because it does=
not return<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (rc2)<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } <-------- executed<o:p></o:p=
></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; insert_key =3D insert_data =3D rc=
; <-------- rc =3D -30798 or MDB_NOTFOUND!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (insert_key) { <-------- tr=
ue<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* The key d=
oes not exist */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DPRINTF((&qu=
ot;inserting key at index %i", mc->mc_ki[mc->mc_top]));<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((mc->=
mc_db->md_flags & MDB_DUPSORT) &&<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; LEAFSIZE(key, data) > env->me_nodemax) <-------- false si=
nce mc->mc_db->md_flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; {<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Too big for a node, insert in sub-DB. Set up an empty<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * "old sub-page" for prep_subDB to expand to a full page=
.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags =3D P_LEAF|P_DIRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp =3D env->me_pbuf;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_pad =3D data->mv_size; /* used if MDB_DUPFIXED */<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_lower =3D fp->mp_upper =3D (PAGEHDRSZ-PAGEBASE);<o:p>=
</o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; olddata.mv_size =3D PAGEHDRSZ;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto prep_subDB;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } <------=
-- this was not executed, and the very long external else contingency below=
should be skipped!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* there's o=
nly a key anyway, so this is a no-op */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (IS_LEAF2=
(mc->mc_pg[mc->mc_top])) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; char *ptr;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; unsigned int ksize =3D mc->mc_db->md_pad;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (key->mv_size !=3D ksize)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return MDB_BAD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; ptr =3D LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->=
mc_top], ksize);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(ptr, key->mv_data, ksize);<o:p></o:p></p>
<p class=3D"MsoPlainText">fix_parent:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* if overwriting slot 0 of leaf, need to<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * update branch key if there is a parent page<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (mc->mc_top && !mc->mc_ki[mc->mc_top]) {<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; unsigned short dtop =3D 1;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mc->mc_top--;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* slot 0 is always an empty key, find real s=
lot */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; while (mc->mc_top && !mc->mc_ki=
[mc->mc_top]) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mc->mc_top--;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dtop++;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (mc->mc_ki[mc->mc_top])<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc2 =3D mdb_update_key(m=
c, key);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; else<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc2 =3D MDB_SUCCESS;<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mc->mc_top +=3D dtop;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (rc2)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_SUCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">more:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; leaf =3D NOD=
EPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; olddata.mv_s=
ize =3D NODEDSZ(leaf);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; olddata.mv_d=
ata =3D NODEDATA(leaf);<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* DB has du=
ps? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (F_ISSET(=
mc->mc_db->md_flags, MDB_DUPSORT)) {
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Prepare (sub-)page/sub-DB to accept the new item,<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * if needed. fp: old sub-page or a header faking<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * it. mp: new (sub-)page. offset: growth in page<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * size. xdata: node data with new page or DB.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; unsigned &nbs=
p; i, offset =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mp =3D fp =3D xdata.mv_data =3D env->me_pbuf;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mp->mp_pgno =3D mc->mc_pg[mc->mc_top]->mp_pgno;<o:p></=
o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Was a single item before, must convert now */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; MDB_cmp_func *dcmp;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Just overwrite the current item */<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (flags =3D=3D MDB_CURRENT)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto current;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dcmp =3D mc->mc_dbx->md_dcmp;<o:p></o:p=
></p>
<p class=3D"MsoPlainText">#if UINT_MAX < SIZE_MAX<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (dcmp =3D=3D mdb_cmp_int && olddat=
a.mv_size =3D=3D sizeof(size_t))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dcmp =3D mdb_cmp_clong;<=
o:p></o:p></p>
<p class=3D"MsoPlainText">#endif<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* does data match? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (!dcmp(data, &olddata)) {<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (flags & (MDB_NOD=
UPDATA|MDB_APPENDDUP))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; ret=
urn MDB_KEYEXIST;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* overwrite it */<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto current;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Back up original data item */<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dkey.mv_size =3D olddata.mv_size;<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dkey.mv_data =3D memcpy(fp+1, olddata.mv_=
data, olddata.mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Make sub-page header for the dup items, wi=
th dummy body */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp->mp_flags =3D P_LEAF|P_DIRTY|P_SUBP;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp->mp_lower =3D (PAGEHDRSZ-PAGEBASE);<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; xdata.mv_size =3D PAGEHDRSZ + dkey.mv_siz=
e + data->mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; =
&nb=
sp; =
if (mc->mc_db->md_flags & MDB_DUPFIXED) =
{<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_flags |=3D P_L=
EAF2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_pad =3D data-&=
gt;mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size +=3D 2=
* data->mv_size; /* leave space for 2 mor=
e */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size +=3D 2=
* (sizeof(indx_t) + NODESIZE) +<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; (dk=
ey.mv_size & 1) + (data->mv_size & 1);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp->mp_upper =3D xdata.mv_size - PAGEBASE;=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; olddata.mv_size =3D xdata.mv_size; /* pretend=
olddata is fp */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; } else if (leaf->mn_flags & F_SUBDATA) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Data is on sub-DB, just store it */<o:p></=
o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; flags |=3D F_DUPDATA|F_SUBDATA;<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; goto put_sub;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Data is on sub-page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp =3D olddata.mv_data;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; switch (flags) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; default:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!(mc->mc_db->m=
d_flags & MDB_DUPFIXED)) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; off=
set =3D EVEN(NODESIZE + sizeof(indx_t) +<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; data->mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; bre=
ak;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; offset =3D fp->mp_pad=
;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (SIZELEFT(fp) < of=
fset) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; off=
set *=3D 4; /* space for 4 more */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; bre=
ak;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* FALLTHRU: Big enough =
MDB_DUPFIXED sub-page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; case MDB_CURRENT:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_flags |=3D P_D=
IRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; COPY_PGNO(fp->mp_pgno=
, mp->mp_pgno);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mc->mc_xcursor->mx=
_cursor.mc_pg[0] =3D fp;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; flags |=3D F_DUPDATA;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto put_sub;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; xdata.mv_size =3D olddata.mv_size + offse=
t;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags =3D fp->mp_flags;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->=
me_nodemax) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Too big for a sub-pag=
e, convert to sub-DB */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags &=3D ~P_SUB=
P;<o:p></o:p></p>
<p class=3D"MsoPlainText">prep_subDB:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (mc->mc_db->md_=
flags & MDB_DUPFIXED) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp_=
flags |=3D P_LEAF2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_pad =3D fp->mp_pad;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_flags =3D MDB_DUPFIXED;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if =
(mc->mc_db->md_flags & MDB_INTEGERDUP)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dummy.md_flags |=3D MDB_INTEGERKEY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_pad =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_flags =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_depth =3D 1;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_branch_pages =
=3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; =
&nb=
sp; =
&nb=
sp; dummy.md_leaf_pages =3D 1;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_overflow_pages =
=3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_entries =3D NUM=
KEYS(fp);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size =3D sizeof=
(MDB_db);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_data =3D &d=
ummy;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if ((rc =3D mdb_page_all=
oc(mc, 1, &mp)))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; ret=
urn rc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; offset =3D env->me_ps=
ize - olddata.mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; flags |=3D F_DUPDATA|F_S=
UBDATA;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_root =3D mp->=
;mp_pgno;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; sub_root =3D mp;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (mp !=3D fp) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_flags =3D fp_flags | P_DIRTY;<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_pad =3D fp->mp_pad;<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_lower =3D fp->mp_lower;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_upper =3D fp->mp_upper + off=
set;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (fp_flags & P_LEAF2) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(METADATA(mp), MET=
ADATA(fp), NUMKEYS(fp) * fp->mp_pad);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy((char *)mp + =
mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGE=
BASE,<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; old=
data.mv_size - fp->mp_upper - PAGEBASE);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; for (i=3D0; i<NUMKEYS=
(fp); i++)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp-=
>mp_ptrs[i] =3D fp->mp_ptrs[i] + offset;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rdata =3D &xdata;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; flags |=3D F_DUPDATA;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; do_sub =3D 1;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!insert_key)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mdb_node_del(mc, 0);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto new_sub;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText">current:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* LMDB pass=
es F_SUBDATA in 'flags' to write a DB record */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((leaf-&g=
t;mn_flags ^ flags) & F_SUBDATA)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_INCOMPATIBLE;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* overflow =
page overwrites need special handling */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (F_ISSET(=
leaf->mn_flags, F_BIGDATA)) { <-------- is this taken?<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_page *omp;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; pgno_t pg;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; int level, ovpages, dpages =3D OVPAGES(data->mv_size, env->m=
e_psize);<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(&pg, olddata.mv_data, sizeof(pg));<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if ((rc2 =3D mdb_page_get(mc->mc_txn, pg, &omp, &level)=
) !=3D 0)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; ovpages =3D omp->mp_pages;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Is the ov page large enough? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (ovpages >=3D dpages) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!(omp->mp_flags & P_DIRTY) &&<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; (level || (env->me_flags & MDB_=
WRITEMAP)))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; rc =3D mdb_page_unspill(mc->mc_txn, omp, &=
amp;omp); <-------- is this taken?<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (rc)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc;<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; level =3D 0; &nb=
sp; =
/* dirty=
in this txn or clean */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Is it dirty? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (omp->mp_flags & P_DIRTY) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* yes, overwrite it. Note in this case we do=
n't<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; * bother to try shrinking the page if the new=
data<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; * is smaller than the overflow threshold.<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (level > 1) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* It is writable only i=
n a parent txn */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; size_t sz =3D (size_t) e=
nv->me_psize * ovpages, off;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_page *np =3D mdb_pag=
e_malloc(mc->mc_txn, ovpages);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_ID2 id2;<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!np)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; ret=
urn ENOMEM;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; id2.mid =3D pg;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; id2.mptr =3D np;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Note - this page is a=
lready counted in parent's dirty_room */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc2 =3D mdb_mid2l_insert=
(mc->mc_txn->mt_u.dirty_list, &id2);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mdb_cassert(mc, rc2 =3D=
=3D 0);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!(flags & MDB_RE=
SERVE)) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* =
Copy end of page, adjusting alignment so<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; * c=
ompiler may copy words instead of bytes.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; */<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; off=
=3D (PAGEHDRSZ + data->mv_size) & -sizeof(size_t);<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mem=
cpy((size_t *)((char *)np + off),<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; (size_t *)((char *)omp + off), sz - off);<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; sz =
=3D PAGEHDRSZ;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(np, omp, sz); /* =
Copy beginning of page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; omp =3D np;<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; SETDSZ(leaf, data->mv_size);<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (F_ISSET(flags, MDB_RESERVE))<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; data->mv_data =3D MET=
ADATA(omp);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; else<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(METADATA(omp), da=
ta->mv_data, data->mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return MDB_SUCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if ((rc2 =3D mdb_ovpage_free(mc, omp)) !=3D MDB_SUCCESS)<o:p></o:p=
></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } else if (d=
ata->mv_size =3D=3D olddata.mv_size) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* same size, just replace it. Note that we could<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * also reuse this node if the new data is smaller,<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * but instead we opt to shrink the node in that case.<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (F_ISSET(flags, MDB_RESERVE))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; data->mv_data =3D olddata.mv_data;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; else if (!(mc->mc_flags & C_SUB))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; memcpy(olddata.mv_data, data->mv_data, dat=
a->mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; memcpy(NODEKEY(leaf), key->mv_data, key-&g=
t;mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; goto fix_parent;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_SUCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_node_del=
(mc, 0);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } <-------- This entire else c=
ontingency was likely skipped!!<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; rdata =3D data;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">new_sub:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nflags =3D flags & NODE_ADD_F=
LAGS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nsize =3D IS_LEAF2(mc->mc_pg[m=
c->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata); <----=
---- SEGV<o:p></o:p></p>
<p class=3D"MsoPlainText">... &nbs=
p; <o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">This may be an identifiable bug in mdb_cursor_put=
() as It does not safely handle the case when the noted call to mdb_cursor_=
set() returns MDB_NOTFOUND (-30798)!<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">It explicitly fails to preemptively exit by retur=
ning an error in this case.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">The value of -30798 is in turn assigned to insert=
_key, which is therefore non-null in the condition of the subsequent if sta=
tement.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; insert_key =3D insert_data =3D rc=
; <-------- insert_key =3D -30798 or MDB_NOTFOUND!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (insert_key) { <-------- tr=
ue<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* The key d=
oes not exist */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DPRINTF((&qu=
ot;inserting key at index %i", mc->mc_ki[mc->mc_top]));<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((mc->=
mc_db->md_flags & MDB_DUPSORT) &&<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; LEAFSIZE(key, data) > env->me_nodemax) <-------- false si=
nce mc->mc_db->md_flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; {<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Too big for a node, insert in sub-DB. Set up an empty<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * "old sub-page" for prep_subDB to expand to a full page=
.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags =3D P_LEAF|P_DIRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp =3D env->me_pbuf;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_pad =3D data->mv_size; /* used if MDB_DUPFIXED */<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_lower =3D fp->mp_upper =3D (PAGEHDRSZ-PAGEBASE);<o:p>=
</o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; olddata.mv_size =3D PAGEHDRSZ;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto prep_subDB;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } <------=
-- this was not executed, and the very long else contingency below is skipp=
ed!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText">Since mc->mc_db->md_flags =3D 0, the contin=
gency in the embedded if statement fails.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">The segmentation fault occurs due to the call of =
IS_LEAF2 on the null pointer mc->mc_pg[0].<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; rdata =3D data;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">new_sub:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nflags =3D flags & NODE_ADD_F=
LAGS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nsize =3D IS_LEAF2(mc->mc_pg[m=
c->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata); <----=
---- SEGV<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoNormal">Regards,<o:p></o:p></p>
<p class=3D"MsoNormal">Robins.<o:p></o:p></p>
</div>
</body>
</html>
--_000_MN2PR06MB55017A7261FA27380778753BAFEA0MN2PR06MB5501namp_--