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])) {
                   /*

Copy-Paste Error [help] 
<http://codesonar.rd.skov.com:7340/install/codesonar/doc/html/CodeSonar.html#WarningClasses/MISC/MISC.CPE.html>
This block of text appears to be a modified copy of the highlighted text.  Did 
you intend to consistently change csrc to cdst, including here?
*/

            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)) {

/*
Use After Free [help] 
<http://codesonar.rd.skov.com:7340/install/codesonar/doc/html/CodeSonar.html#WarningClasses/ALLOC/ALLOC.UAF.html>
The memory pointed to by mp was freed at mdb.c:2047 and is read from here.
        */


         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
www.skov.com<http://www.skov.com/>

Reply via email to