Until now, GEMS added via `gem.add_dependency` retained the last `MRuby::Build.current` from the build configuration file, which was accessible from the top level of `mrbgem.rake`.
The issue resolved by the preceding patch was solely the C++ exception task within the mruby core.
This patch aims to resolve a similar sequencing issue that also exists in GEMS.
In practice, `mruby-compiler` is sometimes loaded via dependencies rather than being explicitly specified in the build configuration file.
In such cases, when `mruby-compiler/mrbgem.rake` is loaded, it is not yet determined whether C++ exceptions will be used. Consequently, even if it later becomes clear that `core/codegen-cxx.cxx` and `core/y.tab-cxx.cxx` are required, the system could not handle this.
To resolve this issue, we introduce the `MRuby::Gem::Specification#build_settings` method as a mechanism for lazily evaluating build setup.
However, for backward compatibility, the commands are cloned twice in `gem.setup` and `gem.setup_build`.
This is because many existing GEMS configure commands directly within the setup block.
ref. https://github.com/mruby/mruby/issues/6615
Until now, GEMs dependent on GEMs described in the build configuration file were loaded and set up after mruby core tasks were defined.
This caused an issue where, if C++ exceptions were enabled later by a dependent GEM, the necessary tasks for mruby core were not defined.
fixed https://github.com/mruby/mruby/issues/6615
Goes from 36s to 16s on my system (from clean):
```
$ 2>&1 time -p rake -m | rg real
real 14.72
$ 2>&1 time -p rake | rg real
real 14.72
$ 2>&1 time -p rake SERIAL=1 | rg real
real 37.49
```
The MSVC _umul128 code path was designed for 64-bit limbs but mruby's
bigint implementation uses 32-bit limbs even on 64-bit builds. This
fundamental mismatch caused incorrect bigint calculations on VC 64-bit
builds, producing results like "100000000000000000000" -> "1661992960".
Removed the MSVC optimization to fall back to the portable double-limb
arithmetic which correctly handles 32-bit limbs.
Co-authored-by: Claude <noreply@anthropic.com>
The MSVC-specific _umul128 code path had incorrect carry propagation
when adding three values (rp[i] + lo + carry). The original code:
carry = hi + (sum < lo);
only detected overflow between sum and lo, missing overflow in the
first addition rp[i] + lo. This caused incorrect bigint calculations
on VC 64-bit builds.
Fixed by splitting three-way addition into two two-way additions
with proper overflow detection for each step:
temp = rp_val + lo;
sum = temp + carry;
carry = hi + (temp < rp_val) + (sum < temp);
Co-authored-by: Claude <noreply@anthropic.com>
Replaced mathematical symbols in comments with ASCII equivalents:
- multiplication sign to *
- Greek mu to mu
- approximately equal to ~
- subscript 2 to 2
- less than or equal to <=
This complies with the coding standard to use English and ASCII
characters in all code comments and documentation.
Co-authored-by: Claude <noreply@anthropic.com>
The previous implementation of mrb_int_mul_overflow performed
the multiplication before checking for overflow. This is undefined
behavior for signed integers and can lead to incorrect results on
some compilers (e.g., MSVC).
The implementation has been changed to perform the overflow checks
before the multiplication.
Co-authored-by: Gemini <gemini@google.com>
Adds Math.expm1 and Math.log1p, which provide more accurate
calculations for exp(x) - 1 and log(1 + x) respectively,
especially for small values of x.
Co-authored-by: Gemini <gemini@google.com>
Cast RARRAY_LEN result to int in send_method when handling visibility
errors to resolve C4244 warning about potential data loss from
mrb_ssize to int conversion. The cast is safe since n represents
argument count which should fit in int range.
Co-authored-by: Claude <noreply@anthropic.com>
Cast base parameter to uint64_t in mpz_get_str power-of-2 path to
resolve C4018 warning about signed/unsigned mismatch. The comparison
now properly compares two unsigned values: ((uint64_t)1 << shift)
with (uint64_t)base.
Co-authored-by: Claude <noreply@anthropic.com>
Cast mrb_int capacity to khint_t when calling kh_init_data to resolve
C4244 warning about potential data loss in conversion from signed to
unsigned type. The khash API expects khint_t (uint32_t) parameters.
Co-authored-by: Claude <noreply@anthropic.com>
Remove intermediate bound variable and cast max directly to uint32_t
where needed for unsigned operations. This eliminates C4146 warning
about unary minus on unsigned type while maintaining the same
mathematical behavior.
Co-authored-by: Claude <noreply@anthropic.com>
use mrb_int for size variable and cast to size_t only when calling getcwd.
this maintains consistency with mruby type system while avoiding
conversion warnings on windows vc compiler.
Co-authored-by: Claude <noreply@anthropic.com>
This patch fixs a critical segmentation fault in `io_gets` function caused by an uninitialized limit variable.
This bug may specifically heppen when:
- MicroRuby with task scheduler, which I'm implementing, enabled
## Root Cause Analysis
When `io_gets` is called without arguments (argc=0), the local variable `limit` remains uninitialized on the stack.
I guess that this uninitialized memory often contains leftover heap addresses from previous stack frames.
### The problematic flow:
1. `mrb_get_args(mrb, "|o?i?", &rs, &rs_given, &limit, &limit_given)` with 0 arguments
2. `limit_given = FALSE` but limit contains garbage heap address
3. Looks like later processing truncates this address, creating invalid pointer 0xffff0000
4. This value gets pushed onto VM stack during string operations
5. Garbage collector attempts to mark 0xffff0000 as valid object pointer
6. SIGSEGV in mrb_gc_mark() at gc.c:748
```
Program received signal SIGSEGV, Segmentation fault.
0x00005c8bebffa95c in mrb_gc_mark (mrb=0x5c8bec2836c8 <heap_pool+728>, obj=0xffff0000)
at .../gc.c:748
748 if (!is_white(obj)) return;
#1 mark_context_stack (mrb=0x5c8bec2836c8 <heap_pool+728>, c=0x5c8bec2b4a50 <heap_pool+202336>)
at .../gc.c:555
555 mrb_gc_mark(mrb, mrb_basic_ptr(v));
```
## Solution
I couldn't figure out the exact mechanism of the issue. Anyway, initializing the limit variable to zero could prevent invalid garbage stack memory:
```c
mrb_int limit = 0; // Explicit initialization
```
## Files Changed
- mrbgems/picoruby-mruby/lib/mruby/mrbgems/mruby-io/src/io.c
changed all unpack function signatures from int srclen to mrb_int srclen
to maintain consistency with pack functions that use mrb_int sidx.
eliminates potential overflow when strings exceed INT_MAX and avoids
unnecessary casting from RSTRING_LEN() return value.
Co-authored-by: Claude <noreply@anthropic.com>
Fix C4334 and C4244 warnings that caused test failures on Windows VS 2022:
- Use uint64_t for shift operation to avoid undefined behavior
- Add explicit mp_limb casts for type conversions
Co-authored-by: Claude <noreply@anthropic.com>
When creating a bigint with embedded storage, the array wasn't being
initialized when x->p was NULL but x->sz > 0. This could leave garbage
memory in the embedded array, which VS 2022 might interpret differently
than VS 2019, causing test failures.
This fix ensures the embedded array is always properly initialized with
zeros when x->p is NULL, preventing potential undefined behavior.
Co-authored-by: Claude <noreply@anthropic.com>
This fixes Windows VC build issues where MRB_NO_MPZ64BIT is automatically
enabled, switching to 16-bit limbs. When multiplication results in a carry,
the size must be updated to include the additional limb.
Co-authored-by: Claude <noreply@anthropic.com>
Fixes carry propagation in multiplication and integer conversion
overflow detection when MRB_NO_MPZ64BIT is enabled on windows
with MRB_INT32. resolves test failures for large number operations.
Co-authored-by: Claude <noreply@anthropic.com>
In the Windows-specific code path for IO.popen, the variable 'p'
is a struct, not a pointer. The code was using 'p->klass' to
access a member, which is incorrect and causes a build failure
on Windows. This has been corrected to use the 'klass' argument
directly.
Co-authored-by: Gemini <gemini@google.com>
SYMTBL_LITERAL_FLAG was defined as 1UL, which can be smaller
than uintptr_t on some platforms (e.g., Windows 64-bit). This
caused symtbl_get_ptr() to return a corrupted pointer.
Changed the flag to be explicitly cast to uintptr_t to ensure
correct behavior on all platforms.
Co-authored-by: Gemini <gemini@google.com>
Move the definition of struct mrb_ast_node to a private header to
hide implementation details from the public API.
Co-authored-by: Gemini <gemini@google.com>
Move STR_FUNC_* macros, enum mrb_string_type, and struct
mrb_parser_heredoc_info from include/mruby/compile.h to
mrbgems/mruby-compiler/core/node.h.
These types are internal to the mruby compiler gem and are used by
both parse.y and codegen.c. Moving them to node.h encapsulates them
within the compiler gem, cleaning up the public mruby/compile.h header.
Co-authored-by: Gemini <gemini@google.com>
This change allows for handling small tables as linear-search arrays,
improving performance for hashes with few elements.
Co-authored-by: Gemini <gemini@google.com>
The hash rebuild process was not GC-safe. When rebuilding the hash
table, the old data was orphaned before the new table was fully
populated, which could lead to a segmentation fault if a GC cycle
was triggered during the process.
This patch refactors the rebuild function to follow a safer pattern:
- A new temporary hash table is allocated on the stack.
- Elements from the original table are copied to the new one.
- The original table's data is swapped with the new table's data
only after the new table is complete.
This ensures the original data is always reachable by the GC during
the rebuild.
Co-authored-by: Gemini <gemini@google.com>
Replace designated initializer lookup tables with switch statement
functions for C++ compatibility. This approach is cleaner and works
perfectly in both C and C++ modes.
- char_to_bit array -> char_to_bit() function
- char_class array -> char_class() function
- format_table array -> get_format_info() function
Co-authored-by: Claude <noreply@anthropic.com>
Replace designated initializer lookup table with a simple switch statement
for C++ compatibility. The switch approach is cleaner and works perfectly
in both C and C++ modes.
Co-authored-by: Claude <noreply@anthropic.com>
- Add explicit cast for mrb_malloc return value
- Remove restrict keyword from function parameters
- Move variable declarations to avoid goto/initialization conflicts
- Fix signed/unsigned comparison warning in mpz_get_str
Co-authored-by: Claude <noreply@anthropic.com>