/* Copyright (c) 2022 Contrast Security, Inc. See * https://www.contrastsecurity.com/enduser-terms-0317a for more details. */ #include "cs__assess_basic_object.h" #include "../cs__common/cs__common.h" #include "../cs__scope/cs__scope.h" #include <ruby.h> /* * Source code of instance_eval: * * static VALUE * rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self) * { * VALUE klass = singleton_class_for_eval(self); * return specific_eval(argc, argv, klass, self, RB_PASS_CALLED_KEYWORDS); * } */ VALUE contrast_check_and_register_instance_patch( const char *module_name, const char *method_name, VALUE(c_fn)(const int, VALUE *, const VALUE)); void contrast_assess_instance_eval_trigger_check(VALUE self, VALUE source, VALUE ret) { rb_funcall(basic_eval_trigger, instance_trigger_check_method, 3, self, source, ret); } VALUE contrast_assess_basic_object_instance_eval(const int argc, const VALUE *argv, const VALUE self) { if (RTEST(rb_funcall(contrast_patcher(), rb_sym_skip_assess_analysis, 0))) { return rb_obj_instance_eval(argc, argv, self); } VALUE nested_scope = inst_methods_in_cntr_scope(contrast_patcher(), 0); /* Enter scope */ inst_methods_enter_cntr_scope(contrast_patcher(), 0); /* Call the source: */ VALUE ret = rb_obj_instance_eval(argc, argv, self); if (nested_scope == Qfalse && argc > 0) { VALUE data = argv[0]; contrast_assess_instance_eval_trigger_check(self, data, ret); } /* Exit scope */ inst_methods_exit_cntr_scope(contrast_patcher(), 0); return ret; } void Init_cs__assess_basic_object(void) { basic_eval_trigger = rb_define_class_under(core_assess, "EvalTrigger", rb_cObject); instance_trigger_check_method = rb_intern("instance_eval_trigger_check"); /* We don't keep a reference to the underlying method. * Instead, we call rb_obj_instance_eval directly. * This should work an overwhelming majority of the time, * but if someone else patched BasicObject#instance_eval, * IDK if this is intentional... noting it. -ajm */ contrast_check_and_register_instance_patch("BasicObject", "instance_eval", contrast_assess_basic_object_instance_eval); }