[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#7886) mdb_ovpage_free() can break mdb_copy



h.b.furuseth@usit.uio.no wrote:
> Full_Name: Hallvard B Furuseth
> Version: LMDB_0.9.13
> OS: Linux x86_64
> URL:
> Submission from: (NULL) (81.191.45.35)
> Submitted by: hallvard
>
>
> Allocate an ovpage from mt_next_pgno, mdb_ovpage_free() it
> and commit: The datafile may end before MDB_meta.mm_last_pg
> since the ovpage was never written.  mdb_env_copyfd() & co
> break when they read the file to mm_last_pg.

fixed in mdb.master
>
> Same with loose pages if mdb_page_flush() skipped them,
> which it could:  ecde3a4008f5080d8264926f49680db27804787f
> in my branch mdb/loose3.
>
> Bug demo:
>
>    rm data.mdb; ./a.out && ./mdb_copy . > copy.mdb
>    ./mdb_copy: copying failed, error 14 (Bad address)
>
> (Piping it to /dev/null succeeds on Linux, apparently
> it doesn't read anything.)
>
> #include "lmdb.h"
> #include <stdio.h>
> #include <stdlib.h>
> #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
> #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
>      "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
>
> int main(void)
> {
>      int rc;
>      unsigned sz;
>      MDB_env *env;
>      MDB_txn *txn;
>      MDB_dbi dbi;
>      static char buf[20000];
>      E(mdb_env_create(&env));
>      E(mdb_env_open(env, ".", 0, 0664));
>      for (sz = 0; sz<=sizeof(buf); sz = (sz==2 ? sizeof(buf) : sz+1)) {
>          E(mdb_txn_begin(env, NULL, 0, &txn));
>          E(mdb_dbi_open(txn, NULL, 0, &dbi));
>          E(mdb_put(txn, dbi, &(MDB_val){4,&sz}, &(MDB_val){sz,buf}, 0));
>          if (sz)
>              E(mdb_del(txn, dbi, &(MDB_val){4,&sz}, NULL));
>          E(mdb_txn_commit(txn));
>      }
>      mdb_env_close(env);
>      return 0;
> }
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/