Project

General

Profile

Actions

Bug #19635

closed

errno may be overwritten by rb_sprintf if it triggers GC

Added by wks (Kunshan Wang) about 1 year ago. Updated about 1 year ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:113449]

Description

Here is an excerpt in the trap function in signal.c

        oldfunc = ruby_signal(sig, func);
        if (oldfunc == SIG_ERR) rb_sys_fail_str(rb_signo2signm(sig));

ruby_signal tries to register a signal handling function. If it fails, it returns SIG_ERR, and errno is set to by sigaction to indicate the error.

However, the snippet above calls rb_signo2signm(sig) before calling rb_sys_fail_str. rb_signo2signm allocates a Ruby heap object using rb_sprintf. The problem is, if this rb_sprintf triggers GC, the garbage collector may perform may complex operations, including executing obj_free, calling mmap to allocate more memory from the OS, etc. They may overwrite the errno.

So if GC is triggered in the very unfortunate time, the caller of the trap function will receive an exception, but with the wrong reason. This may cause some tests, such as the test_trap_uncatchable_#{sig} test cases in test_signal.rb, to fail.

There are similar use cases in hash.c, for example:

        if (ret) rb_sys_fail_str(rb_sprintf("setenv(%s)", name));

The good practice is always loading from errno immediately after calling functions that may set errno, such as sigaction and setenv.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0