diff options
| -rw-r--r-- | .gdbinit | 19 | ||||
| -rw-r--r-- | NEWS.md | 16 | ||||
| -rw-r--r-- | encoding.c | 2 | ||||
| -rw-r--r-- | error.c | 7 | ||||
| -rw-r--r-- | ext/json/lib/json/version.rb | 2 | ||||
| -rw-r--r-- | ext/json/parser/parser.c | 6 | ||||
| -rw-r--r-- | ext/objspace/objspace_dump.c | 2 | ||||
| -rw-r--r-- | gc.c | 97 | ||||
| -rw-r--r-- | include/ruby/internal/core/rdata.h | 287 | ||||
| -rw-r--r-- | include/ruby/internal/core/rtypeddata.h | 53 | ||||
| -rw-r--r-- | include/ruby/internal/value_type.h | 22 | ||||
| -rw-r--r-- | include/ruby/random.h | 1 | ||||
| -rw-r--r-- | misc/lldb_rb/utils.py | 37 | ||||
| -rw-r--r-- | ractor.c | 2 | ||||
| -rw-r--r-- | spec/ruby/optional/capi/ext/rubyspec.h | 4 | ||||
| -rw-r--r-- | spec/ruby/optional/capi/ext/typed_data_spec.c | 9 | ||||
| -rw-r--r-- | spec/ruby/optional/capi/typed_data_spec.rb | 18 | ||||
| -rw-r--r-- | test/json/json_ryu_fallback_test.rb | 8 | ||||
| -rw-r--r-- | test/rubygems/test_gem_safe_yaml.rb | 6 | ||||
| -rw-r--r-- | zjit/src/cruby_bindings.inc.rs | 1 |
20 files changed, 137 insertions, 462 deletions
@@ -185,19 +185,14 @@ define rp print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_DATA - if ($flags & RUBY_TYPED_FL_IS_TYPED_DATA) - set $data = (struct RTypedData *)($arg0) - set $type = (const rb_data_type_t *)($data->type & ~1) - printf "%sT_DATA%s(%s): ", $color_type, $color_end, $type->wrap_struct_name - print *$type - if ($data->type & 1) - print (void *)&$data->data - else - print $data - end + set $data = (struct RTypedData *)($arg0) + set $type = (const rb_data_type_t *)($data->type & ~1) + printf "%sT_DATA%s(%s): ", $color_type, $color_end, $type->wrap_struct_name + print *$type + if ($data->type & 1) + print (void *)&$data->data else - printf "%sT_DATA%s: ", $color_type, $color_end - print *(struct RData *)($arg0) + print $data end else if ($flags & RUBY_T_MASK) == RUBY_T_MATCH @@ -82,7 +82,7 @@ releases. * 6.0.1 to [v6.0.1.1][erb-v6.0.1.1], [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3], [v6.0.4][erb-v6.0.4] * ipaddr 1.2.9 * 1.2.8 to [v1.2.9][ipaddr-v1.2.9] -* json 2.19.6 +* json 2.19.7 * 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5], [v2.19.6][json-v2.19.6] * openssl 4.0.2 * 4.0.0 to [v4.0.1][openssl-v4.0.1], [v4.0.2][openssl-v4.0.2] @@ -161,6 +161,19 @@ Ruby 4.0 bundled RubyGems and Bundler version 4. see the following links for det [[Feature #21861]] +### Removed APIs + +The following APIs, which have been deprecated for many years, are removed. +[[Feature #21768]] + +* old postponed job functions, +* untyped data object type/functions, +* old APIs to allocate a data object, +* taintedness/trustedness enums/macros, +* `rb_gc_force_recycle` function, +* `rb_iterate` function, +* and some functions and constants for internal use. + ## Implementation improvements ### Ractor @@ -172,6 +185,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [Feature #8948]: https://bugs.ruby-lang.org/issues/8948 [Feature #15330]: https://bugs.ruby-lang.org/issues/15330 [Feature #21390]: https://bugs.ruby-lang.org/issues/21390 +[Feature #21768]: https://bugs.ruby-lang.org/issues/21768 [Feature #21785]: https://bugs.ruby-lang.org/issues/21785 [Feature #21796]: https://bugs.ruby-lang.org/issues/21796 [Feature #21853]: https://bugs.ruby-lang.org/issues/21853 diff --git a/encoding.c b/encoding.c index 8bb393b471..73fad8f1a6 100644 --- a/encoding.c +++ b/encoding.c @@ -126,7 +126,7 @@ static const rb_data_type_t encoding_data_type = { }; #define is_encoding_type(obj) (RTYPEDDATA_TYPE(obj) == &encoding_data_type) -#define is_data_encoding(obj) (rbimpl_rtypeddata_p(obj) && is_encoding_type(obj)) +#define is_data_encoding(obj) is_encoding_type(obj) #define is_obj_encoding(obj) (rbimpl_obj_typeddata_p(obj) && is_encoding_type(obj)) int @@ -1364,8 +1364,7 @@ rb_check_type(VALUE x, int t) rb_bug(UNDEF_LEAKED); } - xt = TYPE(x); - if (xt != t || (xt == T_DATA && rbimpl_rtypeddata_p(x))) { + if (t == T_DATA) { /* * Typed data is not simple `T_DATA`, but in a sense an * extension of `struct RVALUE`, which are incompatible with @@ -1374,6 +1373,10 @@ rb_check_type(VALUE x, int t) * So it is not enough to just check `T_DATA`, it must be * identified by its `type` using `Check_TypedStruct` instead. */ + rb_unexpected_object_type(x, builtin_types[t]); + } + xt = TYPE(x); + if (xt != t) { unexpected_type(x, xt, t); } } diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index 7ea306656b..a69590ff9c 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module JSON - VERSION = '2.19.6' + VERSION = '2.19.7' end diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index fc16f727fe..363f109d3a 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1202,7 +1202,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig raise_parse_error_at("invalid number: %s", state, start); } - exponent = negative_exponent ? -abs_exponent : abs_exponent; + if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) { + exponent = negative_exponent ? INT64_MIN : INT64_MAX; + } else { + exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent; + } } if (integer) { diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index b644c489b8..68ada01af3 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -573,7 +573,7 @@ dump_object(VALUE obj, struct dump_config *dc) break; case T_DATA: - if (RTYPEDDATA_P(obj)) { + { const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); dump_append(dc, ", \"struct\":\""); dump_append(dc, type->wrap_struct_name); @@ -337,8 +337,10 @@ rb_gc_shutdown_call_finalizer_p(VALUE obj) { switch (BUILTIN_TYPE(obj)) { case T_DATA: - if (!ruby_free_at_exit_p() && !DATA_PTR(obj)) return false; - if (!ruby_free_at_exit_p() && !RTYPEDDATA_P(obj) && !RDATA(obj)->dfree) return false; + if (!ruby_free_at_exit_p()) { + if (!RDATA(obj)->type) return false; + if (!rbimpl_typeddata_embedded_p(obj) && !RTYPEDDATA(obj)->data) return false; + } if (rb_obj_is_thread(obj)) return false; if (rb_obj_is_mutex(obj)) return false; if (rb_obj_is_fiber(obj)) return false; @@ -374,7 +376,6 @@ void rb_vm_update_references(void *ptr); #define rb_setjmp(env) RUBY_SETJMP(env) #define rb_jmp_buf rb_jmpbuf_t -#undef rb_data_object_wrap #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) #define MAP_ANONYMOUS MAP_ANON @@ -1138,33 +1139,6 @@ rb_data_object_check(VALUE klass) } } -VALUE -rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) -{ - RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1); - if (klass) rb_data_object_check(klass); - VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, !dmark, sizeof(struct RData)); - - rb_gc_register_pinning_obj(obj); - - struct RData *data = (struct RData *)obj; - data->fields_obj = 0; - data->_reserved = 0; - data->data = datap; - data->dmark = dmark; - data->dfree = dfree; - - return obj; -} - -VALUE -rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) -{ - VALUE obj = rb_data_object_wrap(klass, 0, dmark, dfree); - DATA_PTR(obj) = xcalloc(1, size); - return obj; -} - #define RTYPEDDATA_EMBEDDED_P rbimpl_typeddata_embedded_p #define RB_DATA_TYPE_EMBEDDABLE_P(type) ((type)->flags & RUBY_TYPED_EMBEDDABLE) #define RTYPEDDATA_EMBEDDABLE_P(obj) RB_DATA_TYPE_EMBEDDABLE_P(RTYPEDDATA_TYPE(obj)) @@ -1175,7 +1149,7 @@ typed_data_alloc(VALUE klass, VALUE typed_flag, void *datap, const rb_data_type_ RBIMPL_NONNULL_ARG(type); if (klass) rb_data_object_check(klass); bool wb_protected = (type->flags & RUBY_FL_WB_PROTECTED) || !type->function.dmark; - VALUE obj = rb_newobj(GET_EC(), klass, T_DATA | RUBY_TYPED_FL_IS_TYPED_DATA, ROOT_SHAPE_ID, wb_protected, size); + VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, wb_protected, size); rb_gc_register_pinning_obj(obj); @@ -1237,18 +1211,16 @@ static size_t rb_objspace_data_type_memsize(VALUE obj) { size_t size = 0; - if (RTYPEDDATA_P(obj)) { - const void *ptr = RTYPEDDATA_GET_DATA(obj); + const void *ptr = RTYPEDDATA_GET_DATA(obj); - if (ptr) { - if (RTYPEDDATA_EMBEDDABLE_P(obj) && !RTYPEDDATA_EMBEDDED_P(obj)) { - size += ruby_xmalloc_usable_size((void *)ptr); - } + if (ptr) { + if (RTYPEDDATA_EMBEDDABLE_P(obj) && !RTYPEDDATA_EMBEDDED_P(obj)) { + size += ruby_xmalloc_usable_size((void *)ptr); + } - const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); - if (type->function.dsize) { - size += type->function.dsize(ptr); - } + const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); + if (type->function.dsize) { + size += type->function.dsize(ptr); } } @@ -1258,12 +1230,7 @@ rb_objspace_data_type_memsize(VALUE obj) const char * rb_objspace_data_type_name(VALUE obj) { - if (RTYPEDDATA_P(obj)) { - return RTYPEDDATA_TYPE(obj)->wrap_struct_name; - } - else { - return 0; - } + return RTYPEDDATA_TYPE(obj)->wrap_struct_name; } void @@ -1285,7 +1252,7 @@ rb_gc_handle_weak_references(VALUE obj) { switch (BUILTIN_TYPE(obj)) { case T_DATA: - if (RTYPEDDATA_P(obj)) { + { const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); if (type->function.handle_weak_references) { @@ -1298,9 +1265,6 @@ rb_gc_handle_weak_references(VALUE obj) ); } } - else { - rb_bug("rb_gc_handle_weak_references: unknown T_DATA"); - } break; case T_IMEMO: { @@ -1423,7 +1387,7 @@ rb_gc_obj_needs_cleanup_p(VALUE obj) return false; case T_DATA: - if (flags & RUBY_TYPED_FL_IS_TYPED_DATA) { + { uintptr_t type = (uintptr_t)RTYPEDDATA(obj)->type; if (type & TYPED_DATA_EMBEDDED) { RUBY_DATA_FUNC dfree = ((const rb_data_type_t *)(type & TYPED_DATA_PTR_MASK))->function.dfree; @@ -1485,22 +1449,17 @@ make_io_zombie(void *objspace, VALUE obj) static bool rb_data_free(void *objspace, VALUE obj) { - void *data = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj); + void *data = RTYPEDDATA_GET_DATA(obj); if (data) { int free_immediately = false; void (*dfree)(void *); - if (RTYPEDDATA_P(obj)) { - free_immediately = (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0; - dfree = RTYPEDDATA_TYPE(obj)->function.dfree; - } - else { - dfree = RDATA(obj)->dfree; - } + free_immediately = (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0; + dfree = RTYPEDDATA_TYPE(obj)->function.dfree; if (dfree) { if (dfree == RUBY_DEFAULT_FREE) { - if (!RTYPEDDATA_P(obj) || !RTYPEDDATA_EMBEDDED_P(obj)) { + if (!RTYPEDDATA_EMBEDDED_P(obj)) { xfree(data); RB_DEBUG_COUNTER_INC(obj_data_xfree); } @@ -3512,13 +3471,12 @@ rb_gc_mark_children(void *objspace, VALUE obj) break; case T_DATA: { - bool typed_data = RTYPEDDATA_P(obj); - void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj); + void *const ptr = RTYPEDDATA_GET_DATA(obj); gc_mark_internal(RTYPEDDATA(obj)->fields_obj); if (ptr) { - if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) { + if (gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) { size_t *offset_list = TYPED_DATA_REFS_OFFSET_LIST(obj); for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) { @@ -3526,9 +3484,7 @@ rb_gc_mark_children(void *objspace, VALUE obj) } } else { - RUBY_DATA_FUNC mark_func = typed_data ? - RTYPEDDATA_TYPE(obj)->function.dmark : - RDATA(obj)->dmark; + RUBY_DATA_FUNC mark_func = RTYPEDDATA_TYPE(obj)->function.dmark; if (mark_func) (*mark_func)(ptr); } } @@ -4460,13 +4416,12 @@ rb_gc_update_object_references(void *objspace, VALUE obj) case T_DATA: /* Call the compaction callback, if it exists */ { - bool typed_data = RTYPEDDATA_P(obj); - void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj); + void *const ptr = RTYPEDDATA_GET_DATA(obj); UPDATE_IF_MOVED(objspace, RTYPEDDATA(obj)->fields_obj); if (ptr) { - if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) { + if (gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) { size_t *offset_list = TYPED_DATA_REFS_OFFSET_LIST(obj); for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) { @@ -4474,7 +4429,7 @@ rb_gc_update_object_references(void *objspace, VALUE obj) *ref = gc_location_internal(objspace, *ref); } } - else if (typed_data) { + else { RUBY_DATA_FUNC compact_func = RTYPEDDATA_TYPE(obj)->function.dcompact; if (compact_func) (*compact_func)(ptr); } diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h index 5ebeb2473e..d0a4dc7c83 100644 --- a/include/ruby/internal/core/rdata.h +++ b/include/ruby/internal/core/rdata.h @@ -42,31 +42,9 @@ #endif #define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f)) -#define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \ - RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \ - RBIMPL_ATTR_DEPRECATED(("by TypedData")) - -#define RBIMPL_MACRO_SELECT(x, y) x ## y -#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y) /** @endcond */ /** - * Convenient casting macro. - * - * @param obj An object, which is in fact an ::RData. - * @return The passed object casted to ::RData. - */ -#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj)) - -/** - * Convenient getter macro. - * - * @param obj An object, which is in fact an ::RData. - * @return The passed object's ::RData::data field. - */ -#define DATA_PTR(obj) RDATA(obj)->data - -/** * This is a value you can set to ::RData::dfree. Setting this means the data * was allocated using ::ruby_xmalloc() (or variants), and shall be freed using * ::ruby_xfree(). @@ -85,19 +63,6 @@ #define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0) /** - * @private - * - * @deprecated This macro once was a thing in the old days, but makes no sense - * any longer today. Exists here for backwards compatibility - * only. You can safely forget about it. - */ -#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() - -/* -#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func)) -*/ - -/** * This is the type of callbacks registered to ::RData. The argument is the * `data` field. */ @@ -106,264 +71,16 @@ typedef void (*RUBY_DATA_FUNC)(void*); /** * @deprecated * - * Old "untyped" user data. It has roughly the same usage as struct - * ::RTypedData, but lacked several features such as support for compaction GC. - * Use of this struct is not recommended any longer. If it is dead necessary, - * please inform the core devs about your usage. - * - * @internal - * - * @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded - * too many warnings in the core. Maybe we want to retry later... Just add - * deprecated document for now. - * - * RData shares its initial fields with struct ::RTypedData so the VM can handle - * per-object fields without checking whether a T_DATA object is typed or legacy. + * DO NOT USE: Obsolete "untyped" user data, that is remained only for + * the backward compatibility for some wrapper generator gems. */ struct RData { - - /** Basic part, including flags and class. */ struct RBasic basic; - - /** @internal Direct reference to the slots that hold instance variables, if any. */ VALUE fields_obj; - - /** @internal Padding where ::RTypedData stores its type, so both structs place data at the same offset. */ VALUE _reserved; - - /** Pointer to the actual C level struct that you want to wrap. */ void *data; - - /** - * This function is called when the object is experiencing GC marks. If it - * contains references to other Ruby objects, you need to mark them also. - * Otherwise GC will smash your data. - * - * @see rb_gc_mark() - * @warning This is called during GC runs. Object allocations are - * impossible at that moment (that is why GC runs). - */ RUBY_DATA_FUNC dmark; - - /** - * This function is called when the object is no longer used. You need to - * do whatever necessary to avoid memory leaks. - * - * @warning This is called during GC runs. Object allocations are - * impossible at that moment (that is why GC runs). - */ RUBY_DATA_FUNC dfree; }; -RBIMPL_SYMBOL_EXPORT_BEGIN() - -/** - * This is the primitive way to wrap an existing C struct into ::RData. - * - * @param[in] klass Ruby level class of the returning object. - * @param[in] datap Pointer to the target C struct. - * @param[in] dmark Mark function. - * @param[in] dfree Free function. - * @exception rb_eTypeError `klass` is not a class. - * @exception rb_eNoMemError Out of memory. - * @return An allocated object that wraps `datap`. - */ -VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); - -/** - * Identical to rb_data_object_wrap(), except it allocates a new data region - * internally instead of taking an existing one. The allocation is done using - * ruby_calloc(). Hence it makes no sense to pass anything other than - * ::RUBY_DEFAULT_FREE to the last argument. - * - * @param[in] klass Ruby level class of the returning object. - * @param[in] size Requested size of memory to allocate. - * @param[in] dmark Mark function. - * @param[in] dfree Free function. - * @exception rb_eTypeError `klass` is not a class. - * @exception rb_eNoMemError Out of memory. - * @return An allocated object that wraps a new `size` byte region. - */ -VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); - -RBIMPL_SYMBOL_EXPORT_END() - -/** - * Converts sval, a pointer to your struct, into a Ruby object. - * - * @param klass A ruby level class. - * @param mark Mark function. - * @param free Free function. - * @param sval A pointer to your struct. - * @exception rb_eTypeError `klass` is not a class. - * @exception rb_eNoMemError Out of memory. - * @return A created Ruby object. - */ -#define Data_Wrap_Struct(klass, mark, free, sval) \ - rb_data_object_wrap( \ - (klass), \ - (sval), \ - RBIMPL_DATA_FUNC(mark), \ - RBIMPL_DATA_FUNC(free)) - -/** - * @private - * - * This is an implementation detail of #Data_Make_Struct. People don't use it - * directly. - * - * @param result Variable name of created Ruby object. - * @param klass Ruby level class of the object. - * @param type Type name of the C struct. - * @param size Size of the C struct. - * @param mark Mark function. - * @param free Free function. - * @param sval Variable name of created C struct. - */ -#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \ - VALUE result = rb_data_object_zalloc( \ - (klass), \ - (size), \ - RBIMPL_DATA_FUNC(mark), \ - RBIMPL_DATA_FUNC(free)); \ - (sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \ - RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) - -/** - * Identical to #Data_Wrap_Struct, except it allocates a new data region - * internally instead of taking an existing one. The allocation is done using - * ruby_calloc(). Hence it makes no sense to pass anything other than - * ::RUBY_DEFAULT_FREE to the `free` argument. - * - * @param klass Ruby level class of the returning object. - * @param type Type name of the C struct. - * @param mark Mark function. - * @param free Free function. - * @param sval Variable name of created C struct. - * @exception rb_eTypeError `klass` is not a class. - * @exception rb_eNoMemError Out of memory. - * @return A created Ruby object. - */ -#ifdef HAVE_STMT_AND_DECL_IN_EXPR -#define Data_Make_Struct(klass, type, mark, free, sval) \ - RB_GNUC_EXTENSION({ \ - Data_Make_Struct0( \ - data_struct_obj, \ - klass, \ - type, \ - sizeof(type), \ - mark, \ - free, \ - sval); \ - data_struct_obj; \ - }) -#else -#define Data_Make_Struct(klass, type, mark, free, sval) \ - rb_data_object_make( \ - (klass), \ - RBIMPL_DATA_FUNC(mark), \ - RBIMPL_DATA_FUNC(free), \ - RBIMPL_CAST((void **)&(sval)), \ - sizeof(type)) -#endif - -/** - * Obtains a C struct from inside of a wrapper Ruby object. - * - * @param obj An instance of ::RData. - * @param type Type name of the C struct. - * @param sval Variable name of obtained C struct. - * @return Unwrapped C struct that `obj` holds. - */ -#define Data_Get_Struct(obj, type, sval) \ - ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj))) - -RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() -/** - * @private - * - * This is an implementation detail of rb_data_object_wrap(). People don't use - * it directly. - * - * @param[in] klass Ruby level class of the returning object. - * @param[in] ptr Pointer to the target C struct. - * @param[in] mark Mark function. - * @param[in] free Free function. - * @exception rb_eTypeError `klass` is not a class. - * @exception rb_eNoMemError Out of memory. - * @return An allocated object that wraps `datap`. - */ -static inline VALUE -rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free) -{ - return rb_data_object_wrap(klass, ptr, mark, free); -} - -/** - * @private - * - * This is an implementation detail of #Data_Get_Struct. People don't use it - * directly. - * - * @param[in] obj An instance of ::RData. - * @return Unwrapped C struct that `obj` holds. - */ -static inline void * -rb_data_object_get(VALUE obj) -{ - Check_Type(obj, RUBY_T_DATA); - return DATA_PTR(obj); -} - -RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() -/** - * @private - * - * This is an implementation detail of #Data_Get_Struct. People don't use it - * directly. - * - * @param[in] obj An instance of ::RData. - * @return Unwrapped C struct that `obj` holds. - */ -static inline void * -rb_data_object_get_warning(VALUE obj) -{ - return rb_data_object_get(obj); -} - -/** - * This is an implementation detail of #Data_Make_Struct. People don't use it - * directly. - * - * @param[in] klass Ruby level class of the returning object. - * @param[in] mark_func Mark function. - * @param[in] free_func Free function. - * @param[in] datap Variable of created C struct. - * @param[in] size Requested size of allocation. - * @exception rb_eTypeError `klass` is not a class. - * @exception rb_eNoMemError Out of memory. - * @return A created Ruby object. - * @post `*datap` holds the created C struct. - */ -static inline VALUE -rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size) -{ - Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap); - return result; -} - -/** @cond INTERNAL_MACRO */ -#define rb_data_object_wrap_0 rb_data_object_wrap -#define rb_data_object_wrap_1 rb_data_object_wrap_warning -#define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */ -#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_2, RUBY_UNTYPED_DATA_WARNING) -#define rb_data_object_get_0 rb_data_object_get -#define rb_data_object_get_1 rb_data_object_get_warning -#define rb_data_object_get_2 rb_data_object_get_ /* Used here vvvv */ -#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_2, RUBY_UNTYPED_DATA_WARNING) -#define rb_data_object_make_0 rb_data_object_make -#define rb_data_object_make_1 rb_data_object_make_warning -#define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */ -#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING) -/** @endcond */ #endif /* RBIMPL_RDATA_H */ diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h index 0b189c7ef8..eb8313f180 100644 --- a/include/ruby/internal/core/rtypeddata.h +++ b/include/ruby/internal/core/rtypeddata.h @@ -206,11 +206,6 @@ rbimpl_typeddata_flags { RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */ /** - * This flag is used to distinguish RTypedData from deprecated RData objects. - */ - RUBY_TYPED_FL_IS_TYPED_DATA = RUBY_FL_USERPRIV0, - - /** * This flag determines whether marking and compaction should be carried out * using the dmark/dcompact callback functions or whether we should mark * declaratively using a list of references defined inside the data struct we're wrapping @@ -409,6 +404,22 @@ RBIMPL_STATIC_ASSERT(fields_obj_in_rdata, offsetof(struct RData, fields_obj) == RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data)); #endif +/** + * Convenient casting macro for backward compatibility. + * + * @param obj An object, which is in fact an ::RData. + * @return The passed object casted to ::RData. + */ +#define RDATA(obj) RTYPEDDATA(obj) + +/** + * Convenient casting macro for backward compatibility. + * + * @param obj An object, which is in fact an ::RData. + * @return The passed object's ::RTypedData::data field. + */ +#define DATA_PTR(obj) RTYPEDDATA_DATA(obj) + RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((3)) /** @@ -621,27 +632,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implementation detail of Check_Type(). People don't use it - * directly. - * - * @param[in] obj Object in question - * @retval true `obj` is an instance of ::RTypedData. - * @retval false `obj` is an instance of ::RData. - * @pre `obj` must be a Ruby object of ::RUBY_T_DATA. - */ -static inline bool -rbimpl_rtypeddata_p(VALUE obj) -{ - return FL_TEST_RAW(obj, RUBY_TYPED_FL_IS_TYPED_DATA); -} - -RBIMPL_ATTR_PURE() -RBIMPL_ATTR_ARTIFICIAL() -/** - * @private - * - * Identical to rbimpl_rtypeddata_p(), except it is allowed to call on non-data - * objects. + * Checks whether the passed object is ::RTypedData. * * This is an implementation detail of inline functions defined in this file. * People don't use it directly. @@ -653,17 +644,16 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool rbimpl_obj_typeddata_p(VALUE obj) { - return RB_TYPE_P(obj, RUBY_T_DATA) && rbimpl_rtypeddata_p(obj); + return RB_TYPE_P(obj, RUBY_T_DATA); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * Checks whether the passed object is ::RTypedData or ::RData. + * Checks whether the passed object is ::RTypedData. * * @param[in] obj Object in question - * @retval true `obj` is an instance of ::RTypedData. - * @retval false `obj` is an instance of ::RData. + * @retval true * @pre `obj` must be a Ruby object of ::RUBY_T_DATA. */ static inline bool @@ -671,7 +661,7 @@ RTYPEDDATA_P(VALUE obj) { RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false)); - return rbimpl_rtypeddata_p(obj); + return true; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() @@ -752,7 +742,6 @@ static inline VALUE rbimpl_check_external_typeddata(VALUE obj) { RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false)); - RUBY_ASSERT(rbimpl_obj_typeddata_p(obj)); RUBY_ASSERT(!rbimpl_typeddata_embedded_p(obj)); return obj; } diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h index b47d8afb97..77cb38bc7d 100644 --- a/include/ruby/internal/value_type.h +++ b/include/ruby/internal/value_type.h @@ -410,14 +410,6 @@ RB_TYPE_P(VALUE obj, enum ruby_value_type t) #endif /** @endcond */ -RBIMPL_ATTR_PURE() -RBIMPL_ATTR_ARTIFICIAL() -/** - * @private - * Defined in ruby/internal/core/rtypeddata.h - */ -static inline bool rbimpl_rtypeddata_p(VALUE obj); - RBIMPL_ATTR_ARTIFICIAL() /** * Identical to RB_TYPE_P(), except it raises exceptions on predication @@ -432,19 +424,11 @@ RBIMPL_ATTR_ARTIFICIAL() static inline void Check_Type(VALUE v, enum ruby_value_type t) { + /* Typed data is not simple `T_DATA`, see `rb_check_type` */ + RUBY_ASSERT_ALWAYS(t != RUBY_T_DATA); if (RB_UNLIKELY(! RB_TYPE_P(v, t))) { - goto unexpected_type; + rb_unexpected_type(v, RBIMPL_CAST((int)t)); } - else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) { - /* Typed data is not simple `T_DATA`, see `rb_check_type` */ - goto unexpected_type; - } - else { - return; - } - - unexpected_type: - rb_unexpected_type(v, RBIMPL_CAST((int)t)); } #endif /* RBIMPL_VALUE_TYPE_H */ diff --git a/include/ruby/random.h b/include/ruby/random.h index 740be6bdad..3b63a23334 100644 --- a/include/ruby/random.h +++ b/include/ruby/random.h @@ -333,7 +333,6 @@ static inline const rb_random_interface_t * rb_rand_if(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(obj, T_DATA)); - RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj)); RUBY_ASSERT(rb_typeddata_is_kind_of(obj, &rb_random_data_type)); const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj); const void *ret = t->data; diff --git a/misc/lldb_rb/utils.py b/misc/lldb_rb/utils.py index e0cb609b1a..a2bcedc328 100644 --- a/misc/lldb_rb/utils.py +++ b/misc/lldb_rb/utils.py @@ -236,29 +236,20 @@ class RbInspector(LLDBInterface): elif rval.is_type("RUBY_T_DATA"): tRTypedData = self.target.FindFirstType("struct RTypedData").GetPointerType() val = val.Cast(tRTypedData) - is_typed_data = self.ruby_globals.get("RUBY_TYPED_FL_IS_TYPED_DATA", None) - if is_typed_data: - typed = rval.flags & is_typed_data - else: - typed = val.GetValueForExpressionPath("->typed_flag").GetValueAsUnsigned() == 1 - - if typed: - type = val.GetValueForExpressionPath("->type").GetValueAsUnsigned() - embed = (type & 1) - if embed: - flaginfo += "[EMBED] " - type = self.frame.EvaluateExpression("(rb_data_type_t *)%0#x" % (type & ~1)) - print("T_DATA: %s%s" % - (flaginfo, type.GetValueForExpressionPath("->wrap_struct_name")), - file=self.result) - print("%s", type.Dereference(), file=self.result) - ptr = val.GetValueForExpressionPath("->data") - if embed: - ptr = ptr.AddressOf() - self._append_expression("(void *)%0#x" % ptr.GetValueAsUnsigned()) - else: - print("T_DATA:", file=self.result) - self._append_expression("*(struct RData *) %0#x" % val.GetValueAsUnsigned()) + + type = val.GetValueForExpressionPath("->type").GetValueAsUnsigned() + embed = (type & 1) + if embed: + flaginfo += "[EMBED] " + type = self.frame.EvaluateExpression("(rb_data_type_t *)%0#x" % (type & ~1)) + print("T_DATA: %s%s" % + (flaginfo, type.GetValueForExpressionPath("->wrap_struct_name")), + file=self.result) + print("%s", type.Dereference(), file=self.result) + ptr = val.GetValueForExpressionPath("->data") + if embed: + ptr = ptr.AddressOf() + self._append_expression("(void *)%0#x" % ptr.GetValueAsUnsigned()) elif rval.is_type("RUBY_T_IMEMO"): imemo_type = ((rval.flags >> self.ruby_globals["RUBY_FL_USHIFT"]) @@ -1451,7 +1451,7 @@ allow_frozen_shareable_p(VALUE obj) if (!RB_TYPE_P(obj, T_DATA)) { return true; } - else if (RTYPEDDATA_P(obj)) { + else { const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE) { return true; diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h index 7107bead90..5a92645785 100644 --- a/spec/ruby/optional/capi/ext/rubyspec.h +++ b/spec/ruby/optional/capi/ext/rubyspec.h @@ -35,6 +35,10 @@ (RUBY_API_VERSION_MAJOR == (major) && RUBY_API_VERSION_MINOR < (minor))) #define RUBY_VERSION_SINCE(major,minor) (!RUBY_VERSION_BEFORE(major, minor)) +#if RUBY_VERSION_SINCE(4, 1) +#define RUBY_VERSION_IS_4_1 +#endif + #if RUBY_VERSION_SINCE(4, 0) #define RUBY_VERSION_IS_4_0 #endif diff --git a/spec/ruby/optional/capi/ext/typed_data_spec.c b/spec/ruby/optional/capi/ext/typed_data_spec.c index 221f1c8ac4..c6fcfa3bc8 100644 --- a/spec/ruby/optional/capi/ext/typed_data_spec.c +++ b/spec/ruby/optional/capi/ext/typed_data_spec.c @@ -106,6 +106,7 @@ VALUE sws_typed_wrap_struct(VALUE self, VALUE val) { return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar); } +#ifndef RUBY_VERSION_IS_4_1 #undef RUBY_UNTYPED_DATA_WARNING #define RUBY_UNTYPED_DATA_WARNING 0 VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) { @@ -113,6 +114,7 @@ VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) { *data = FIX2INT(val); return Data_Wrap_Struct(rb_cObject, NULL, free, data); } +#endif VALUE sws_typed_get_struct(VALUE self, VALUE obj) { struct sample_typed_wrapped_struct* bar; @@ -173,9 +175,11 @@ VALUE sws_typed_rb_check_typeddata_different_type(VALUE self, VALUE obj) { return rb_check_typeddata(obj, &sample_typed_wrapped_struct_other_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse; } +#ifndef RUBY_VERSION_IS_4_1 VALUE sws_typed_RTYPEDDATA_P(VALUE self, VALUE obj) { return RTYPEDDATA_P(obj) ? Qtrue : Qfalse; } +#endif void Init_typed_data_spec(void) { VALUE cls = rb_define_class("CApiAllocTypedSpecs", rb_cObject); @@ -183,7 +187,9 @@ void Init_typed_data_spec(void) { rb_define_method(cls, "typed_wrapped_data", sdaf_typed_get_struct, 0); cls = rb_define_class("CApiWrappedTypedStructSpecs", rb_cObject); rb_define_method(cls, "typed_wrap_struct", sws_typed_wrap_struct, 1); +#ifndef RUBY_VERSION_IS_4_1 rb_define_method(cls, "untyped_wrap_struct", sws_untyped_wrap_struct, 1); +#endif rb_define_method(cls, "typed_get_struct", sws_typed_get_struct, 1); rb_define_method(cls, "typed_get_struct_other", sws_typed_get_struct_different_type, 1); rb_define_method(cls, "typed_get_struct_parent", sws_typed_get_struct_parent_type, 1); @@ -194,10 +200,11 @@ void Init_typed_data_spec(void) { rb_define_method(cls, "rb_check_typeddata_same_type", sws_typed_rb_check_typeddata_same_type, 1); rb_define_method(cls, "rb_check_typeddata_same_type_parent", sws_typed_rb_check_typeddata_same_type_parent, 1); rb_define_method(cls, "rb_check_typeddata_different_type", sws_typed_rb_check_typeddata_different_type, 1); +#ifndef RUBY_VERSION_IS_4_1 rb_define_method(cls, "RTYPEDDATA_P", sws_typed_RTYPEDDATA_P, 1); +#endif } #ifdef __cplusplus } #endif - diff --git a/spec/ruby/optional/capi/typed_data_spec.rb b/spec/ruby/optional/capi/typed_data_spec.rb index 8eaf7751ba..376cfe417f 100644 --- a/spec/ruby/optional/capi/typed_data_spec.rb +++ b/spec/ruby/optional/capi/typed_data_spec.rb @@ -86,15 +86,17 @@ describe "CApiWrappedTypedStruct" do end end - describe "RTYPEDDATA_P" do - it "returns true for a typed data" do - a = @s.typed_wrap_struct(1024) - @s.RTYPEDDATA_P(a).should == true - end + ruby_version_is ""..."4.1" do + describe "RTYPEDDATA_P" do + it "returns true for a typed data" do + a = @s.typed_wrap_struct(1024) + @s.RTYPEDDATA_P(a).should == true + end - it "returns false for an untyped data object" do - a = @s.untyped_wrap_struct(1024) - @s.RTYPEDDATA_P(a).should == false + it "returns false for an untyped data object" do + a = @s.untyped_wrap_struct(1024) + @s.RTYPEDDATA_P(a).should == false + end end end end diff --git a/test/json/json_ryu_fallback_test.rb b/test/json/json_ryu_fallback_test.rb index 152de7e360..a61b3e668d 100644 --- a/test/json/json_ryu_fallback_test.rb +++ b/test/json/json_ryu_fallback_test.rb @@ -179,5 +179,13 @@ class JSONRyuFallbackTest < Test::Unit::TestCase assert_equal(-0.0, JSON.parse("-99999999999999999e-4294967296")) assert_equal(-Float::INFINITY, JSON.parse("-1e4294967295")) assert_equal(-Float::INFINITY, JSON.parse("-1e4294967297")) + + assert_equal(Float::INFINITY, JSON.parse("1e9223372036854775808")) + assert_equal(Float::INFINITY, JSON.parse("1e9999999999999999999")) + assert_equal(Float::INFINITY, JSON.parse("1e18446744073709551616")) + assert_equal(Float::INFINITY, JSON.parse("1e10000000000000000000")) + assert_equal(Float::INFINITY, JSON.parse("1e184467440737095516160")) + assert_equal 0.0, JSON.parse("1e-18446744073709551615") + assert_equal 0.0, JSON.parse("1e-9223372036854775809") end end diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb index ce2c690fc1..8d0ac63c41 100644 --- a/test/rubygems/test_gem_safe_yaml.rb +++ b/test/rubygems/test_gem_safe_yaml.rb @@ -138,7 +138,11 @@ class TestGemSafeYAML < Gem::TestCase depth = Gem::YAMLSerializer::Parser::MAX_NESTING_DEPTH + 1 yaml = "x: " + ("[" * depth) + "a" + ("]" * depth) + "\n" - assert_raise(Psych::SyntaxError) do + expected = [Psych::SyntaxError] + # JRuby's JVM stack overflows before the Ruby-level nesting cap fires. + expected << ::Java::JavaLang::StackOverflowError if RUBY_ENGINE == "jruby" + + assert_raise(*expected) do Gem::YAMLSerializer.load(yaml, permitted_classes: []) end end diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs index dad29087be..f6f43fd5e2 100644 --- a/zjit/src/cruby_bindings.inc.rs +++ b/zjit/src/cruby_bindings.inc.rs @@ -347,7 +347,6 @@ pub const RUBY_TYPED_FREE_IMMEDIATELY: rbimpl_typeddata_flags = 1; pub const RUBY_TYPED_EMBEDDABLE: rbimpl_typeddata_flags = 2; pub const RUBY_TYPED_FROZEN_SHAREABLE: rbimpl_typeddata_flags = 256; pub const RUBY_TYPED_WB_PROTECTED: rbimpl_typeddata_flags = 32; -pub const RUBY_TYPED_FL_IS_TYPED_DATA: rbimpl_typeddata_flags = 64; pub const RUBY_TYPED_DECL_MARKING: rbimpl_typeddata_flags = 16384; pub type rbimpl_typeddata_flags = u32; pub type rb_event_flag_t = u32; |
