Ensure the name given to Module#set_temporary_name is not a valid constant path

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
This commit is contained in:
Benoit Daloze 2023-07-06 13:25:21 +02:00
Родитель e76022f41c
Коммит 9ee1877e4a
3 изменённых файлов: 53 добавлений и 4 удалений

Просмотреть файл

@ -17548,6 +17548,7 @@ variable.$(OBJEXT): {$(VPATH)}rubyparser.h
variable.$(OBJEXT): {$(VPATH)}shape.h
variable.$(OBJEXT): {$(VPATH)}st.h
variable.$(OBJEXT): {$(VPATH)}subst.h
variable.$(OBJEXT): {$(VPATH)}symbol.h
variable.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
variable.$(OBJEXT): {$(VPATH)}thread_native.h
variable.$(OBJEXT): {$(VPATH)}transient_heap.h

Просмотреть файл

@ -1,5 +1,4 @@
require_relative '../../spec_helper'
require_relative 'fixtures/module'
ruby_version_is "3.3" do
describe "Module#set_temporary_name" do
@ -14,6 +13,15 @@ ruby_version_is "3.3" do
m.name.should be_nil
end
it "can assign a temporary name which is not a valid constant path" do
m = Module.new
m.set_temporary_name("a::B")
m.name.should == "a::B"
m.set_temporary_name("Template['foo.rb']")
m.name.should == "Template['foo.rb']"
end
it "can't assign empty string as name" do
m = Module.new
-> { m.set_temporary_name("") }.should raise_error(ArgumentError, "empty class/module name")
@ -21,7 +29,14 @@ ruby_version_is "3.3" do
it "can't assign a constant name as a temporary name" do
m = Module.new
-> { m.set_temporary_name("Object") }.should raise_error(ArgumentError, "name must not be valid constant name")
-> { m.set_temporary_name("Object") }.should raise_error(ArgumentError, "name must not be valid constant path")
end
it "can't assign a constant path as a temporary name" do
m = Module.new
-> { m.set_temporary_name("A::B") }.should raise_error(ArgumentError, "name must not be valid constant path")
-> { m.set_temporary_name("::A") }.should raise_error(ArgumentError, "name must not be valid constant path")
-> { m.set_temporary_name("::A::B") }.should raise_error(ArgumentError, "name must not be valid constant path")
end
it "can't assign name to permanent module" do

Просмотреть файл

@ -35,6 +35,7 @@
#include "ruby/util.h"
#include "transient_heap.h"
#include "shape.h"
#include "symbol.h"
#include "variable.h"
#include "vm_core.h"
#include "ractor_core.h"
@ -134,6 +135,38 @@ rb_mod_name(VALUE mod)
return classname(mod, &permanent);
}
// Similar to logic in rb_mod_const_get()
static bool
is_constant_path(VALUE name)
{
const char *path = RSTRING_PTR(name);
const char *pend = RSTRING_END(name);
rb_encoding *enc = rb_enc_get(name);
const char *p = path;
if (p >= pend || !*p) {
return false;
}
while (p < pend) {
if (p + 2 <= pend && p[0] == ':' && p[1] == ':') {
p += 2;
}
const char *pbeg = p;
while (p < pend && *p != ':') p++;
if (pbeg == p) return false;
if (rb_enc_symname_type(pbeg, p - pbeg, enc, 0) != ID_CONST) {
return false;
}
}
return true;
}
/*
* call-seq:
* mod.set_temporary_name(string) -> self
@ -196,8 +229,8 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
rb_raise(rb_eArgError, "empty class/module name");
}
if (rb_is_const_name(name)) {
rb_raise(rb_eArgError, "name must not be valid constant name");
if (is_constant_path(name)) {
rb_raise(rb_eArgError, "name must not be valid constant path");
}
// Set the temporary classpath to the given name: