diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index 1fdbaa0aca..03616fd4d8 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -259,8 +259,11 @@ fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) value = dbm_fetch(dbm, key); if (value.dptr == 0) { not_found: - if (ifnone == Qnil && rb_block_given_p()) - return rb_yield(rb_tainted_str_new(key.dptr, key.dsize)); + if (NIL_P(ifnone) && rb_block_given_p()) { + keystr = rb_str_dup(keystr); + OBJ_TAINT(keystr); + return rb_yield(keystr); + } return ifnone; } return rb_tainted_str_new(value.dptr, value.dsize); diff --git a/test/dbm/test_dbm.rb b/test/dbm/test_dbm.rb index 9f7604be15..083a5c25ba 100644 --- a/test/dbm/test_dbm.rb +++ b/test/dbm/test_dbm.rb @@ -58,6 +58,14 @@ if defined? DBM assert_nil(@dbm_rdonly.delete("bar")) end end + + def test_fetch_not_found + notfound = nil + result = Object.new + assert_same(result, @dbm_rdonly.fetch("bar") {|k| notfound = k; result}) + assert_equal("bar", notfound) + assert_predicate(notfound, :tainted?) + end end class TestDBM < Test::Unit::TestCase