[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