From fb6d4fba95782afb8fdfd736c7a4360c66dd2353 Mon Sep 17 00:00:00 2001 From: "mahlon@martini.nu" Date: Tue, 13 Jul 2021 23:58:16 +0000 Subject: [PATCH] Bugfix: Don't use a ruby string outside of the stack, GC can snag out from under us. (Thanks Michael!) FossilOrigin-Name: bbcafda1bc42bf6deb5ac30acf620b0a3e020154e7d82f0140d2118ca29961fb --- .pryrc | 1 - ext/mdbx_ext/database.c | 17 ++++++++--------- spec/mdbx/database_spec.rb | 10 ---------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/.pryrc b/.pryrc index 8765b2e..7086754 100644 --- a/.pryrc +++ b/.pryrc @@ -12,5 +12,4 @@ rescue Exception => e end db = MDBX::Database.open( 'tmp/testdb', max_collections: 50 ) -#db = MDBX::Database.open( 'tmp/testdb', duplicate_keys: true ) diff --git a/ext/mdbx_ext/database.c b/ext/mdbx_ext/database.c index 32f09f6..1ebf17b 100644 --- a/ext/mdbx_ext/database.c +++ b/ext/mdbx_ext/database.c @@ -439,7 +439,14 @@ rmdbx_set_subdb( VALUE self, VALUE name ) if ( db->txn ) rb_raise( rmdbx_eDatabaseError, "Unable to change collection: transaction open" ); - db->subdb = NIL_P( name ) ? NULL : StringValueCStr( name ); + xfree( db->subdb ); + db->subdb = NULL; + + if ( ! NIL_P(name) ) { + size_t len = RSTRING_LEN( name ) + 1; + db->subdb = malloc( len ); + strlcpy( db->subdb, StringValuePtr(name), len ); + } /* Reset the db handle and issue a single transaction to reify the collection. @@ -786,8 +793,6 @@ rmdbx_database_initialize( int argc, VALUE *argv, VALUE self ) db->settings.db_flags = db->settings.db_flags | MDBX_DB_ACCEDE; db->settings.env_flags = db->settings.env_flags | MDBX_ACCEDE; } - /* opt = rb_hash_delete( opts, ID2SYM( rb_intern("duplicate_keys") ) ); */ - /* if ( RTEST(opt) ) db->settings.db_flags = db->settings.db_flags | MDBX_DUPSORT; */ opt = rb_hash_delete( opts, ID2SYM( rb_intern("exclusive") ) ); if ( RTEST(opt) ) db->settings.env_flags = db->settings.env_flags | MDBX_EXCLUSIVE; opt = rb_hash_delete( opts, ID2SYM( rb_intern("lifo_reclaim") ) ); @@ -815,12 +820,6 @@ rmdbx_database_initialize( int argc, VALUE *argv, VALUE self ) opt = rb_hash_delete( opts, ID2SYM( rb_intern("writemap") ) ); if ( RTEST(opt) ) db->settings.env_flags = db->settings.env_flags | MDBX_WRITEMAP; - /* Bail early on incompatible options. FIXME: I don't think this is true. */ - /* if ( db->settings.max_collections > 0 && */ - /* rmdbx_flag_enabled( db->settings.db_flags, MDBX_DUPSORT ) ) { */ - /* rb_raise( rb_eArgError, "Collections and multiple values per key are mutually exclusive options." ); */ - /* } */ - if ( rb_hash_size_num(opts) > 0 ) { rb_raise( rb_eArgError, "Unknown option(s): %"PRIsVALUE, opts ); } diff --git a/spec/mdbx/database_spec.rb b/spec/mdbx/database_spec.rb index d82ce20..e10fe0e 100644 --- a/spec/mdbx/database_spec.rb +++ b/spec/mdbx/database_spec.rb @@ -173,16 +173,6 @@ RSpec.describe( MDBX::Database ) do end - # context 'duplicate keys' do - # - # let( :db ) { described_class.open( TEST_DATABASE.to_s, max_collections: 5, duplicate_keys: true ) } - # - # after( :each ) do - # db.close - # end - # end - - context 'collections' do let!( :db ) { described_class.open( TEST_DATABASE.to_s, max_collections: 5 ) }