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

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

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