[DRE-commits] [ruby-bdb] 03/12: Add patch 'dont-rely-on-ruby-objects-to-accommodate-c-data'

David Suárez deiv-guest at moszumanska.debian.org
Wed Mar 12 20:40:57 UTC 2014


This is an automated email from the git hooks/post-receive script.

deiv-guest pushed a commit to branch master
in repository ruby-bdb.

commit 28d8d30d10e374436b5f85cbf78cc10beb9e2308
Author: David Suárez <david.sephirot at gmail.com>
Date:   Wed Mar 12 20:21:08 2014 +0100

    Add patch 'dont-rely-on-ruby-objects-to-accommodate-c-data'
---
 ...dont-rely-on-ruby-objects-to-accommodate-c-data | 469 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 2 files changed, 470 insertions(+)

diff --git a/debian/patches/dont-rely-on-ruby-objects-to-accommodate-c-data b/debian/patches/dont-rely-on-ruby-objects-to-accommodate-c-data
new file mode 100644
index 0000000..f5ff144
--- /dev/null
+++ b/debian/patches/dont-rely-on-ruby-objects-to-accommodate-c-data
@@ -0,0 +1,469 @@
+Description: Don't use ruby objects to accommodate C data
+ Fix segfaults, due to incorrect memory access and the use of ruby level functions,
+ in case the ruby objects were not cleanly (explicitily) closed.
+
+Author: David Suárez <david.sephirot at gmail.com>
+Last-Update: 2014-03-12
+
+--- a/src/bdb.h
++++ b/src/bdb.h
+@@ -159,10 +159,21 @@ struct ary_st {
+     VALUE *ptr;
+ };
+ 
++typedef enum BDB_OBJ_TYPE {BDB_OBJ_UNKNOWN, BDB_OBJ_DB, /*BDB_OBJ_ENV, BDB_OBJ_LOG, */ BDB_OBJ_LOCK, BDB_OBJ_TX};
++
++struct bdb_objassoc {
++   VALUE obj;
++   void* obj_ptr;
++   enum BDB_OBJ_TYPE obj_type;
++};
++
++struct bdb_objassoc* create_assoc(VALUE obj, void* obj_ptr, enum BDB_OBJ_TYPE obj_type);
++
+ typedef struct  {
+     int options;
+     VALUE marshal;
+     struct ary_st db_ary;
++    struct ary_st db_objassoc_ary;
+     VALUE home;
+     DB_ENV *envp;
+ #if HAVE_DB_LOG_REGISTER_4 || HAVE_ST_DB_ENV_LG_INFO
+@@ -214,7 +225,9 @@ typedef struct {
+     int status, options;
+     VALUE marshal, mutex;
+     struct ary_st db_ary;
++    struct ary_st db_objassoc_ary;
+     struct ary_st db_assoc;
++    struct ary_st db_assoc_objassoc_ary;
+     VALUE env;
+     DB_TXN *txnid;
+     DB_TXN *parent;
+@@ -238,6 +251,7 @@ typedef struct {
+     VALUE marshal;
+     DBTYPE type;
+     VALUE env, orig, secondary, txn;
++    bdb_ENV* env_ptr;
+     VALUE filename, database;
+     VALUE bt_compare, bt_prefix, h_hash;
+ #if HAVE_CONST_DB_DUPSORT
+@@ -295,6 +309,7 @@ typedef struct {
+ typedef struct {
+     unsigned int lock;
+     VALUE env, self;
++    bdb_ENV *env_ptr;
+ } bdb_LOCKID;
+ 
+ typedef struct {
+@@ -573,6 +588,12 @@ extern VALUE bdb_ary_delete _((struct ar
+ extern void bdb_ary_mark _((struct ary_st *));
+ extern VALUE bdb_respond_to _((VALUE, ID));
+ 
++/* for internal close */
++extern VALUE bdb_internal_close(bdb_DB *dbst, bdb_ENV *envst);
++extern VALUE txn_free(bdb_TXN *txnst);
++extern VALUE bdb_ary_delete_assoc(struct ary_st *db_ary, VALUE val);
++extern void lockid_free( bdb_LOCKID *dblockid);
++
+ #if ! HAVE_ST_DBC_C_CLOSE && HAVE_ST_DBC_CLOSE
+ #define c_close close
+ #undef HAVE_ST_DBC_C_CLOSE
+--- a/src/common.c
++++ b/src/common.c
+@@ -149,6 +149,31 @@ bdb_ary_delete(struct ary_st *db_ary, VA
+     return Qfalse;
+ }
+ 
++VALUE
++bdb_ary_delete_assoc(struct ary_st *db_ary, VALUE val)
++{
++    int i, pos;
++
++    if (!db_ary->ptr || db_ary->mark) return Qfalse;
++
++    for (pos = 0; pos < db_ary->len; pos++) {
++
++       struct bdb_objassoc* assoc = db_ary->ptr[pos];
++
++       if (assoc->obj == val) {
++          for (i = pos + 1; i < db_ary->len; i++, pos++) {
++              db_ary->ptr[pos] = db_ary->ptr[i];
++          }
++
++          free(assoc);
++          db_ary->len = pos;
++          return Qtrue;
++       }
++    }
++
++    return Qfalse;
++}
++
+ void
+ bdb_ary_mark(struct ary_st *db_ary)
+ {
+@@ -929,8 +954,10 @@ bdb_i_close(bdb_DB *dbst, int flags)
+ 
+ 	    Data_Get_Struct(dbst->txn, bdb_TXN, txnst);
+ 	    opened = bdb_ary_delete(&txnst->db_ary, dbst->ori_val);
++        bdb_ary_delete_assoc(&txnst->db_objassoc_ary, dbst->ori_val);
+ 	    if (!opened) {
+ 		opened = bdb_ary_delete(&txnst->db_assoc, dbst->ori_val);
++        bdb_ary_delete_assoc(&txnst->db_assoc_objassoc_ary, dbst->ori_val);
+ 	    }
+ 	    if (opened) {
+ 		if (txnst->options & BDB_TXN_COMMIT) {
+@@ -948,6 +975,7 @@ bdb_i_close(bdb_DB *dbst, int flags)
+ 	    if (dbst->env && RBASIC(dbst->env)->flags) {
+ 		Data_Get_Struct(dbst->env, bdb_ENV, envst);
+ 		bdb_ary_delete(&envst->db_ary, dbst->ori_val);
++        bdb_ary_delete_assoc(&envst->db_objassoc_ary, dbst->ori_val);
+ 	    }
+ 	    if (!(dbst->options & BDB_NOT_OPEN)) {
+ 		dbst->dbp->close(dbst->dbp, flags);
+@@ -967,10 +995,29 @@ bdb_local_aref()
+     return obj;
+ }
+ 
++static void
++bdb_i_internal_close(bdb_DB *dbst, int flags, bdb_ENV *envst)
++{
++    //bdb_ENV *envst;
++
++   if (dbst->dbp) {
++       if (dbst->env && RBASIC(dbst->env)->flags) {
++       //Data_Get_Struct(dbst->env, bdb_ENV, envst);
++       bdb_ary_delete(&envst->db_ary, dbst->ori_val);
++       bdb_ary_delete_assoc(&envst->db_objassoc_ary, dbst->ori_val);
++       }
++       if (!(dbst->options & BDB_NOT_OPEN)) {
++       dbst->dbp->close(dbst->dbp, flags);
++       }
++   }
++   dbst->dbp = NULL;
++}
++
+ static VALUE
+ i_close(bdb_DB *dbst)
+ {
+-    bdb_i_close(dbst, 0);
++    //bdb_i_close(dbst, 0);
++    bdb_i_internal_close(dbst, 0, dbst->env_ptr);
+     return Qnil;
+ }
+ 
+@@ -1098,6 +1145,18 @@ bdb_close(int argc, VALUE *argv, VALUE o
+     return Qnil;
+ }
+ 
++VALUE
++bdb_internal_close(bdb_DB *dbst, bdb_ENV *envst)
++{
++    int flags = 0;
++
++    if (dbst->dbp != NULL) {
++        bdb_i_internal_close(dbst, flags, envst);
++    }
++
++    return Qnil;
++}
++
+ #if ! HAVE_ST_DB_BTREE_STAT_BT_NKEYS
+ 
+ static long
+@@ -1211,6 +1270,17 @@ bdb_recno_length(obj)
+     return hash;
+ }
+ 
++struct bdb_objassoc* create_assoc(VALUE obj, void* obj_ptr, enum BDB_OBJ_TYPE obj_type)
++{
++   struct bdb_objassoc *assoc = ALLOC(struct bdb_objassoc);
++
++   assoc->obj = obj;
++   assoc->obj_ptr = obj_ptr;
++   assoc->obj_type = obj_type;
++
++   return assoc;
++}
++
+ static VALUE
+ bdb_s_new(int argc, VALUE *argv, VALUE obj)
+ {
+@@ -1236,6 +1306,7 @@ bdb_s_new(int argc, VALUE *argv, VALUE o
+ 	    Data_Get_Struct(v, bdb_TXN, txnst);
+ 	    dbst->txn = v;
+ 	    dbst->env = txnst->env;
++        dbst->env_ptr = envst;
+ 	    Data_Get_Struct(txnst->env, bdb_ENV, envst);
+ 	    envp = envst->envp;
+ 	    dbst->options |= envst->options & BDB_NO_THREAD;
+@@ -1247,6 +1318,7 @@ bdb_s_new(int argc, VALUE *argv, VALUE o
+ 	    }
+ 	    Data_Get_Struct(v, bdb_ENV, envst);
+ 	    dbst->env = v;
++        dbst->env_ptr = envst;
+ 	    envp = envst->envp;
+ 	    dbst->options |= envst->options & BDB_NO_THREAD;
+ 	    dbst->marshal = envst->marshal;
+@@ -1292,9 +1364,11 @@ bdb_s_new(int argc, VALUE *argv, VALUE o
+     rb_obj_call_init(res, argc, argv);
+     if (txnst) {
+ 	bdb_ary_push(&txnst->db_ary, res);
++    bdb_ary_push(&txnst->db_objassoc_ary, (VALUE)create_assoc(res, dbst, BDB_OBJ_DB));
+     }
+     else if (envst) {
+ 	bdb_ary_push(&envst->db_ary, res);
++    bdb_ary_push(&envst->db_objassoc_ary, (VALUE)create_assoc(res, dbst, BDB_OBJ_DB));
+     }
+     return res;
+ }
+--- a/src/env.c
++++ b/src/env.c
+@@ -1080,6 +1080,11 @@ bdb_final(bdb_ENV *envst)
+         envst->db_ary.total = envst->db_ary.len = 0;
+         envst->db_ary.ptr = 0;
+         free(ary);
++
++        envst->db_objassoc_ary.mark = Qfalse;
++        envst->db_objassoc_ary.total = envst->db_objassoc_ary.len = 0;
++        free(envst->db_objassoc_ary.ptr);
++        envst->db_objassoc_ary.ptr = 0;
+     }
+     if (envst->envp) {
+ 	if (!(envst->options & BDB_ENV_NOT_OPEN)) {
+@@ -1112,7 +1117,75 @@ bdb_final(bdb_ENV *envst)
+ static void
+ bdb_env_free(bdb_ENV *envst)
+ {
+-    bdb_final(envst);
++    //bdb_final(envst);
++
++    VALUE *ary;
++    int i;
++
++    ary = envst->db_ary.ptr;
++    if (ary) {
++        envst->db_ary.mark = Qtrue;
++        envst->db_objassoc_ary.mark = Qtrue;
++        for (i = 0; i < envst->db_ary.len; i++) {
++            /*if (rb_respond_to(ary[i], rb_intern("close"))) {
++                bdb_protect_close(ary[i]);
++            }*/
++           //if(i < envst->db_ptr_ary.len)
++
++           struct bdb_objassoc* assoc = envst->db_objassoc_ary.ptr[i];
++
++           switch (assoc->obj_type) {
++              case BDB_OBJ_DB:
++                    bdb_internal_close(assoc->obj_ptr, envst);
++                    break;
++
++              case BDB_OBJ_TX:
++                  txn_free(assoc->obj_ptr);
++                  break;
++
++              case BDB_OBJ_LOCK:
++                  lockid_free(assoc->obj_ptr);
++                  break;
++           }
++
++        }
++        envst->db_ary.mark = Qfalse;
++        envst->db_ary.total = envst->db_ary.len = 0;
++        envst->db_ary.ptr = 0;
++        free(ary);
++
++        envst->db_objassoc_ary.mark = Qfalse;
++        envst->db_objassoc_ary.total = envst->db_objassoc_ary.len = 0;
++        free(envst->db_objassoc_ary.ptr);
++        envst->db_objassoc_ary.ptr = 0;
++    }
++    if (envst->envp) {
++    if (!(envst->options & BDB_ENV_NOT_OPEN)) {
++#if HAVE_ST_DB_ENV_CLOSE
++        envst->envp->close(envst->envp, 0);
++#else
++        db_appexit(envst->envp);
++        free(envst->envp);
++#endif
++    }
++    envst->envp = NULL;
++    }
++#if BDB_NEED_ENV_CURRENT
++    {
++    VALUE obj;
++    bdb_ENV *thst;
++    int status = 0;
++
++    obj = bdb_env_aref();
++    if (!status && !NIL_P(obj)) {
++        Data_Get_Struct(obj, bdb_ENV, thst);
++        if (thst == envst) {
++        rb_thread_local_aset(rb_thread_current(), bdb_id_current_env, Qnil);
++        }
++    }
++    }
++#endif
++
+     free(envst);
+ }
+ 
+--- a/src/lock.c
++++ b/src/lock.c
+@@ -12,21 +12,30 @@ bdb_clean_env(VALUE env, VALUE obj)
+     bdb_ENV *envst;
+     Data_Get_Struct(env, bdb_ENV, envst);
+     bdb_ary_delete(&envst->db_ary, obj);
++    bdb_ary_delete_assoc(&envst->db_objassoc_ary, obj);
+ }
+-    
+-static void 
++
++void
+ lockid_free( bdb_LOCKID *dblockid)
+ {
+ #if HAVE_ST_DB_ENV_LOCK_ID_FREE
+     bdb_ENV *envst;
+ 
+-    bdb_clean_env(dblockid->env, dblockid->self);
+-    Data_Get_Struct(dblockid->env, bdb_ENV, envst);
+-    if (envst->envp) {
+-	envst->envp->lock_id_free(envst->envp, dblockid->lock);
++    if (dblockid->env_ptr != NULL) {
++      envst = dblockid->env_ptr;
++
++      //bdb_clean_env(dblockid->env, dblockid->self);
++      bdb_ary_delete(&envst->db_ary, dblockid->self);
++      bdb_ary_delete_assoc(&envst->db_objassoc_ary, dblockid->self);
++
++      //Data_Get_Struct(dblockid->env, bdb_ENV, envst);
++      if (envst->envp) {
++      envst->envp->lock_id_free(envst->envp, dblockid->lock);
++      }
++  #endif
++      free(dblockid);
++      dblockid->env_ptr = NULL;
+     }
+-#endif
+-    free(dblockid);
+ }
+ 
+ static VALUE
+@@ -52,8 +61,10 @@ bdb_env_lockid(VALUE obj)
+     dblockid->lock = idp;
+     dblockid->env = obj;
+     dblockid->self = a;
++    dblockid->env_ptr = envst;
+ #if HAVE_ST_DB_ENV_LOCK_ID
+     bdb_ary_push(&envst->db_ary, a);
++    bdb_ary_push(&envst->db_objassoc_ary, (VALUE)create_assoc(a, dblockid, BDB_OBJ_LOCK));
+ #endif
+     return a;
+ }
+--- a/src/log.c
++++ b/src/log.c
+@@ -387,6 +387,7 @@ bdb_log_cursor(VALUE lsn)
+ 	GetEnvDB(lsnst->env, envst);
+ 	bdb_test_error(envst->envp->log_cursor(envst->envp, &lsnst->cursor, 0));
+ 	bdb_ary_push(&envst->db_ary, lsn);
++    //bdb_ary_push(&envst->db_objassoc_ary, (VALUE)create_assoc(lsn, lsnst, BDB_OBJ_LOG));
+     }
+     return lsn;
+ }
+--- a/src/transaction.c
++++ b/src/transaction.c
+@@ -50,7 +50,68 @@ clean_ary(bdb_TXN *txnst, VALUE result)
+     }
+ }
+ 
+-static VALUE 
++static VALUE
++bdb__txn__internal_close(VALUE obj, VALUE commit, VALUE real)
++{
++    bdb_DB *dbst, *dbst1;
++
++    if (!real) {
++   Data_Get_Struct(obj, bdb_DB, dbst);
++   dbst->dbp = NULL;
++    }
++    else {
++   if (commit) {
++       Data_Get_Struct(obj, bdb_DB, dbst);
++       if (dbst->orig) {
++       Data_Get_Struct(dbst->orig, bdb_DB, dbst1);
++       dbst1->len = dbst->len;
++       }
++   }
++// bdb_close(0, 0, obj);
++    }
++    return Qnil;
++}
++
++static void
++clean_ary_internal(bdb_TXN *txnst, VALUE result)
++{
++    VALUE *ary, tmp[3];
++    int i, len;
++
++    tmp[0] = Qnil;
++    tmp[1] = result;
++    tmp[2] = Qtrue;
++    if (txnst->db_ary.ptr) {
++        txnst->db_ary.mark = Qtrue;
++   ary = txnst->db_ary.ptr;
++   len = txnst->db_ary.len;
++
++   for (i = 0; i < len; i++) {
++            tmp[0] = ary[i];
++            bdb__txn__internal_close(txnst->db_objassoc_ary.ptr[i], result, Qtrue); //txn_close_i(tmp);
++   }
++   txnst->db_ary.mark = Qfalse;
++   txnst->db_ary.ptr = 0;
++   txnst->db_ary.total = txnst->db_ary.len = 0;
++   free(ary);
++    }
++    tmp[2] = Qfalse;
++    if (txnst->db_assoc.ptr) {
++        txnst->db_assoc.mark = Qtrue;
++   ary = txnst->db_assoc.ptr;
++   len = txnst->db_assoc.len;
++   for (i = 0; i < len; i++) {
++            tmp[0] = ary[i];
++            bdb__txn__internal_close(txnst->db_objassoc_ary.ptr[i], result, Qtrue); //txn_close_i(tmp);
++   }
++   txnst->db_assoc.mark = Qfalse;
++   txnst->db_assoc.ptr = 0;
++   txnst->db_assoc.total = txnst->db_assoc.len = 0;
++   free(ary);
++   }
++}
++
++VALUE
+ txn_free(bdb_TXN *txnst)
+ {
+     if (txnst->txnid && txnst->parent == NULL) {
+@@ -72,7 +133,7 @@ txn_free(bdb_TXN *txnst)
+     if (txnst->txn_cxx) 
+         free(txnst->txn_cxx);
+ #endif
+-    clean_ary(txnst, Qfalse);
++    clean_ary_internal(txnst, Qfalse);
+     return Qnil;
+ }
+ 
+@@ -107,6 +168,7 @@ bdb_txn_assoc(int argc, VALUE *argv, VAL
+     for (i = 0; i < argc; i++) {
+ 	a = rb_funcall(argv[i], rb_intern("__txn_dup__"), 1, obj);
+ 	bdb_ary_push(&txnst->db_assoc, a);
++    bdb_ary_push(&txnst->db_assoc_objassoc_ary, (VALUE)create_assoc(a, txnst, BDB_OBJ_TX));
+         rb_ary_push(ary, a);
+     }
+     switch (RARRAY_LEN(ary)) {
+@@ -386,6 +448,7 @@ bdb_env_rslbl_begin(VALUE origin, int ar
+     txnst->options = envst->options & BDB_INIT_LOCK;
+     txnst->mutex = opt.mutex;
+     bdb_ary_unshift(&envst->db_ary, txnv);
++    bdb_ary_unshift(&envst->db_objassoc_ary, (VALUE)create_assoc(txnv, txnst, BDB_OBJ_TX));
+     if (commit) {
+ 	txnst->options |= BDB_TXN_COMMIT;
+     }
diff --git a/debian/patches/series b/debian/patches/series
index fc8ecf4..238cc81 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -6,3 +6,4 @@ add-support-for-libdb_version_5_and_higher.patch
 remove_constants_safely
 fix-inheritance
 remove-src-dir-from-tests-load-path
+dont-rely-on-ruby-objects-to-accommodate-c-data

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-bdb.git



More information about the Pkg-ruby-extras-commits mailing list