mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
merge revision(s) bccec7fb46
, 5f8ebcada0
, e13575bb79
, 4adcfc8cd7
: [Backport #19584]
Fix crash in rb_gc_register_address [Bug #19584] Some C extensions pass a pointer to a global variable to rb_gc_register_address. However, if a GC is triggered inside of rb_gc_register_address, then the object could get swept since it does not exist on the stack. [Bug #19584] Register global variable address before assignment [Bug #19584] Register global variables before assignment [Bug #19584] [DOC] Tweek description of `rb_gc_register_address`
This commit is contained in:
parent
2c49513291
commit
f89a334b55
6 changed files with 30 additions and 13 deletions
13
gc.c
13
gc.c
|
@ -9281,10 +9281,23 @@ rb_gc_register_address(VALUE *addr)
|
||||||
rb_objspace_t *objspace = &rb_objspace;
|
rb_objspace_t *objspace = &rb_objspace;
|
||||||
struct gc_list *tmp;
|
struct gc_list *tmp;
|
||||||
|
|
||||||
|
VALUE obj = *addr;
|
||||||
|
|
||||||
tmp = ALLOC(struct gc_list);
|
tmp = ALLOC(struct gc_list);
|
||||||
tmp->next = global_list;
|
tmp->next = global_list;
|
||||||
tmp->varptr = addr;
|
tmp->varptr = addr;
|
||||||
global_list = tmp;
|
global_list = tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because some C extensions have assignment-then-register bugs,
|
||||||
|
* we guard `obj` here so that it would not get swept defensively.
|
||||||
|
*/
|
||||||
|
RB_GC_GUARD(obj);
|
||||||
|
if (0 && !SPECIAL_CONST_P(obj)) {
|
||||||
|
rb_warn("Object is assigned to registering address already: %"PRIsVALUE,
|
||||||
|
rb_obj_class(obj));
|
||||||
|
rb_print_backtrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -26,10 +26,15 @@
|
||||||
RBIMPL_SYMBOL_EXPORT_BEGIN()
|
RBIMPL_SYMBOL_EXPORT_BEGIN()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the garbage collector that `valptr` points to a live Ruby object that
|
* Inform the garbage collector that the global or static variable pointed by
|
||||||
* should not be moved. Note that extensions should use this API on global
|
* `valptr` stores a live Ruby object that should not be moved. Note that
|
||||||
* constants instead of assuming constants defined in Ruby are always alive.
|
* extensions should use this API on global constants instead of assuming
|
||||||
* Ruby code can remove global constants.
|
* constants defined in Ruby are always alive. Ruby code can remove global
|
||||||
|
* constants.
|
||||||
|
*
|
||||||
|
* Because this registration itself has a possibility to trigger a GC, this
|
||||||
|
* function must be called before any GC-able objects is assigned to the
|
||||||
|
* address pointed by `valptr`.
|
||||||
*/
|
*/
|
||||||
void rb_gc_register_address(VALUE *valptr);
|
void rb_gc_register_address(VALUE *valptr);
|
||||||
|
|
||||||
|
|
7
io.c
7
io.c
|
@ -15547,13 +15547,12 @@ Init_IO(void)
|
||||||
rb_gvar_ractor_local("$>");
|
rb_gvar_ractor_local("$>");
|
||||||
rb_gvar_ractor_local("$stderr");
|
rb_gvar_ractor_local("$stderr");
|
||||||
|
|
||||||
rb_stdin = rb_io_prep_stdin();
|
|
||||||
rb_stdout = rb_io_prep_stdout();
|
|
||||||
rb_stderr = rb_io_prep_stderr();
|
|
||||||
|
|
||||||
rb_global_variable(&rb_stdin);
|
rb_global_variable(&rb_stdin);
|
||||||
|
rb_stdin = rb_io_prep_stdin();
|
||||||
rb_global_variable(&rb_stdout);
|
rb_global_variable(&rb_stdout);
|
||||||
|
rb_stdout = rb_io_prep_stdout();
|
||||||
rb_global_variable(&rb_stderr);
|
rb_global_variable(&rb_stderr);
|
||||||
|
rb_stderr = rb_io_prep_stderr();
|
||||||
|
|
||||||
orig_stdout = rb_stdout;
|
orig_stdout = rb_stdout;
|
||||||
orig_stderr = rb_stderr;
|
orig_stderr = rb_stderr;
|
||||||
|
|
2
ruby.c
2
ruby.c
|
@ -647,8 +647,8 @@ ruby_init_loadpath(void)
|
||||||
# endif
|
# endif
|
||||||
rb_obj_hide(selfpath);
|
rb_obj_hide(selfpath);
|
||||||
OBJ_FREEZE_RAW(selfpath);
|
OBJ_FREEZE_RAW(selfpath);
|
||||||
rb_libruby_selfpath = selfpath;
|
|
||||||
rb_gc_register_address(&rb_libruby_selfpath);
|
rb_gc_register_address(&rb_libruby_selfpath);
|
||||||
|
rb_libruby_selfpath = selfpath;
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ static VALUE get_registered_before_rb_global_variable(VALUE self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE gc_spec_rb_gc_register_address(VALUE self) {
|
static VALUE gc_spec_rb_gc_register_address(VALUE self) {
|
||||||
rb_gc_register_address_outside_init = rb_str_new_cstr("rb_gc_register_address() outside Init_");
|
|
||||||
rb_gc_register_address(&rb_gc_register_address_outside_init);
|
rb_gc_register_address(&rb_gc_register_address_outside_init);
|
||||||
|
rb_gc_register_address_outside_init = rb_str_new_cstr("rb_gc_register_address() outside Init_");
|
||||||
return rb_gc_register_address_outside_init;
|
return rb_gc_register_address_outside_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,14 +67,14 @@ static VALUE gc_spec_rb_gc_register_mark_object(VALUE self, VALUE obj) {
|
||||||
|
|
||||||
void Init_gc_spec(void) {
|
void Init_gc_spec(void) {
|
||||||
VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject);
|
VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject);
|
||||||
registered_tagged_value = INT2NUM(10);
|
|
||||||
registered_reference_value = rb_str_new2("Globally registered data");
|
|
||||||
|
|
||||||
rb_gc_register_address(®istered_tagged_value);
|
rb_gc_register_address(®istered_tagged_value);
|
||||||
rb_gc_register_address(®istered_reference_value);
|
rb_gc_register_address(®istered_reference_value);
|
||||||
rb_gc_register_address(®istered_before_rb_gc_register_address);
|
rb_gc_register_address(®istered_before_rb_gc_register_address);
|
||||||
rb_global_variable(®istered_before_rb_global_variable);
|
rb_global_variable(®istered_before_rb_global_variable);
|
||||||
|
|
||||||
|
registered_tagged_value = INT2NUM(10);
|
||||||
|
registered_reference_value = rb_str_new2("Globally registered data");
|
||||||
registered_before_rb_gc_register_address = rb_str_new_cstr("registered before rb_gc_register_address()");
|
registered_before_rb_gc_register_address = rb_str_new_cstr("registered before rb_gc_register_address()");
|
||||||
registered_before_rb_global_variable = rb_str_new_cstr("registered before rb_global_variable()");
|
registered_before_rb_global_variable = rb_str_new_cstr("registered before rb_global_variable()");
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||||
#define RUBY_VERSION_TEENY 7
|
#define RUBY_VERSION_TEENY 7
|
||||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||||
#define RUBY_PATCHLEVEL 258
|
#define RUBY_PATCHLEVEL 259
|
||||||
|
|
||||||
#include "ruby/version.h"
|
#include "ruby/version.h"
|
||||||
#include "ruby/internal/abi.h"
|
#include "ruby/internal/abi.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue