Skip to content

Commit

Permalink
sprintf.c: nil value is valid
Browse files Browse the repository at this point in the history
* sprintf.c (rb_str_format): look up the key, then get default
  value and raise KeyError if the returned value is nil.
  [ruby-dev:49338] [Ruby trunk - Bug ruby#11677]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52537 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
nobu committed Nov 11, 2015
1 parent 9cf1136 commit 56e3b49
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Wed Nov 11 18:30:28 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>

* sprintf.c (rb_str_format): look up the key, then get default
value and raise KeyError if the returned value is nil.
[ruby-dev:49338] [Ruby trunk - Bug #11677]

Wed Nov 11 17:38:24 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>

* vm_eval.c (local_var_list_add): skip internal local variable
Expand Down
8 changes: 4 additions & 4 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,8 @@ rb_hash_rehash(VALUE hash)
return hash;
}

static VALUE
hash_default_value(VALUE hash, VALUE key)
VALUE
rb_hash_default_value(VALUE hash, VALUE key)
{
if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) {
VALUE ifnone = RHASH_IFNONE(hash);
Expand Down Expand Up @@ -792,7 +792,7 @@ rb_hash_aref(VALUE hash, VALUE key)
st_data_t val;

if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
return hash_default_value(hash, key);
return rb_hash_default_value(hash, key);
}
return (VALUE)val;
}
Expand Down Expand Up @@ -1184,7 +1184,7 @@ rb_hash_shift(VALUE hash)
}
}
}
return hash_default_value(hash, Qnil);
return rb_hash_default_value(hash, Qnil);
}

static int
Expand Down
1 change: 1 addition & 0 deletions internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ void rb_gc_resurrect(VALUE ptr);
/* hash.c */
struct st_table *rb_hash_tbl_raw(VALUE hash);
VALUE rb_hash_has_key(VALUE hash, VALUE key);
VALUE rb_hash_default_value(VALUE hash, VALUE key);
VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc);
long rb_objid_hash(st_index_t index);
st_table *rb_init_identtable(void);
Expand Down
20 changes: 14 additions & 6 deletions sprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,12 +605,20 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
}
CHECKNAMEARG(start, len, enc);
get_hash(&hash, argc, argv);
sym = rb_cstr_intern(start + 1,
len - 2 /* without parenthesis */,
enc);
nextvalue = rb_hash_aref(hash, sym);
if (NIL_P(nextvalue) && !FL_TEST(hash, HASH_PROC_DEFAULT)) {
rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start);
sym = rb_check_symbol_cstr(start + 1,
len - 2 /* without parenthesis */,
enc);
if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
if (nextvalue == Qundef) {
if (NIL_P(sym)) {
sym = rb_cstr_intern(start + 1,
len - 2 /* without parenthesis */,
enc);
}
nextvalue = rb_hash_default_value(hash, sym);
if (NIL_P(nextvalue)) {
rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start);
}
}
if (term == '}') goto format_s;
p++;
Expand Down
5 changes: 5 additions & 0 deletions test/ruby/test_sprintf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,9 @@ def test_named_default
assert_equal("hello world", "hello %{location}" % h)
assert_equal("hello world", "hello %<location>s" % h)
end

def test_named_with_nil
h = { key: nil, key2: "key2_val" }
assert_equal("key is , key2 is key2_val", "key is %{key}, key2 is %{key2}" % h)
end
end

0 comments on commit 56e3b49

Please sign in to comment.