1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/tool/ruby_vm/views/_leaf_helpers.erb
Dylan Thacker-Smith ac112f2b5d Avoid top-level search for nested constant reference from nil in defined?
Fixes [Bug #16332]

Constant access was changed to no longer allow top-level constant access
through `nil`, but `defined?` wasn't changed at the same time to stay
consistent.

Use a separate defined type to distinguish between a constant
referenced from the current lexical scope and one referenced from
another namespace.
2019-11-13 15:36:58 +09:00

108 lines
2.8 KiB
Text

%# -*- C -*-
%# Copyright (c) 2018 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%;
#line <%= __LINE__ + 1 %> <%=cstr __FILE__ %>
static bool
leafness_of_getglobal(VALUE gentry)
{
const struct rb_global_entry *e = (void *)gentry;
if (UNLIKELY(rb_gvar_is_traced(e))) {
return false;
}
else {
/* We cannot write this function using a switch() because a
* case label cannot be a function pointer. */
static rb_gvar_getter_t *const allowlist[] = {
rb_gvar_val_getter,
rb_gvar_var_getter,
/* rb_gvar_undef_getter issues rb_warning() */
};
rb_gvar_getter_t *f = rb_gvar_getter_function_of(e);
int i;
for (i = 0; i < numberof(allowlist); i++) {
if (f == allowlist[i]) {
return true;
}
}
return false;
}
}
static bool
leafness_of_setglobal(VALUE gentry)
{
const struct rb_global_entry *e = (void *)gentry;
if (UNLIKELY(rb_gvar_is_traced(e))) {
return false;
}
else {
/* We cannot write this function using a switch() because a
* case label cannot be a function pointer. */
static rb_gvar_setter_t *const allowlist[] = {
rb_gvar_val_setter,
/* rb_gvar_readonly_setter issues rb_name_error() */
rb_gvar_var_setter,
rb_gvar_undef_setter,
};
rb_gvar_setter_t *f = rb_gvar_setter_function_of(e);
int i;
for (i = 0; i < numberof(allowlist); i++) {
if (f == allowlist[i]) {
return true;
}
}
return false;
}
}
#include "iseq.h"
static bool
leafness_of_defined(rb_num_t op_type)
{
/* see also: vm_insnhelper.c:vm_defined() */
switch (op_type) {
case DEFINED_IVAR:
case DEFINED_IVAR2:
case DEFINED_GVAR:
case DEFINED_CVAR:
case DEFINED_YIELD:
case DEFINED_REF:
case DEFINED_ZSUPER:
return false;
case DEFINED_CONST:
case DEFINED_CONST_FROM:
/* has rb_autoload_load(); */
return false;
case DEFINED_FUNC:
case DEFINED_METHOD:
/* calls #respond_to_missing? */
return false;
default:
rb_bug("unknown operand %ld: blame @shyouhei.", op_type);
}
}
static bool
leafness_of_checkmatch(rb_num_t flag)
{
/* see also: vm_insnhelper.c:check_match() */
if (flag == VM_CHECKMATCH_TYPE_WHEN) {
return true;
}
else {
/* has rb_funcallv() */
return false;
}
}
#pragma RubyVM reset source