Commit Graph

349 Commits

Author SHA1 Message Date
yuri c9d4d96872 surpress warning when MRB_DISABLE_STDIO 2016-09-06 22:41:50 +09:00
ksss a5c2e95b10 Should clear method name
- Fix method name in top-level
- Fix SEGV when call Exception#backtrace if callinfo over CALLINFO_INIT_SIZE(32)
2016-09-05 21:58:08 +09:00
ksss 9dc820590f Should raise LocalJumpError when no block given 2016-07-14 13:03:25 +09:00
cremno 7453a5dfea use mrb_int_mul_overflow() 2016-05-10 19:12:02 +02:00
Kouhei Sutou 51cc35dc09 Remove needless assignment
d4ee409ae9 should remove this line.
2016-05-09 14:05:51 +09:00
Kenji Okimoto d4ee409ae9 Use stack directly
See https://github.com/mruby/mruby/pull/3142#issuecomment-201138873
2016-04-27 10:18:13 +09:00
Yukihiro "Matz" Matsumoto ae5b5ce575 vm.c: mrb_hash_set() may reallocate VM stack; close #3133 2016-04-11 14:11:44 +09:00
Kouhei Sutou c69cba2ad9 Add missing regs update
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.
2016-03-25 00:25:48 +09:00
Kouhei Sutou 1d84b3205a Fix SEGV on re-raising NoMemoryError
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
2016-01-19 16:37:42 +09:00
Yukihiro "Matz" Matsumoto f7afe1d82a change mrb_run related API names; compatibility macros provided 2016-01-07 22:36:29 +09:00
Yukihiro "Matz" Matsumoto aec825a64c stack_extend before eval_under() 2016-01-04 10:22:38 +09:00
Yukihiro "Matz" Matsumoto aa1f668b80 instance_eval should pass the receiver as a block parameter; close #3029 2016-01-02 22:01:00 +09:00
Yukihiro "Matz" Matsumoto bd462c5edc mruby-fiber: fiber_switch() to use nesting VM when it's called from C API or mrb_funcall(); close #3056 2016-01-02 13:48:45 +09:00
Yukihiro "Matz" Matsumoto 3531fe179c GC must scan env from fibers even when it's not yet copied to heap; fix #3063 2015-12-31 00:11:37 +09:00
Kouhei Sutou a561bdb25f Support backtrace after method calls
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.
2015-12-29 20:36:12 +09:00
Yukihiro "Matz" Matsumoto 5c405dea3d include changed from by quotes ("") to by brackets (<>); close #3032 2015-11-27 17:48:23 +09:00
Yukihiro "Matz" Matsumoto 4440566b95 DISABLE_STDIO/ENABLE_DEBUG macros to rename; close #3014
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
2015-11-17 07:30:34 +09:00
Yukihiro "Matz" Matsumoto d3b323cf2f PR #2521 did not work for singleton classes for non-class objects; fix #3003 2015-11-07 15:51:00 +09:00
Yukihiro "Matz" Matsumoto 614927447a mrb_str_concat() may call VM resursively thus may reallocate VM stack; close #3000 2015-10-27 01:06:15 +09:00
furunkel 3ab2f9371e Clean up GC code 2015-10-19 22:29:43 +02:00
Yukihiro "Matz" Matsumoto 6ddd79fd0e ensure must not be called before rescue; fix #2933 2015-09-02 21:46:51 +09:00
Yukihiro "Matz" Matsumoto 5af770cd59 prevent out-of-bounds ensure clause access; fix #2910 2015-08-10 11:41:01 +09:00
Yukihiro "Matz" Matsumoto f0040b5371 vm: execute ensure without exception at the top of the fiber; fix #2904 2015-07-30 16:46:31 +09:00
Yukihiro "Matz" Matsumoto 89ebb0c4f1 vm: execute ensure at the top of the fiber; fix #2903 2015-07-30 16:45:31 +09:00
Yukihiro "Matz" Matsumoto 9c311ddc93 refactor mrb_bob_missing to share raising NoMethodError code; fix #2878
Note: arguments of mrb_no_method_error() has changed. You need to replace
3rd and 4th argument (say n, argv) to mrb_ary_new_from_values(mrb, n, argv).
2015-07-13 11:07:59 +09:00
Yukihiro "Matz" Matsumoto 40252169fc method_missing definition may be undefined; fix #2878 2015-07-07 10:32:54 +09:00
Yukihiro "Matz" Matsumoto 6a1978c7e1 fix OP_APOST bug for no pre arg cases; fix #2810 2015-05-31 18:30:37 +09:00
take_cheeze 6498d90f1b Move "src/mrb_throw.h" to "include/mruby/throw.h".
Related to #2760.
2015-05-25 21:19:24 +09:00
cremno 2106d4d446 remove mrb_define_method_vm() function
It isn't needed as it's very similar to mrb_define_method_raw() and also
there's only one place where mrb_proc_ptr() actually has to be called.

Inspired by @furunkel's method cache patch (#2764).
2015-05-15 13:04:55 +02:00
Yukihiro "Matz" Matsumoto 5c25a9a6a9 C++ compilation failed due to skipping iniitalization by goto out_super 2015-04-27 02:50:42 +09:00
Yukihiro "Matz" Matsumoto bdb9d4d19c super should not be called outside of a method; fix #2770 2015-04-27 00:53:08 +09:00
Yukihiro "Matz" Matsumoto 4cf9b2fd1c execute ensure clause only when skipping call frame; fix #2726 2015-03-21 11:20:44 +09:00
Go Saito 16b5986d14 stack_extend in mrb_f_send
mrb_f_send needs stack_extend like OP_SEND

Signed-off-by: Go Saito <gos@iij.ad.jp>
2015-03-05 17:41:34 +09:00
Kouhei Sutou 42359d6241 Use ptrdiff_t to suppress signedness warning
3df3216179 says so but there is no warning
with GCC 4.9 on my Debian GNU/Linux environment.
2015-02-28 15:30:18 +09:00
Yukihiro "Matz" Matsumoto 414678d61a Merge pull request #2736 from cremno/delete-prototypes-of-undefined-functions
delete prototypes of undefined functions
2015-02-27 17:15:59 +09:00
Yukihiro "Matz" Matsumoto 3df3216179 change size_t to ptrdiff_t to silence signedness warnings; #2732 2015-02-27 17:14:03 +09:00
cremno 893f937922 delete prototypes of undefined functions 2015-02-26 09:56:03 +01:00
Kouhei Sutou 3fefe52ffb Fix a crash bug on raising after realloc
The following program reproduces this problem:

    #include <mruby.h>

    static mrb_value
    recursive(mrb_state *mrb, mrb_value self)
    {
      mrb_int n;

      mrb_get_args(mrb, "i", &n);

      if (n == 0) {
        mrb_raise(mrb, E_RUNTIME_ERROR, "XXX");
      } else {
        mrb_funcall(mrb, self, "recursive", 1, mrb_fixnum_value(n - 1));
      }

      return self;
    }

    int
    main(void)
    {
      mrb_state *mrb;

      mrb = mrb_open();

      mrb_define_method(mrb, mrb->kernel_module, "recursive", recursive,
                        MRB_ARGS_REQ(1));
      mrb_funcall(mrb, mrb_top_self(mrb), "recursive", 1, mrb_fixnum_value(30));

      mrb_close(mrb);
    }

Recursive method call isn't required. It's just for expanding call info
stack.

If mrb_realloc() is called in cipush(), cibase address is changed. So,
we shouldn't compare ci before mrb_realloc() and cibase after
mrb_realloc(). It accesses unknown address and causes crash.
2015-02-25 00:13:40 +09:00
Go Saito 42d23084b7 fix pointer dereference after realloc
In src/vm.c: mrb_funcall_with_block
stack_extend may realloc mrb->c->stbase, if argv points on mruby's stack,
then it points invalid address after stack_extend.

e.g. src/class.c: mrb_instance_new

This code:

```ruby
class A
  def initialize(a0,a1,a2,a3,a4)
    a0.is_a? Array
  end
end

def f(a0,a1,a2,a3,a4)
  A.new(a0,a1,a2,a3,a4)
  f(a0,a1,a2,a3,a4)
end

f(0,1,2,3,4)
```

is expected to get exception
```
stack level too deep. (limit=(0x40000 - 128)) (SystemStackError)
```

but get segfault.

Signed-off-by: Go Saito <gos@iij.ad.jp>
2015-02-23 11:25:21 +09:00
Kouhei Sutou 8cb40fcda7 Fix ensure with yield context on break and return
How to reproduce:

    class A
      def x
        yield
      ensure
        y
      end

      def y
      end
    end

    # Work
    A.new.x do
    end

    # Not work
    # trace:
    # 	[2] /tmp/a.rb:5:in A.x
    # 	[0] /tmp/a.rb:15
    # /tmp/a.rb:5: undefined method 'y' for main (NoMethodError)
    A.new.x do
      break
    end

    # trace:
    # 	[2] /tmp/a.rb:5:in A.call
    # 	[0] /tmp/a.rb:19
    # /tmp/a.rb:5: undefined method 'y' for main (NoMethodError)
    lambda do
      A.new.x do
        return
      end
    end.call

`self` in ensure is broken when yield and break/return are used.
2015-02-05 22:40:25 +09:00
Xuejie "Rafael" Xiao d63e45a014 Use setter macro instead of directly setting values 2015-01-26 10:52:06 +08:00
Yukihiro "Matz" Matsumoto 09c6ca936c preserve ICLASS in ci->target_class; fix #2657; ensuring #1467 #1470 #1493 still works 2014-11-28 20:35:06 +09:00
sdottaka 820f6d147f Fix an error when calling a method implemented in C by super() with arguments. This fix makes the following code workable:
Expected:

class MRBTime < Time; def self.new; super(2012, 4, 21); end; end
MRBTime.new # => Sat Apr 21 00:00:00 2012

Actual:

class MRBTime < Time; def self.new; super(2012, 4, 21); end; end
MRBTime.new # => can't convert nil into Integer (TypeError)
2014-11-19 13:29:22 +09:00
Jan Berdajs aff2be4b40 fix typo (i->idx) 2014-10-15 14:11:00 +02:00
cremno 26bbc81e12 get rid of shadowing variables
Mostly by renaming the shadowing variable.
If a shadowing variable was deleted,
the shadowed one can be used instead.
2014-09-03 10:00:37 +02:00
Yukihiro "Matz" Matsumoto 7ac68809d3 remove ci->nreg initialization from cipush() 2014-09-01 15:38:25 +09:00
dycoon 77b2ec30ff add write barrier to env on pop call info poped. #2525 2014-08-28 09:14:40 +09:00
cremno bdaa12de1d use MRB_STRINGIZE
It's defined in mruby/version.h which gets included in mruby.h, so it's
safe to use.
2014-08-26 00:32:06 +02:00
Kouhei Sutou e75e2083fd Fix a bug that class variable can't be referenced from class method
Class method defined in singleton class should be evaluated in class
context not singleton class context.

fix #2515
2014-08-09 15:06:17 +09:00
go kikuta 513f24e908 removed non-need space 2014-08-07 23:11:10 +09:00