Bypass check for warning_category on internal calls

This commit is contained in:
Nobuyoshi Nakada 2020-12-24 10:27:59 +09:00
Родитель 64d79d333b
Коммит 2556cd3f51
2 изменённых файлов: 37 добавлений и 25 удалений

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

@ -5015,6 +5015,7 @@ error.$(OBJEXT): $(top_srcdir)/internal/compilers.h
error.$(OBJEXT): $(top_srcdir)/internal/error.h error.$(OBJEXT): $(top_srcdir)/internal/error.h
error.$(OBJEXT): $(top_srcdir)/internal/eval.h error.$(OBJEXT): $(top_srcdir)/internal/eval.h
error.$(OBJEXT): $(top_srcdir)/internal/gc.h error.$(OBJEXT): $(top_srcdir)/internal/gc.h
error.$(OBJEXT): $(top_srcdir)/internal/hash.h
error.$(OBJEXT): $(top_srcdir)/internal/imemo.h error.$(OBJEXT): $(top_srcdir)/internal/imemo.h
error.$(OBJEXT): $(top_srcdir)/internal/io.h error.$(OBJEXT): $(top_srcdir)/internal/io.h
error.$(OBJEXT): $(top_srcdir)/internal/load.h error.$(OBJEXT): $(top_srcdir)/internal/load.h

61
error.c
Просмотреть файл

@ -30,6 +30,7 @@
#include "internal.h" #include "internal.h"
#include "internal/error.h" #include "internal/error.h"
#include "internal/eval.h" #include "internal/eval.h"
#include "internal/hash.h"
#include "internal/io.h" #include "internal/io.h"
#include "internal/load.h" #include "internal/load.h"
#include "internal/object.h" #include "internal/object.h"
@ -77,8 +78,9 @@ static ID id_category;
static ID id_deprecated; static ID id_deprecated;
static ID id_experimental; static ID id_experimental;
static VALUE sym_category; static VALUE sym_category;
static VALUE warning_categories; static struct {
static VALUE warning_category_t_map; st_table *id2enum, *enum2id;
} warning_categories;
extern const char ruby_description[]; extern const char ruby_description[];
@ -162,13 +164,24 @@ rb_warning_category_mask(VALUE category)
rb_warning_category_t rb_warning_category_t
rb_warning_category_from_name(VALUE category) rb_warning_category_from_name(VALUE category)
{ {
VALUE cat_value; st_data_t cat_value;
ID cat_id;
Check_Type(category, T_SYMBOL); Check_Type(category, T_SYMBOL);
cat_value = rb_hash_aref(warning_categories, category); if (!(cat_id = rb_check_id(&category)) ||
if (cat_value == Qnil) { !st_lookup(warning_categories.id2enum, cat_id, &cat_value)) {
rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category); rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category);
} }
return NUM2INT(cat_value); return (rb_warning_category_t)cat_value;
}
static VALUE
rb_warning_category_to_name(rb_warning_category_t category)
{
st_data_t id;
if (!st_lookup(warning_categories.enum2id, category, &id)) {
rb_raise(rb_eArgError, "invalid category: %d", (int)category);
}
return id ? ID2SYM(id) : Qnil;
} }
void void
@ -312,11 +325,8 @@ rb_warning_warn_arity(void)
static VALUE static VALUE
rb_warn_category(VALUE str, VALUE category) rb_warn_category(VALUE str, VALUE category)
{ {
if (category != Qnil) { if (RUBY_DEBUG && !NIL_P(category)) {
category = rb_to_symbol_type(category); rb_warning_category_from_name(category);
if (!RTEST(rb_hash_aref(warning_categories, category))) {
rb_raise(rb_eArgError, "invalid warning category used: %s", rb_id2name(SYM2ID(category)));
}
} }
if (rb_warning_warn_arity() == 1) { if (rb_warning_warn_arity() == 1) {
@ -386,7 +396,7 @@ rb_category_compile_warn(rb_warning_category_t category, const char *file, int l
va_start(args, fmt); va_start(args, fmt);
str = warn_vsprintf(NULL, file, line, fmt, args); str = warn_vsprintf(NULL, file, line, fmt, args);
va_end(args); va_end(args);
rb_warn_category(str, rb_hash_fetch(warning_category_t_map, INT2NUM(category))); rb_warn_category(str, rb_warning_category_to_name(category));
} }
static VALUE static VALUE
@ -418,7 +428,7 @@ rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
{ {
if (!NIL_P(ruby_verbose)) { if (!NIL_P(ruby_verbose)) {
with_warning_string(mesg, 0, fmt) { with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_hash_fetch(warning_category_t_map, INT2NUM(category))); rb_warn_category(mesg, rb_warning_category_to_name(category));
} }
} }
} }
@ -450,7 +460,7 @@ rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
{ {
if (RTEST(ruby_verbose)) { if (RTEST(ruby_verbose)) {
with_warning_string(mesg, 0, fmt) { with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_hash_fetch(warning_category_t_map, INT2NUM(category))); rb_warn_category(mesg, rb_warning_category_to_name(category));
} }
} }
} }
@ -562,6 +572,11 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALU
RBASIC_SET_CLASS(str, rb_cString); RBASIC_SET_CLASS(str, rb_cString);
} }
if (!NIL_P(category)) {
category = rb_to_symbol_type(category);
rb_warning_category_from_name(category);
}
if (exc == rb_mWarning) { if (exc == rb_mWarning) {
rb_must_asciicompat(str); rb_must_asciicompat(str);
rb_write_error_str(str); rb_write_error_str(str);
@ -2846,18 +2861,14 @@ Init_Exception(void)
sym_category = ID2SYM(id_category); sym_category = ID2SYM(id_category);
warning_categories = rb_ident_hash_new(); warning_categories.id2enum = rb_init_identtable();
rb_gc_register_mark_object(warning_categories); st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED);
rb_hash_aset(warning_categories, ID2SYM(id_deprecated), INT2NUM(RB_WARN_CATEGORY_DEPRECATED)); st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL);
rb_hash_aset(warning_categories, ID2SYM(id_experimental), INT2NUM(RB_WARN_CATEGORY_EXPERIMENTAL));
rb_obj_freeze(warning_categories);
warning_category_t_map = rb_ident_hash_new(); warning_categories.enum2id = rb_init_identtable();
rb_gc_register_mark_object(warning_category_t_map); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_NONE, 0);
rb_hash_aset(warning_category_t_map, INT2NUM(RB_WARN_CATEGORY_NONE), Qnil); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_DEPRECATED, id_deprecated);
rb_hash_aset(warning_category_t_map, INT2NUM(RB_WARN_CATEGORY_DEPRECATED), ID2SYM(id_deprecated)); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_EXPERIMENTAL, id_experimental);
rb_hash_aset(warning_category_t_map, INT2NUM(RB_WARN_CATEGORY_EXPERIMENTAL), ID2SYM(id_experimental));
rb_obj_freeze(warning_category_t_map);
} }
void void