VALUE rb_singleton_class(VALUE obj) { VALUE klass; if (FIXNUM_P(obj) || SYMBOL_P(obj)) { rb_raise(rb_eTypeError, "can't define singleton"); } if (rb_special_const_p(obj)) { SPECIAL_SINGLETON(Qnil, rb_cNilClass); SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); rb_bug("unknown immediate %ld", obj); } DEFER_INTS; if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) { klass = RBASIC(obj)->klass; } else { klass = rb_make_metaclass(obj, RBASIC(obj)->klass); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); } else { FL_UNSET(klass, FL_TAINT); } if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); ALLOW_INTS; return klass; }
/* * Returns system temporary directory; typically "/tmp". */ static VALUE etc_systmpdir(void) { VALUE tmpdir; #ifdef _WIN32 WCHAR path[_MAX_PATH]; UINT len = rb_w32_system_tmpdir(path, numberof(path)); if (!len) return Qnil; tmpdir = rb_w32_conv_from_wchar(path, rb_filesystem_encoding()); #else const char default_tmp[] = "/tmp"; const char *tmpstr = default_tmp; size_t tmplen = strlen(default_tmp); # if defined _CS_DARWIN_USER_TEMP_DIR #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif char path[MAXPATHLEN]; size_t len; len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path)); if (len > 0) { tmpstr = path; tmplen = len - 1; } # endif tmpdir = rb_filesystem_str_new(tmpstr, tmplen); #endif FL_UNSET(tmpdir, FL_TAINT); return tmpdir; }
/* call-seq: * unfreeze -> self * * Unfreezes the given object. Will raise a +SecurityError+ if * <tt>$SAFE</tt> > 0. Has no effect if the object is not yet frozen. */ static VALUE evilr_unfreeze(VALUE self) { if (rb_safe_level() > 0) { rb_raise(rb_eSecurityError, "can't unfreeze objects when $SAFE > 0"); } FL_UNSET(self, FL_FREEZE); return self; }
static int load_encoding(const char *name) { VALUE enclib = rb_sprintf("enc/%s.so", name); VALUE verbose = ruby_verbose; VALUE debug = ruby_debug; VALUE errinfo; VALUE loaded; char *s = RSTRING_PTR(enclib) + 4, *e = RSTRING_END(enclib) - 3; int idx; while (s < e) { if (!ISALNUM(*s)) *s = '_'; else if (ISUPPER(*s)) *s = (char)TOLOWER(*s); ++s; } FL_UNSET(enclib, FL_TAINT|FL_UNTRUSTED); OBJ_FREEZE(enclib); ruby_verbose = Qfalse; ruby_debug = Qfalse; errinfo = rb_errinfo(); loaded = rb_protect(require_enc, enclib, 0); ruby_verbose = verbose; ruby_debug = debug; rb_set_errinfo(errinfo); if (NIL_P(loaded)) return -1; if ((idx = rb_enc_registered(name)) < 0) return -1; if (enc_autoload_p(enc_table.list[idx].enc)) return -1; return idx; }
static int load_encoding(const char *name) { VALUE enclib = rb_sprintf("enc/%s.so", name); VALUE verbose = ruby_verbose; VALUE debug = ruby_debug; VALUE errinfo; char *s = RSTRING_PTR(enclib) + 4, *e = RSTRING_END(enclib) - 3; int loaded; int idx; while (s < e) { if (!ISALNUM(*s)) *s = '_'; else if (ISUPPER(*s)) *s = (char)TOLOWER(*s); ++s; } FL_UNSET(enclib, FL_TAINT); enclib = rb_fstring(enclib); ruby_verbose = Qfalse; ruby_debug = Qfalse; errinfo = rb_errinfo(); loaded = rb_require_internal(enclib, rb_safe_level()); ruby_verbose = verbose; ruby_debug = debug; rb_set_errinfo(errinfo); if (loaded < 0 || 1 < loaded) return -1; if ((idx = rb_enc_registered(name)) < 0) return -1; if (enc_autoload_p(enc_table.list[idx].enc)) return -1; return idx; }
VALUE rb_singleton_class(VALUE obj) { VALUE klass; ID attached; if (FIXNUM_P(obj) || SYMBOL_P(obj)) { rb_raise(rb_eTypeError, "can't define singleton"); } if (rb_special_const_p(obj)) { SPECIAL_SINGLETON(Qnil, rb_cNilClass); SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); rb_bug("unknown immediate %ld", obj); } CONST_ID(attached, "__attached__"); if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && rb_ivar_get(RBASIC(obj)->klass, attached) == obj) { klass = RBASIC(obj)->klass; } else { klass = rb_make_metaclass(obj, RBASIC(obj)->klass); } if (BUILTIN_TYPE(obj) == T_CLASS) { if (rb_iv_get(RBASIC(klass)->klass, "__attached__") != klass) make_metametaclass(klass); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); } else { FL_UNSET(klass, FL_TAINT); } if (OBJ_UNTRUSTED(obj)) { OBJ_UNTRUST(klass); } else { FL_UNSET(klass, FL_UNTRUSTED); } if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); return klass; }
/* call-seq: * detach_singleton -> self * * If the receiver is a singleton class, it is transformed into a * regular class and it is detached from the instance. Note that * this means it becomes the class of the object to which it was previous * attached. If the receiver is not a singleton class, has no effect. * Returns the receiver. */ static VALUE evilr_detach_singleton(VALUE klass) { if (IS_SINGLETON_CLASS(klass)) { FL_UNSET(klass, FL_SINGLETON); if (RCLASS_IV_TBL(klass)) { st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&evilr__attached, 0); } } return klass; }
/* call-seq: * to_class(klass=Object) -> Class * * Makes a copy of the module, converts the copy to a class, and returns it. The * returned class can then have instances created from it. The +klass+ argument * sets the superclass of the returned class. If +klass+ is not a Class, * raises +TypeError+. */ static VALUE evilr_to_class(int argc, VALUE *argv, VALUE self) { VALUE klass = evilr__optional_class(argc, argv); self = rb_obj_clone(self); RBASIC_SET_KLASS(self, rb_singleton_class(klass)); RCLASS_SET_SUPER(self, klass); FL_UNSET(self, T_MASK); FL_SET(self, T_CLASS); return self; }
/*! * \internal * Returns the singleton class of \a obj. Creates it if necessary. * * \note DO NOT expose the returned singleton class to * outside of class.c. * Use \ref rb_singleton_class instead for * consistency of the metaclass hierarchy. */ static VALUE singleton_class_of(VALUE obj) { VALUE klass; if (FIXNUM_P(obj) || SYMBOL_P(obj)) { rb_raise(rb_eTypeError, "can't define singleton"); } if (rb_special_const_p(obj)) { SPECIAL_SINGLETON(Qnil, rb_cNilClass); SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); rb_bug("unknown immediate %p", (void *)obj); } if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) { klass = RBASIC(obj)->klass; } else { klass = rb_make_metaclass(obj, RBASIC(obj)->klass); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); } else { FL_UNSET(klass, FL_TAINT); } if (OBJ_UNTRUSTED(obj)) { OBJ_UNTRUST(klass); } else { FL_UNSET(klass, FL_UNTRUSTED); } if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); return klass; }
/* call-seq: * dup_singleton_class(klass=Object) -> Class || nil * * If the receiver has a singleton class, a copy of the class is returned, * and the superclass of that class is set to the given +klass+. Any * modules that extend the object become modules included in the returned class. * If the receiver does not have a singleton class, +nil+ is returned and no * changes are made. If the receiver is an immediate, a +TypeError+ is raised. */ static VALUE evilr_dup_singleton_class(int argc, VALUE *argv, VALUE self) { VALUE klass; evilr__check_immediate(self); if (!HAS_SINGLETON_CLASS(self)) { return Qnil; } klass = evilr__optional_class(argc, argv); self = rb_singleton_class_clone(self); evilr__reparent_class(self, klass); FL_UNSET(self, FL_SINGLETON); return self; }
static VALUE undefine_final(VALUE os, SEL sel, VALUE obj) { if (__os_finalizers != NULL) CFDictionaryRemoveValue(__os_finalizers, (const void *)obj); if (NATIVE(obj)) { rb_objc_flag_set((void *)obj, FL_FINALIZE, false); } else { FL_UNSET(obj, FL_FINALIZE); } return obj; }
/* * Returns system temporary directory; typically "/tmp". */ static VALUE etc_systmpdir(void) { VALUE tmpdir; #ifdef _WIN32 WCHAR path[_MAX_PATH]; UINT len = rb_w32_system_tmpdir(path, numberof(path)); if (!len) return Qnil; tmpdir = rb_w32_conv_from_wchar(path, rb_filesystem_encoding()); #else tmpdir = rb_filesystem_str_new_cstr("/tmp"); #endif FL_UNSET(tmpdir, FL_TAINT); return tmpdir; }
/*! * \internal * Returns the singleton class of \a obj. Creates it if necessary. * * \note DO NOT expose the returned singleton class to * outside of class.c. * Use \ref rb_singleton_class instead for * consistency of the metaclass hierarchy. */ static VALUE singleton_class_of(VALUE obj) { VALUE klass; if (FIXNUM_P(obj) || FLONUM_P(obj) || SYMBOL_P(obj)) { rb_raise(rb_eTypeError, "can't define singleton"); } if (SPECIAL_CONST_P(obj)) { klass = special_singleton_class_of(obj); if (NIL_P(klass)) rb_bug("unknown immediate %p", (void *)obj); return klass; } else { enum ruby_value_type type = BUILTIN_TYPE(obj); if (type == T_FLOAT || type == T_BIGNUM) { rb_raise(rb_eTypeError, "can't define singleton"); } } if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) { klass = RBASIC(obj)->klass; } else { klass = rb_make_metaclass(obj, RBASIC(obj)->klass); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); } else { FL_UNSET(klass, FL_TAINT); } if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); return klass; }
/* call-seq: * to_module -> Module * * Makes a copy of the class, converts the copy to a module, and returns it. The * returned module can be included in other classes. */ static VALUE evilr_to_module(VALUE klass) { VALUE mod, iclass; if (IS_SINGLETON_CLASS(klass)) { if((mod = evilr_singleton_class_instance(klass))) { mod = rb_singleton_class_clone(mod); (void)evilr_detach_singleton(mod); } else { rb_raise(rb_eTypeError, "singleton class without attached instance"); } } else { mod = rb_obj_clone(klass); } RBASIC_SET_KLASS(mod, rb_cModule); iclass = RCLASS_SUPER(mod); RCLASS_SET_SUPER(mod, NULL); FL_UNSET(mod, T_MASK); FL_SET(mod, T_MODULE); evilr__include_iclasses(mod, iclass); return mod; }
VALUE rb_object_free(VALUE obj) { ID id_destructor = rb_intern("__destruct__"); /* value returned by destructor */ VALUE destruct_value = Qnil; /* prevent freeing of immediates */ switch (TYPE(obj)) { case T_NIL: case T_FIXNUM: case T_TRUE: case T_FALSE: case T_SYMBOL: rb_raise(rb_eTypeError, "obj_free() called for immediate value"); break; } /* prevent freeing of *some* critical objects */ if ((obj == rb_cObject) || (obj == rb_cClass) || (obj == rb_cModule) || (obj == rb_cSymbol) || (obj == rb_cFixnum) || (obj == rb_cFloat) || (obj == rb_cString) || (obj == rb_cRegexp) || (obj == rb_cInteger) || (obj == rb_cArray) || (obj == rb_cNilClass) || (obj == rb_cFalseClass) || (obj == rb_cTrueClass) || (obj == rb_cNumeric) || (obj == rb_cBignum) || (obj == rb_cStruct)) rb_raise(rb_eTypeError, "obj_free() called for critical object"); /* run destructor (if one is defined) */ if (rb_respond_to(obj, id_destructor)) destruct_value = rb_funcall(obj, id_destructor, 0); #ifdef RUBY_19 switch (BUILTIN_TYPE(obj)) { case T_NIL: case T_FIXNUM: case T_TRUE: case T_FALSE: rb_bug("obj_free() called for broken object"); break; } if (FL_TEST(obj, FL_EXIVAR)) { rb_free_generic_ivar((VALUE)obj); FL_UNSET(obj, FL_EXIVAR); } switch (BUILTIN_TYPE(obj)) { case T_OBJECT: if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) && RANY(obj)->as.object.as.heap.ivptr) { xfree(RANY(obj)->as.object.as.heap.ivptr); } break; case T_MODULE: case T_CLASS: rb_clear_cache_by_class((VALUE)obj); rb_free_m_table(RCLASS_M_TBL(obj)); if (RCLASS_IV_TBL(obj)) { st_free_table(RCLASS_IV_TBL(obj)); } if (RCLASS_IV_INDEX_TBL(obj)) { st_free_table(RCLASS_IV_INDEX_TBL(obj)); } xfree(RANY(obj)->as.klass.ptr); break; case T_STRING: rb_str_free(obj); break; case T_ARRAY: rb_ary_free(obj); break; case T_HASH: if (RANY(obj)->as.hash.ntbl) { st_free_table(RANY(obj)->as.hash.ntbl); } break; case T_REGEXP: if (RANY(obj)->as.regexp.ptr) { onig_free(RANY(obj)->as.regexp.ptr); } break; case T_DATA: if (DATA_PTR(obj)) { if (RTYPEDDATA_P(obj)) { RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->dfree; } if ((long)RANY(obj)->as.data.dfree == -1) { xfree(DATA_PTR(obj)); } else if (RANY(obj)->as.data.dfree) { make_deferred(RANY(obj)); return 1; } } break; case T_MATCH: if (RANY(obj)->as.match.rmatch) { struct rmatch *rm = RANY(obj)->as.match.rmatch; onig_region_free(&rm->regs, 0); if (rm->char_offset) xfree(rm->char_offset); xfree(rm); } break; case T_FILE: if (RANY(obj)->as.file.fptr) { make_io_deferred(RANY(obj)); return 1; } break; case T_RATIONAL: case T_COMPLEX: break; case T_ICLASS: /* iClass shares table with the module */ xfree(RANY(obj)->as.klass.ptr); break; case T_FLOAT: break; case T_BIGNUM: if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) { xfree(RBIGNUM_DIGITS(obj)); } break; case T_NODE: switch (nd_type(obj)) { case NODE_SCOPE: if (RANY(obj)->as.node.u1.tbl) { xfree(RANY(obj)->as.node.u1.tbl); } break; case NODE_ALLOCA: xfree(RANY(obj)->as.node.u1.node); break; } break; /* no need to free iv_tbl */ case T_STRUCT: if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && RANY(obj)->as.rstruct.as.heap.ptr) { xfree(RANY(obj)->as.rstruct.as.heap.ptr); } break; default: rb_bug("gc_sweep(): unknown data type 0x%x(%p)", BUILTIN_TYPE(obj), (void*)obj); } #else switch (BUILTIN_TYPE(obj)) { case T_NIL: case T_FIXNUM: case T_TRUE: case T_FALSE: rb_bug("obj_free() called for broken object"); break; } if (FL_TEST(obj, FL_EXIVAR)) { rb_free_generic_ivar((VALUE)obj); } switch (BUILTIN_TYPE(obj)) { case T_OBJECT: if (RANY(obj)->as.object.iv_tbl) { st_free_table(RANY(obj)->as.object.iv_tbl); } break; case T_MODULE: case T_CLASS: rb_clear_cache_by_class((VALUE)obj); st_free_table(RANY(obj)->as.klass.m_tbl); if (RANY(obj)->as.object.iv_tbl) { st_free_table(RANY(obj)->as.object.iv_tbl); } break; case T_STRING: if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); } break; case T_ARRAY: if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); } break; case T_HASH: if (RANY(obj)->as.hash.tbl) { st_free_table(RANY(obj)->as.hash.tbl); } break; case T_REGEXP: if (RANY(obj)->as.regexp.ptr) { re_free_pattern(RANY(obj)->as.regexp.ptr); } if (RANY(obj)->as.regexp.str) { RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); } break; case T_DATA: if (DATA_PTR(obj)) { if ((long)RANY(obj)->as.data.dfree == -1) { RUBY_CRITICAL(free(DATA_PTR(obj))); } else if (RANY(obj)->as.data.dfree) { make_deferred(RANY(obj)); return 1; } } break; case T_MATCH: if (RANY(obj)->as.match.regs) { re_free_registers(RANY(obj)->as.match.regs); RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); } break; case T_FILE: if (RANY(obj)->as.file.fptr) { struct rb_io_t *fptr = RANY(obj)->as.file.fptr; make_deferred(RANY(obj)); RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize; RDATA(obj)->data = fptr; return 1; } break; case T_ICLASS: /* iClass shares table with the module */ break; case T_FLOAT: case T_VARMAP: case T_BLKTAG: break; case T_BIGNUM: if (RANY(obj)->as.bignum.digits) { RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); } break; case T_NODE: switch (nd_type(obj)) { case NODE_SCOPE: if (RANY(obj)->as.node.u1.tbl) { RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl)); } break; case NODE_ALLOCA: RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node)); break; } break; /* no need to free iv_tbl */ case T_SCOPE: if (RANY(obj)->as.scope.local_vars && RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { VALUE *vars = RANY(obj)->as.scope.local_vars-1; if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl)); if ((RANY(obj)->as.scope.flags & (SCOPE_MALLOC|SCOPE_CLONE)) == SCOPE_MALLOC) RUBY_CRITICAL(free(vars)); } break; case T_STRUCT: if (RANY(obj)->as.rstruct.ptr) { RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); } break; default: rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", RANY(obj)->as.basic.flags & T_MASK, obj); } #endif rb_gc_force_recycle(obj); return destruct_value; }