| Age | Commit message (Collapse) | Author |
|
|
|
* fixes partial copy of objects in GC root array (due to missing `* sizeof(mrb_value)`)
* restores the behavior that permitted an unregistered object to be used as an argument
|
|
Reported by https://hackerone.com/haquaman
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when multiple mrb_gc_register() were called for the same object
|
|
GitHub: fix #3122
It reverts #3126. #3126 fixes the segmentation fault but generates
broken backtrace.
This change fixes the segmentation fault and generates correct
backtrace. The strategy of this change is "generating backtrace while
irep is alive".
/tmp/test.rb:
def gen
e0 = nil
begin
1.times {
raise 'foobar'
}
rescue => e
e0 = e
end
e0
end
e = gen
GC.start
gen
GC.start
puts e.backtrace.join("\n")
Run:
% bin/mruby /tmp/test.rb
/tmp/test.rb:5:in Object.gen
/home/kou/work/ruby/mruby.kou/mrblib/numeric.rb:77:in Integral#times
/tmp/test.rb:4:in Object.gen
/tmp/test.rb:13
FYI:
% ruby -v /tmp/test.rb
ruby 2.3.0p0 (2015-12-25) [x86_64-linux-gnu]
/tmp/test.rb:5:in `block in gen'
/tmp/test.rb:4:in `times'
/tmp/test.rb:4:in `gen'
/tmp/test.rb:13:in `<main>'
|
|
|
|
Think about the following Ruby script:
segv.rb:
begin
lambda do
lambda do
"x" * 1000 # NoMemoryError
end.call
end.call
rescue
raise
end
If memory can't allocate after `"x" * 1000`, mruby crashes.
Because L_RAISE: block in mrb_vm_exec() calls mrb_env_unshare() via
cipop() and mrb_env_unshare() uses allocated memory without NULL check:
L_RAISE: block:
L_RAISE:
// ...
while (ci[0].ridx == ci[-1].ridx) {
cipop(mrb);
// ...
}
cipop():
static void
cipop(mrb_state *mrb)
{
struct mrb_context *c = mrb->c;
if (c->ci->env) {
mrb_env_unshare(mrb, c->ci->env);
}
c->ci--;
}
mrb_env_unshare():
MRB_API void
mrb_env_unshare(mrb_state *mrb, struct REnv *e)
{
size_t len = (size_t)MRB_ENV_STACK_LEN(e);
// p is NULL in this case
mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
MRB_ENV_UNSHARE_STACK(e);
if (len > 0) {
stack_copy(p, e->stack, len); // p is NULL but used. It causes SEGV.
}
e->stack = p;
mrb_write_barrier(mrb, (struct RBasic *)e);
}
To solve the SEGV, this change always raises NoMemoryError even when
realloc() is failed after the first NoMemoryError in
mrb_realloc(). mrb_unv_unshare() doesn't need to check NULL with this
change.
But it causes infinite loop in the following while:
L_RAISE:
// ...
while (ci[0].ridx == ci[-1].ridx) {
cipop(mrb);
// ...
}
Because cipop() never pops ci.
This change includes cipop() change. The change pops ci even when
mrb_unv_unshare() is failed by NoMemoryError.
This case can be reproduced by the following program:
#include <stdlib.h>
#include <mruby.h>
#include <mruby/compile.h>
static void *
allocf(mrb_state *mrb, void *ptr, size_t size, void *ud)
{
static mrb_bool always_fail = FALSE;
if (size == 1001) {
always_fail = TRUE;
}
if (always_fail) {
return NULL;
}
if (size == 0) {
free(ptr);
return NULL;
} else {
return realloc(ptr, size);
}
}
int
main(int argc, char **argv)
{
mrb_state *mrb;
mrbc_context *c;
FILE *file;
mrb = mrb_open_allocf(allocf, NULL);
c = mrbc_context_new(mrb);
file = fopen(argv[1], "r");
mrb_load_file_cxt(mrb, file, c);
fclose(file);
mrbc_context_free(mrb, c);
mrb_close(mrb);
return EXIT_SUCCESS;
}
Try the following command lines:
% cc -I include -L build/host/lib -O0 -g3 -o no-memory no-memory.c -lmruby -lm
% ./no-memory segv.rb
|
|
|
|
|
|
The return type of the mrb_objspace_each_objects function is void.
So this return statement with an expression is unnecessary and
also violates a constraint. From C99 §6.8.6.4:
>A return statement with an expression shall not appear
>in a function whose return type is void.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
some routines need to refer mruby objects (e.g. callbacks), in that case
you have to protect your objects from garbage collection. the new functions
mrb_gc_register() keeps those objects from GC. you have to remove your
objects using mrb_gc_unregister() when your C routines use mruby objects
any longer, otherwise objects will leak.
|
|
Based on the gc patch by ko1
https://github.com/ruby/ruby/commit/5922c954614e5947a548780bb3b894626affe6dd
|
|
|
|
|
|
Add a missing space after ",".
|
|
|
|
|
|
|
|
|
|
Rename GC_STATE_NONE GC_STATE_ROOT
|
|
|
|
|
|
|
|
|
|
suzukaze-add-gc-docs
|
|
|
|
|
|
Those warnings are not enabled by default,
but getting rid of them doesn't hurt.
|
|
|
|
|
|
|
|
|
|
Add field `allocf_ud` to replace current `ud`.
|
|
|
|
Since some use it as `mrb_state` associated user data.
|
|
|
|
|
|
|