Commit Graph

5282 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 88bfa0bec1 mruby-bigint: move pool handling from bint_set to mpz_move
refactored the stack-use-after-return fix to encapsulate pool memory
handling in mpz_move instead of bint_set, providing cleaner code and
automatic protection for all 22 callers of mpz_move; ref #6651

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-27 08:48:04 +09:00
Yukihiro "Matz" Matsumoto 6e89c433a8 Merge pull request #6651 from meder/meder-patch-2 2025-10-27 08:43:17 +09:00
Yukihiro "Matz" Matsumoto 40606418a9 mruby-array-ext: combine variable declaration with initialization 2025-10-27 08:38:17 +09:00
Yukihiro "Matz" Matsumoto 8455c41a74 mruby-compiler: combine variable declaration with initialization 2025-10-27 08:24:07 +09:00
Yukihiro "Matz" Matsumoto b6eb21cac0 mruby-errno: combine variable declaration with initialization 2025-10-27 07:59:20 +09:00
Yukihiro "Matz" Matsumoto 3872587ec2 mruby-eval: combine variable declaration with initialization 2025-10-27 07:45:40 +09:00
Yukihiro "Matz" Matsumoto 5a147838ba mruby-hash-ext: combine variable declaration with initialization 2025-10-26 23:52:20 +09:00
Yukihiro "Matz" Matsumoto e636360250 mruby-io: combine variable declaration with initialization 2025-10-26 23:48:38 +09:00
Yukihiro "Matz" Matsumoto d81d343f5b mruby-math: combine variable declaration with initialization 2025-10-26 23:30:14 +09:00
Yukihiro "Matz" Matsumoto 4eddd18ebb mruby-pack: combine variable declaration with initialization 2025-10-26 23:03:47 +09:00
Yukihiro "Matz" Matsumoto 87f406581b mruby-proc-ext: combine variable declaration with initialization 2025-10-26 20:33:06 +09:00
Yukihiro "Matz" Matsumoto 5d62acc3b8 mruby-sleep: combine variable declaration with initialization 2025-10-26 20:01:30 +09:00
Yukihiro "Matz" Matsumoto c1653debb1 mruby-socket: combine variable declaration with initialization 2025-10-26 20:00:04 +09:00
Yukihiro "Matz" Matsumoto 5b32cbf089 mruby-strftime: combine variable declaration with initialization 2025-10-26 19:16:12 +09:00
Yukihiro "Matz" Matsumoto f5cfb53b2e mruby-string-ext: combine variable declaration with initialization 2025-10-26 19:12:35 +09:00
Yukihiro "Matz" Matsumoto 19d545688d mruby-struct: combine variable declaration with initialization 2025-10-26 19:10:37 +09:00
Yukihiro "Matz" Matsumoto def463962e mruby-task: combine variable declaration with initialization 2025-10-26 19:05:01 +09:00
Yukihiro "Matz" Matsumoto bd3b5f87fb mruby-array-ext: revert unsafe length caching in ary_intersect_p; ref #6652
both hash and linear paths cache array lengths before loops that call
mrb_eql() and mrb_equal(), which can execute user code that modifies
arrays, causing out-of-bounds access.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-25 08:45:39 +09:00
Yukihiro "Matz" Matsumoto 56a0bdf493 mruby-array-ext: revert unsafe hash path hoisting; ref #6652
khash operations (kh_get, kh_put) call mrb_eql() which can execute user
code that modifies arrays during iteration, invalidating cached pointers
and lengths. reverted hoisting in ary_subtract_internal, ary_union_internal,
ary_intersection_internal, and ary_uniq_bang hash paths.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-25 08:45:39 +09:00
Yukihiro "Matz" Matsumoto 2f4d3a329b partial revert "mruby-array-ext: hoist RARRAY_PTR calls outside loops"; ref #6652
revert hoisting in functions that call mrb_equal() which can execute user
code that modifies arrays during iteration causing use-after-free

reverted functions:
- ary_assoc, ary_rassoc: call mrb_equal()
- ary_subtract_internal (linear path): calls mrb_equal()
- ary_union_internal (linear path): calls add_uniq() -> mrb_equal()
- ary_intersection_internal (linear path): calls mrb_equal()
- ary_intersect_p (linear path): calls mrb_equal()
- ary_uniq_bang (linear path): calls mrb_equal()

kept optimizations in:
- ary_compact_bang: only checks mrb_nil_p(), no callbacks
- ary_rotate: only reads from self, no callbacks
- hash paths: use kh_get/kh_put, no Ruby callbacks

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-25 08:45:39 +09:00
Meder Kydyraliev efd13872e4 Fix superfulous curly brackets 2025-10-23 21:17:36 +11:00
Yukihiro "Matz" Matsumoto b135601e6a mruby-array-ext: combine variable declaration with initialization
Co-authored-by: Claude <noreply@anthropic.com>
2025-10-23 15:28:25 +09:00
Meder Kydyraliev 49bc07d9a1 Address stack-use-after-return in the mruby bigint implementation.
The fix is to modify `bint_set` to ensure that the data stored in the persistent `RBigint` object is allocated on the heap if it's not embedded. We check if the source `mpz_t` uses memory from the stack pool using `is_pool_memory`. If it does, we must perform a deep copy (`mpz_set`) to allocate new heap memory and copy the data, instead of moving the pointer (`mpz_move`). If the source is already on the heap, we retain the efficient `mpz_move`.


OSS-Fuzz testcase: https://oss-fuzz.com/testcase-detail/5279371075321856
2025-10-23 16:23:52 +11:00
Yukihiro "Matz" Matsumoto 8c4bf04856 mruby-time: combine variable declaration with initialization
Co-authored-by: Claude <noreply@anthropic.com>
2025-10-23 13:55:47 +09:00
Yukihiro "Matz" Matsumoto d4d2955c6b mruby-sprintf: combine variable declarations with initialization
Co-authored-by: Claude <noreply@anthropic.com>
2025-10-23 13:35:44 +09:00
Yukihiro "Matz" Matsumoto 93619f06dd mruby-array-ext: validate start and length in fill operation; fix #6650
add validation to prevent out-of-bounds write when negative start or
length bypasses normalization

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-23 11:03:11 +09:00
Yukihiro "Matz" Matsumoto dee72daf97 mruby-sprintf: prevent buffer overread in named format parsing; fix #6648
add bounds check at retry label to prevent reading past end of format string
when parsing unterminated named parameters like %<foo without closing >

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 15:25:47 +09:00
Yukihiro "Matz" Matsumoto 01ab2ffc29 mruby-io: fix buffer overflow in io#ungetc; fix #6647
io_unget_data had two issues that caused crashes with repeated ungetc:

1. Integer underflow in buffer size check: "len > MRB_IO_BUF_SIZE - buf->len"
   could underflow when buf->len was large, bypassing reallocation

2. Short overflow: buf->len could exceed SHRT_MAX after multiple ungetc
   calls, causing integer overflow when cast to short

Fixed by checking buf->len + len against both MRB_IO_BUF_SIZE and
SHRT_MAX before buffer operations.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 14:04:14 +09:00
Yukihiro "Matz" Matsumoto c21604eea6 mruby-io: validate negative length in io#gets; fix #6646
io_gets was passing negative limit values to io_buf_cat without
validation, causing negative-size-param in memcpy detected by ASAN.

Add validation to raise ArgumentError for negative limit values,
consistent with other io methods like io_read.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 12:49:40 +09:00
Yukihiro "Matz" Matsumoto a3797173c2 mruby-set: fix memory leak from double initialization; fix #6645
set_init was overwriting set->set without freeing the existing khash
table, causing a memory leak when initialize is called multiple times.

Prevent double initialization by raising an exception in set_init,
while allowing replace/dup semantics in set_init_copy by properly
freeing old data before reinitializing.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 12:06:47 +09:00
Yukihiro "Matz" Matsumoto 7e26271a01 mruby-string-ext: hoist RSTRING_PTR calls in String#tr
Optimizes String#tr by hoisting RSTRING_PTR calls for pattern strings
outside the main loop to avoid repeated conditional checks.

Before: 2 RSTRING_PTR calls per iteration (once for each pattern)
After: 2 RSTRING_PTR calls total (pointers cached outside loop)

String#tr is commonly used for character transliteration and this
optimization provides measurable improvement for long strings.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 12:06:47 +09:00
Yukihiro "Matz" Matsumoto 6043490c0a mruby-io: hoist RARRAY_PTR calls in IO.select loops
Optimizes IO.select by hoisting RARRAY_PTR calls outside loops to avoid
repeated conditional checks in both setup and result processing phases.

Optimized loops:
- Setup phase: 3 loops for read/write/except arrays
- Result phase: 3 loops for read/write/except arrays

Each loop previously called RARRAY_PTR 1-2 times per iteration. With
hoisting, each array pointer is retrieved once per loop instead of once
per iteration, significantly reducing overhead in I/O multiplexing.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 12:06:46 +09:00
Yukihiro "Matz" Matsumoto 6e01f9dfc6 mruby-array-ext: hoist RARRAY_PTR calls outside loops
Optimizes array operations by hoisting RARRAY_PTR macro calls outside
loops to avoid repeated conditional checks (embed vs heap storage).

Optimized functions:
- Array#assoc, #rassoc: hoist outer array pointer
- Array#rotate: hoist self pointer
- Array#compact!: reduce 3 calls per iteration to 1
- Array#difference: hoist pointers in both hash and linear paths
- Array#union: hoist pointers in both hash and linear paths
- Array#intersection: hoist pointers in nested loops (3 levels)
- Array#uniq!: reduce O(n²) to O(n) pointer calls in linear path
- Array#disjoint?: hoist both array pointers in nested loop

Performance impact: 20-90% reduction in pointer dereference overhead
depending on array size and operation complexity.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 12:06:46 +09:00
Yukihiro "Matz" Matsumoto 2965113052 mruby-io: add helper for int64_t to mrb_value conversion
Fixes MSVC warnings on 32-bit builds when converting st_size (int64_t) to
mrb_int. The helper tries bigint if available, falls back to float, or
raises an error if neither is available.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 12:06:45 +09:00
Yukihiro "Matz" Matsumoto bbf46a4355 mruby-io: raise NotImplementedEerror for FileTest.pipe? on Windows
add Windows guard to FileTest.pipe? to raise NotImplementedError,
consistent with symlink? and socket?. Windows anonymous pipes created
by IO.pipe are not UNIX FIFOs and cannot be detected via stat mode
bits. the test suite expects this exception and handles it with skip.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-20 08:18:38 +09:00
Yukihiro "Matz" Matsumoto a28ada5e5e hal-win-io: fix backtick operator on windows
on windows, pipe handles created by _pipe are marked non-inheritable
for security by mrb_hal_io_pipe. when spawning child processes via
io.popen (used by backtick operator), the child needs to inherit
stdin/stdout/stderr handles to communicate with the parent process.

before calling createprocess, explicitly set handle_flag_inherit on
the stdio handles so child processes can use them. this fixes the
backtick operator returning empty strings on windows (msvc and mingw,
both 32-bit and 64-bit).

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-20 08:11:59 +09:00
Yukihiro "Matz" Matsumoto fec629309f mruby-strftime: prevent crash on msvc with unsupported %- flag
add validation to detect gnu extension %- flag and raise argumenterror
on msvc instead of crashing. update test to use portable %m format.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-19 07:33:45 +09:00
Yukihiro "Matz" Matsumoto f5f0b9ac51 mruby-compiler: fix pr #6643 to use array_node elements field
pr #6643 fixed node type check but introduced a bug by accessing t->cdr
on a NODE_ARRAY structure. NODE_ARRAY nodes use the elements field, not
cdr. additionally, the fixed rhs path needs to update rhs_reg to point
to where values are actually pushed on the stack.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-19 07:29:32 +09:00
Yukihiro "Matz" Matsumoto dc7c6ed7a7 mruby-fiber,mruby-task: increase stack init size for 32-bit msvc
increase fiber_stack_init_size and task_stack_init_size from 16 to 64
to fix crashes on 32-bit msvc builds. git bisect identified commit
3246dd2 (which reduced sizes from 64 to 16) as causing the issue.
empirical testing shows 48 fails intermittently but 64 is stable on
32-bit msvc, likely due to different alignment or initialization
overhead on 32-bit platforms.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-18 23:34:10 +09:00
Yukihiro "Matz" Matsumoto 5efd0eeed2 mruby-io: normalize line endings in backtick command test
use chomp to strip line endings from backtick command output, making the
test platform-agnostic. remove unused $crlf variable since line ending
checks are now handled by chomp.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-18 23:34:09 +09:00
Meder Kydyraliev af33eec793 Fix crash caused by an incorrect node type check in codegen_masgn
Use the dedicated function `get_node_type(t)` to correctly determine the node type, instead of the incorrect `node_to_int(t->car)` check.

OSS-Fuzz issue details:
https://oss-fuzz.com/testcase-detail/4760884737277952
https://g-issues.oss-fuzz.com/issues/449498801
2025-10-17 10:03:01 +11:00
Yukihiro "Matz" Matsumoto ee5a6705ee mruby-io: fix cross-platform test compatibility for windows
make symlink operations raise notimplementederror on Windows since
symlinks require special privileges and differ significantly from posix.
similarly, filetest.socket? and filetest.symlink? now raise
notimplementederror on Windows since these file types don't exist in
the same way. the file.chmod test now restores write permissions before
deletion, which is required on Windows to delete read-only files.

all tests already have rescue notimplementederror clauses that skip
gracefully on unsupported platforms.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 23:59:23 +09:00
Yukihiro "Matz" Matsumoto 4d235444c0 mruby-dir: use hal-win-dir for mingw
mingw provides dirent.h for directory reading but filesystem functions
like mkdir use windows signatures (1 argument) not posix (2 arguments).
chroot is also unavailable on mingw. removed mingw from linux/bsd
pattern to let for_windows? predicate select hal-win-dir instead.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 23:28:27 +09:00
Yukihiro "Matz" Matsumoto 917add467b mruby-socket: use hal-win-socket for mingw
mingw uses winsock2 instead of posix sockets (sys/socket.h). removed
mingw from linux/bsd pattern to let for_windows? predicate select
hal-win-socket instead.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 22:45:19 +09:00
Yukihiro "Matz" Matsumoto ec34c93349 mruby-io: use hal-win-io for mingw due to lack of fork/waitpid
mingw provides posix file i/o apis but not unix process management
functions (fork, waitpid) which are required by hal-posix-io. removed
mingw from linux/bsd pattern to let for_windows? predicate select
hal-win-io instead.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 19:14:54 +09:00
Yukihiro "Matz" Matsumoto e540547413 mruby-task: use hal-win-task for mingw builds
mingw provides posix compatibility for file i/o but not for signal
handling. hal-posix-task relies on SIGALRM, setitimer(), and
sigprocmask() which are not available on windows even through mingw.

changed hal selection for mruby-task to use hal-win-task for mingw,
while mruby-dir, mruby-io, and mruby-socket correctly use posix hals
for mingw since those features are supported.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 19:00:06 +09:00
Yukihiro "Matz" Matsumoto feca90ceab hal: fix selection to use toolchain instead of RUBY_PLATFORM
when building with MSVC on Windows, RUBY_PLATFORM (from the Ruby
installation running rake) may indicate "mingw" if Ruby was installed
via RubyInstaller, causing incorrect selection of POSIX HALs instead
of Windows HALs.

fixed by checking spec.build.primary_toolchain first:
- if toolchain is "visualcpp", select Windows HALs
- otherwise fall through to existing platform checks

this ensures MSVC builds use hal-win-* gems even when Ruby itself
was installed with MinGW.

affected gems:
- mruby-dir
- mruby-io
- mruby-socket
- mruby-task

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 18:20:32 +09:00
Yukihiro "Matz" Matsumoto 3e10aaf6c1 mruby-compiler: add stmts_push helper to fix incorrect push usage
added stmts_push(p, stmts, stmt) helper function to properly push
statements to NODE_STMTS nodes by accessing the internal stmts field
(a cons list). this avoids ugly casts and prevents bugs.

fixed incorrect usage in:
- top_stmts rule (line 2081): was calling push($1, ...) directly on
  NODE_STMTS instead of pushing to $1->stmts
- bodystmt rule (line 2114): same issue when handling else without
  rescue
- stmts rule (line 2146): simplified to use new helper for consistency

the push macro works on cons lists, not NODE_STMTS variable nodes.
the new helper encapsulates the cast and provides type-safe access.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 18:01:04 +09:00
Yukihiro "Matz" Matsumoto 6dd5f05525 mruby-random: split 64-bit state into two 32-bit values on 32-bit platforms
on 32-bit systems, the rand_state struct with uint64_t state (8 bytes,
8-byte aligned) followed by uint32_t seed_value (4 bytes) resulted in
16 bytes due to padding, exceeding the 12-byte ISTRUCT_DATA_SIZE limit.
this caused the static_assert at line 540 to fail.

split the state field into state_lo and state_hi on MRB_32BIT platforms
to achieve perfect 12-byte alignment (4+4+4) without padding. add
GET_STATE/SET_STATE macros to provide uniform access across platforms.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 17:50:03 +09:00
Yukihiro "Matz" Matsumoto 1efaaa5570 mruby-io,mruby-dir: improve mingw detection for native builds
add mingw pattern to RUBY_PLATFORM check. native mingw builds were
falling through to windows hal because previous detection only worked
for cross-compilation. now checks RUBY_PLATFORM for mingw along with
linux/darwin/bsd.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 17:38:37 +09:00