summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-09-02 15:08:53 +0900
committerGitHub <noreply@github.com>2019-09-02 15:08:53 +0900
commit6f206b8ec6f945804c56cf8249739c6e94ed65f6 (patch)
tree8e04d964baa3cd07239dcaeb35ed41d113c55c39
parent633ae3278ecce7c2b98fa1aa6106f963894c538a (diff)
Prohibit nul-separated glob pattern [Feature #14643] (#2419)
Notes
Notes: Merged-By: nobu <nobu@ruby-lang.org>
-rw-r--r--NEWS7
-rw-r--r--dir.c31
-rw-r--r--spec/ruby/core/dir/shared/glob.rb8
-rw-r--r--test/ruby/test_dir.rb5
4 files changed, 23 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index 2857cc9e4c..710039417a 100644
--- a/NEWS
+++ b/NEWS
@@ -79,6 +79,13 @@ Complex::
* Added Complex#<=>. So 0 <=> 0i will not raise NoMethodError. [Bug #15857]
+Dir::
+
+ Modified method::
+
+ * Dir#glob and Dir#[] no longer allow NUL-separated glob pattern.
+ Use Array instead. [Feature #14643]
+
Encoding::
* Added new encoding CESU-8 [Feature #15931]
diff --git a/dir.c b/dir.c
index bfd085e16c..f5cc42d99f 100644
--- a/dir.c
+++ b/dir.c
@@ -2694,41 +2694,24 @@ push_glob(VALUE ary, VALUE str, VALUE base, int flags)
static VALUE
rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */
{
- long offset = 0;
- long len;
VALUE ary;
- int warned = FALSE;
+ int status;
/* can contain null bytes as separators */
- if (!RB_TYPE_P((str), T_STRING)) {
+ if (!RB_TYPE_P(str, T_STRING)) {
FilePathValue(str);
}
+ else if (!rb_str_to_cstr(str)) {
+ rb_raise(rb_eArgError, "nul-separated glob pattern is deprecated");
+ }
else {
rb_check_safe_obj(str);
rb_enc_check(str, rb_enc_from_encoding(rb_usascii_encoding()));
}
ary = rb_ary_new();
- while (offset < (len = RSTRING_LEN(str))) {
- int status;
- long rest = len - offset;
- const char *pbeg = RSTRING_PTR(str), *p = pbeg + offset;
- const char *pend = memchr(p, '\0', rest);
- if (pend) {
- if (!warned) {
- rb_warn("use glob patterns list instead of nul-separated patterns");
- warned = TRUE;
- }
- rest = ++pend - p;
- offset = pend - pbeg;
- }
- else {
- offset = len;
- }
- status = push_glob(ary, rb_str_subseq(str, p-pbeg, rest),
- base, flags);
- if (status) GLOB_JUMP_TAG(status);
- }
+ status = push_glob(ary, str, base, flags);
+ if (status) GLOB_JUMP_TAG(status);
return ary;
}
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index e4ffb51286..62675145df 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -30,7 +30,7 @@ describe :dir_glob, shared: true do
end
end
- ruby_version_is "2.6" do
+ ruby_version_is "2.6"..."2.7" do
it "splits the string on \\0 if there is only one string given and warns" do
-> {
Dir.send(@method, "file_o*\0file_t*").should ==
@@ -39,6 +39,12 @@ describe :dir_glob, shared: true do
end
end
+ ruby_version_is "2.7" do
+ it "raises an ArgumentError if the string contains \\0" do
+ -> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error ArgumentError, /nul-separated/
+ end
+ end
+
it "matches non-dotfiles with '*'" do
expected = %w[
brace
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index 93ae3c3ed9..75cae71093 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -138,9 +138,8 @@ class TestDir < Test::Unit::TestCase
Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH).sort)
assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }.sort,
Dir.glob([@root, File.join(@root, "*")]).sort)
- assert_warning(/nul-separated patterns/) do
- assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }.sort,
- Dir.glob(@root + "\0\0\0" + File.join(@root, "*")).sort)
+ assert_raise_with_message(ArgumentError, /nul-separated/) do
+ Dir.glob(@root + "\0\0\0" + File.join(@root, "*"))
end
assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") }.sort,