| Age | Commit message (Collapse) | Author |
|
But #3421 still cause stack overflow error due to infinite recursion.
To prevent overflow, we need to add different stack depth check.
|
|
This issue was reported by https://hackerone.com/d4nny
|
|
The issue was reported by https://hackerone.com/titanous
|
|
There's incompatibility left for mruby.
When you return from `ensure` clause, mruby simply ignores the return
value. CRuby returns from the method squashing the exception raised.
```
def f
no_such_method() # NoMethodError
ensure
return 22
end
p f() # CRuby prints `22`
```
|
|
OP_RETURN accesses ci[1]->stackent that might be broken; fix #3442
|
|
|
|
|
|
Dinko Galetic and Denis Kasak reported the issue and the fix.
(via https://hackerone.com/dgaletic).
|
|
Now `eval()` can call Fiber.yield etc.
|
|
|
|
This issue was reported by https://hackerone.com/ston3
|
|
This issue was reported by https://hackerone.com/titanous
|
|
|
|
|
|
This issue was reported by https://hackerone.com/ssarong
|
|
This issue was original reported by https://hackerone.com/icanthack
https://hackerone.com/titanous suggested the solution.
`regs` may be reallocated in the function call.
|
|
close #3389
This issue was reported by https://hackerone.com/ston3
|
|
|
|
The issue was reported by https://hackerone.com/ston3
|
|
|
|
Fix stack move segfaulting in OP_ARYCAT
|
|
bouk-method-missing-segfault
|
|
Reported by https://hackerone.com/haquaman
Testcase (couldn't get it to work as a test):
def nil.b
b *nil
end
nil.b
|
|
Reported by @charliesome
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Fix method name in top-level
- Fix SEGV when call Exception#backtrace if callinfo over CALLINFO_INIT_SIZE(32)
|
|
|
|
|
|
d4ee409ae912dec6eb719a5727da4566f817d9d8 should remove this line.
|
|
See https://github.com/mruby/mruby/pull/3142#issuecomment-201138873
|
|
|
|
mrb_vm_define_class() may realloc() mrb->c->stack because it calls
mrb_funcall() for inherited hook. If mrb->c->stack is realloc()-ed, regs
refers orphan address.
|
|
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
|
|
|
|
|
|
|
|
mrb_funcall(); close #3056
|
|
|
|
GitHub: fix #2902, #2917
The current implementation traverses stack to retrieve backtrace. But
stack will be changed when some operations are occurred. It means that
backtrace may be broken after some operations.
This change (1) saves the minimum information to retrieve backtrace when
exception is raised and (2) restores backtrace from the minimum
information when backtrace is needed. It reduces overhead for creating
backtrace Ruby objects.
The space for the minimum information is reused by multiple
exceptions. So memory allocation isn't occurred for each exception.
|
|
|
|
changes:
* rename DISABLE_STDIO -> MRB_DISABLE_STDIO
* rename ENABLE_DEBUG -> MRB_ENABLE_DEBUG_HOOK
* no more opposite macro definitions (e.g. ENABLE_STDIO, DISABLE_DEBUG).
* rewrite above macro references throughout the code.
* update documents
|
|
|
|
#3000
|
|
|