diff --git a/ChangeLog b/ChangeLog
index f161abcec3..4c3c349728 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sat Feb 16 13:16:49 2008  Tanaka Akira  <akr@fsij.org>
+
+	* string.c (rb_str_sub_bang): stringize replacing hash values.
+	  (str_gsub): ditto.
+
 Sat Feb 16 13:01:33 2008  NARUSE, Yui  <naruse@ruby-lang.org>
 
 	* string.c (rb_enc_strlen): add search_nonascii like character
diff --git a/string.c b/string.c
index d59a5d1993..4fcdd52cbf 100644
--- a/string.c
+++ b/string.c
@@ -2902,17 +2902,20 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
 	match = rb_backref_get();
 	regs = RMATCH(match)->regs;
 
-	if (iter) {
+	if (iter || !NIL_P(hash)) {
 	    char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str);
 
-	    rb_match_busy(match);
-	    repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+            if (iter) {
+                rb_match_busy(match);
+                repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+            }
+            else {
+                repl = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0)));
+                repl = rb_obj_as_string(repl);
+            }
 	    str_mod_check(str, p, len);
 	    str_frozen_check(str);
-	    rb_backref_set(match);
-	}
-	else if (!NIL_P(hash)) {
-	    repl = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0)));
+	    if (iter) rb_backref_set(match);
 	}
 	else {
 	    repl = rb_reg_regsub(repl, str, regs, pat);
@@ -3045,18 +3048,21 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
 	n++;
 	match = rb_backref_get();
 	regs = RMATCH(match)->regs;
-	if (iter) {
-	    rb_match_busy(match);
-	    val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+	if (iter || !NIL_P(hash)) {
+            if (iter) {
+                rb_match_busy(match);
+                val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+            }
+            else {
+                val = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0)));
+                val = rb_obj_as_string(val);
+            }
 	    str_mod_check(str, sp, slen);
 	    if (bang) str_frozen_check(str);
 	    if (val == dest) { 	/* paranoid check [ruby-dev:24827] */
 		rb_raise(rb_eRuntimeError, "block should not cheat");
 	    }
-	    rb_backref_set(match);
-	}
-	else if (!NIL_P(hash)) {
-	    val = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0)));
+	    if (iter) rb_backref_set(match);
 	}
 	else {
 	    val = rb_reg_regsub(repl, str, regs, pat);