ruby-changes:38263
From: nobu <ko1@a...>
Date: Sun, 19 Apr 2015 10:43:21 +0900 (JST)
Subject: [ruby-changes:38263] nobu:r50344 (trunk): hash.c: check env vars encoding
nobu 2015-04-19 10:42:57 +0900 (Sun, 19 Apr 2015) New Revision: 50344 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50344 Log: hash.c: check env vars encoding * hash.c (get_env_cstr): environment variables must be ASCII compatible, as dummy encodings and wide char encodings are unsupproted now. Modified files: trunk/ChangeLog trunk/hash.c trunk/test/ruby/test_env.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 50343) +++ ChangeLog (revision 50344) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Apr 19 10:42:54 2015 Nobuyoshi Nakada <nobu@r...> + + * hash.c (get_env_cstr): environment variables must be ASCII + compatible, as dummy encodings and wide char encodings are + unsupproted now. + Sat Apr 18 15:18:56 2015 Nobuyoshi Nakada <nobu@r...> * ext/json/parser/parser.rl: raise with messages in UTF-8 Index: hash.c =================================================================== --- hash.c (revision 50343) +++ hash.c (revision 50344) @@ -2699,9 +2699,24 @@ env_str_new2(const char *ptr) https://github.com/ruby/ruby/blob/trunk/hash.c#L2699 return env_str_new(ptr, strlen(ptr)); } +static void * +get_env_cstr(VALUE str, const char *name) +{ + char *var; + rb_encoding *enc = rb_enc_get(str); + if (!rb_enc_asciicompat(enc)) { + rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s", + name, rb_enc_name(enc)); + } + var = RSTRING_PTR(str); + if (memchr(var, '\0', RSTRING_LEN(str))) { + rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name); + } + return var; +} + #define get_env_ptr(var, val) \ - (memchr((var = RSTRING_PTR(val)), '\0', RSTRING_LEN(val)) ? \ - rb_raise(rb_eArgError, "bad environment variable " #var) : (void)0) + (var = get_env_cstr(val, #var)) static inline const char * env_name(volatile VALUE *s) Index: test/ruby/test_env.rb =================================================================== --- test/ruby/test_env.rb (revision 50343) +++ test/ruby/test_env.rb (revision 50344) @@ -3,6 +3,23 @@ require 'test/unit' https://github.com/ruby/ruby/blob/trunk/test/ruby/test_env.rb#L3 class TestEnv < Test::Unit::TestCase IGNORE_CASE = /bccwin|mswin|mingw/ =~ RUBY_PLATFORM PATH_ENV = "PATH" + INVALID_ENVVARS = [ + "foo\0bar", + "\xa1\xa1".force_encoding(Encoding::UTF_16LE), + "foo".force_encoding(Encoding::ISO_2022_JP), + ] + + def assert_invalid_env(msg = nil) + failed = {} + INVALID_ENVVARS.select do |v| + begin + assert_raise(ArgumentError) {yield v} + rescue MiniTest::Assertion => e + failed[v] = e + end + end + assert(failed.empty?, message(msg) {mu_pp(failed)}) + end def setup @verbose = $VERBOSE @@ -87,13 +104,13 @@ class TestEnv < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_env.rb#L104 end def test_delete - assert_raise(ArgumentError) { ENV.delete("foo\0bar") } + assert_invalid_env {|v| ENV.delete(v)} assert_nil(ENV.delete("TEST")) assert_nothing_raised { ENV.delete(PATH_ENV) } end def test_getenv - assert_raise(ArgumentError) { ENV["foo\0bar"] } + assert_invalid_env {|v| ENV[v]} ENV[PATH_ENV] = "" assert_equal("", ENV[PATH_ENV]) assert_nil(ENV[""]) @@ -110,7 +127,7 @@ class TestEnv < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_env.rb#L127 assert_equal("foo", ENV.fetch("test", "foo")) assert_equal("bar", ENV.fetch("test") { "bar" }) assert_equal("bar", ENV.fetch("test", "foo") { "bar" }) - assert_raise(ArgumentError) { ENV.fetch("foo\0bar") } + assert_invalid_env {|v| ENV.fetch(v)} assert_nothing_raised { ENV.fetch(PATH_ENV, "foo") } ENV[PATH_ENV] = "" assert_equal("", ENV.fetch(PATH_ENV)) @@ -119,8 +136,8 @@ class TestEnv < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_env.rb#L136 def test_aset assert_nothing_raised { ENV["test"] = nil } assert_equal(nil, ENV["test"]) - assert_raise(ArgumentError) { ENV["foo\0bar"] = "test" } - assert_raise(ArgumentError) { ENV["test"] = "foo\0bar" } + assert_invalid_env {|v| ENV[v] = "test"} + assert_invalid_env {|v| ENV["test"] = v} begin # setenv(3) allowed the name includes '=', @@ -276,7 +293,7 @@ class TestEnv < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_env.rb#L293 assert_not_send([ENV, :has_key?, "test"]) ENV["test"] = "foo" assert_send([ENV, :has_key?, "test"]) - assert_raise(ArgumentError) { ENV.has_key?("foo\0bar") } + assert_invalid_env {|v| ENV.has_key?(v)} end def test_assoc @@ -290,7 +307,7 @@ class TestEnv < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_env.rb#L307 assert_equal("test", k) assert_equal("foo", v) end - assert_raise(ArgumentError) { ENV.assoc("foo\0bar") } + assert_invalid_env {|v| ENV.assoc(v)} end def test_has_value2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/