1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Remove support for nil::Constant

This was an intentional bug added in 1.9.

The approach taken here is to add a second operand to the
getconstant instruction for whether nil should be allowed and
treated as current scope.

Fixes [Bug #11718]
This commit is contained in:
Jeremy Evans 2019-08-13 22:44:36 -07:00
parent 7d32cb7631
commit fbcd065294
4 changed files with 19 additions and 13 deletions

View file

@ -4404,18 +4404,18 @@ compile_const_prefix(rb_iseq_t *iseq, const NODE *const node,
switch (nd_type(node)) { switch (nd_type(node)) {
case NODE_CONST: case NODE_CONST:
debugi("compile_const_prefix - colon", node->nd_vid); debugi("compile_const_prefix - colon", node->nd_vid);
ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid)); ADD_INSN2(body, nd_line(node), getconstant, ID2SYM(node->nd_vid), 1);
break; break;
case NODE_COLON3: case NODE_COLON3:
debugi("compile_const_prefix - colon3", node->nd_mid); debugi("compile_const_prefix - colon3", node->nd_mid);
ADD_INSN(body, nd_line(node), pop); ADD_INSN(body, nd_line(node), pop);
ADD_INSN1(body, nd_line(node), putobject, rb_cObject); ADD_INSN1(body, nd_line(node), putobject, rb_cObject);
ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); ADD_INSN2(body, nd_line(node), getconstant, ID2SYM(node->nd_mid), 1);
break; break;
case NODE_COLON2: case NODE_COLON2:
CHECK(compile_const_prefix(iseq, node->nd_head, pref, body)); CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
debugi("compile_const_prefix - colon2", node->nd_mid); debugi("compile_const_prefix - colon2", node->nd_mid);
ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); ADD_INSN2(body, nd_line(node), getconstant, ID2SYM(node->nd_mid), 0);
break; break;
default: default:
CHECK(COMPILE(pref, "const colon2 prefix", node)); CHECK(COMPILE(pref, "const colon2 prefix", node));
@ -7154,7 +7154,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
ADD_INSNL(ret, line, branchunless, lassign); /* cref */ ADD_INSNL(ret, line, branchunless, lassign); /* cref */
} }
ADD_INSN(ret, line, dup); /* cref cref */ ADD_INSN(ret, line, dup); /* cref cref */
ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */ ADD_INSN2(ret, line, getconstant, ID2SYM(mid), 1); /* cref obj */
if (node->nd_aid == idOROP || node->nd_aid == idANDOP) { if (node->nd_aid == idOROP || node->nd_aid == idANDOP) {
lfin = NEW_LABEL(line); lfin = NEW_LABEL(line);
@ -7500,13 +7500,13 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
int ic_index = body->is_size++; int ic_index = body->is_size++;
ADD_INSN2(ret, line, opt_getinlinecache, lend, INT2FIX(ic_index)); ADD_INSN2(ret, line, opt_getinlinecache, lend, INT2FIX(ic_index));
ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); ADD_INSN2(ret, line, getconstant, ID2SYM(node->nd_vid), 1);
ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index)); ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index));
ADD_LABEL(ret, lend); ADD_LABEL(ret, lend);
} }
else { else {
ADD_INSN(ret, line, putnil); ADD_INSN(ret, line, putnil);
ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); ADD_INSN2(ret, line, getconstant, ID2SYM(node->nd_vid), 1);
} }
if (popped) { if (popped) {
@ -7893,7 +7893,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
} }
ADD_INSN1(ret, line, putobject, rb_cObject); ADD_INSN1(ret, line, putobject, rb_cObject);
ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid)); ADD_INSN2(ret, line, getconstant, ID2SYM(node->nd_mid), 1);
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index)); ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index));

View file

@ -252,19 +252,19 @@ setclassvariable
rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id, val); rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id, val);
} }
/* Get constant variable id. If klass is Qnil, constants /* Get constant variable id. If klass is Qnil and allow_nil is true, constants
are searched in the current scope. Otherwise, get constant under klass are searched in the current scope. Otherwise, get constant under klass
class or module. class or module.
*/ */
DEFINE_INSN DEFINE_INSN
getconstant getconstant
(ID id) (ID id, VALUE allow_nil)
(VALUE klass) (VALUE klass)
(VALUE val) (VALUE val)
/* getconstant can kick autoload */ /* getconstant can kick autoload */
// attr bool leaf = false; /* has rb_autoload_load() */ // attr bool leaf = false; /* has rb_autoload_load() */
{ {
val = vm_get_ev_const(ec, klass, id, 0); val = vm_get_ev_const(ec, klass, id, allow_nil, 0);
} }
/* Set constant variable id under cbase class or module. /* Set constant variable id under cbase class or module.

View file

@ -48,6 +48,12 @@ class TestConst < Test::Unit::TestCase
assert_equal 8, TEST4 assert_equal 8, TEST4
end end
def test_const_access_from_nil
assert_raise(TypeError) { eval("nil::Object") }
assert_raise(TypeError) { eval("c = nil; c::Object") }
assert_raise(TypeError) { eval("sc = Class.new; sc::C = nil; sc::C::Object") }
end
def test_redefinition def test_redefinition
c = Class.new c = Class.new
name = "X\u{5b9a 6570}" name = "X\u{5b9a 6570}"

View file

@ -890,12 +890,12 @@ vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
} }
static inline VALUE static inline VALUE
vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, int is_defined) vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, int allow_nil, int is_defined)
{ {
void rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id); void rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id);
VALUE val; VALUE val;
if (orig_klass == Qnil) { if (orig_klass == Qnil && allow_nil) {
/* in current lexical scope */ /* in current lexical scope */
const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep); const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
const rb_cref_t *cref; const rb_cref_t *cref;
@ -3146,7 +3146,7 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_
} }
case DEFINED_CONST: case DEFINED_CONST:
klass = v; klass = v;
if (vm_get_ev_const(ec, klass, SYM2ID(obj), 1)) { if (vm_get_ev_const(ec, klass, SYM2ID(obj), 1, 1)) {
expr_type = DEFINED_CONST; expr_type = DEFINED_CONST;
} }
break; break;