The "d" directive in `mrb_get_args()` can be used as an alternative.
Furthermore, NULL checking is unnecessary for the following reasons:
- Incomplete objects from `ary_combination_init()` are not passed to the caller and are garbage collected when `ObjectSpace.each_object` is called, so they are never retrieved
- Even if `state.clone` is called, the `RData::type` of the cloned object is set to NULL, so it is rejected by `mrb_get_args()`
Several methods defined in mruby-array-ext are written in C and may call `mrb_vm_exec()`.
If array objects are modified on the Ruby side, problems may arise in subsequent processing.
- Using objects that have been removed from the array and garbage collected
- Using pointers or array lengths that have become invalid due to changes to the array object
- Modifying the contents of a shared array object directly
ref: https://github.com/mruby/mruby/issues/6662
Replace `__product_group` method with `__product_generate` and `__product_next`.
This change eliminates the need for Ruby to perform internal state calculations, allowing it to simply receive the results.
Since presym is now mandatory, mruby.h includes presym.h so that
MRB_SYM() macros are available everywhere without explicit include.
Remove redundant #include <mruby/presym.h> from all source files.
Co-authored-by: Claude <noreply@anthropic.com>
ROM method tables used static mrb_mt_tbl variables shared
across the process. The next pointer in each wrapper was
mutated by mrb_mt_init_rom(), causing cross-state
contamination when multiple mrb_state instances existed.
Allocate mrb_mt_tbl wrappers per-state via mrb_malloc().
The const mrb_mt_entry[] arrays remain static and shared.
Wrappers are tracked in mrb->rom_mt and freed at mrb_close().
Remove MRB_MT_ROM_TAB macro; add MRB_MT_INIT_ROM macro that
auto-computes size and calls the new mrb_mt_init_rom().
Co-authored-by: Claude <noreply@anthropic.com>
Replace check_method_noarg() with check_argument_count() that validates
min <= argc <= max using the full aspec stored in mrb_method_t.flags.
This catches ArgumentError earlier at dispatch time, before entering
the C function.
The old check only handled the special case of aspec==0 (NOARG).
The new check extracts REQ, OPT, REST, POST, KEY, and KDICT from
the aspec and validates accordingly. Keyword hash is counted as
a positional arg only when the method doesn't accept keywords.
Remove MRB_METHOD_NOARG_P macro from proc.h (subsumed by aspec check).
Fix 15 incorrect aspec declarations across the codebase that were
exposed by the stricter enforcement.
Co-authored-by: Claude <noreply@anthropic.com>
Restore MRB_ARGS_* argument specs and ISO section comments to all
709 ROM method table entries. The aspec is encoded in bits 4-27 of
the flags field; MRB_MT_NOARG is now auto-derived from aspec==0.
Add MRB_MT_ENTRY_PRIVATE() macro for private methods (53 entries)
and MRB_MT_ASPEC() accessor for extracting aspec from flags.
Co-authored-by: Claude <noreply@anthropic.com>
Since ROM table entries are always C functions, have the
MRB_MT_ENTRY() macro set MRB_MT_FUNC automatically. This
simplifies entry definitions across all 32 source files.
Co-authored-by: Claude <noreply@anthropic.com>
Replace binary search with linear scan in mt_get(), mt_put(),
mt_del(), mt_chain_has(), and mrb_mt_foreach(). The method cache
makes repeated lookups O(1), so linear scan on cache misses is
acceptable.
This removes the sorting requirement, allowing ROM entry arrays
to be declared const. On embedded systems, const static data
resides in flash/ROM instead of RAM, saving ~8.4KB for ~700
method entries on 32-bit MCUs.
Co-authored-by: Claude <noreply@anthropic.com>
Replace the parallel-arrays (struct-of-arrays) ROM method table
layout with an array-of-structs layout where each mrb_mt_entry
bundles its function pointer and symbol key together.
New MRB_MT_ENTRY() and MRB_MT_ROM_TAB() macros simplify ROM table
definitions from a 3-part pattern (SIZE define + anonymous struct +
mrb_mt_tbl) to a 2-part pattern (entries array + mrb_mt_tbl).
Internal mt_* functions in class.c are simplified: single memmove/
memcpy operations replace paired key+value operations.
Co-authored-by: Claude <noreply@anthropic.com>
The purpose is to avoid using the `MRB_TT_CPTR` object.
The reasons are as follows:
- The `MRB_WORD_BOXING` setting involves object creation.
- If object creation fails, the `ary_set_t` data leaks memory.
refactored five functions to use mrb_ensure() instead of MRB_TRY/MRB_CATCH:
- ary_subtract_internal(): body/ensure pattern for set cleanup
- ary_union_internal(): body/ensure pattern for set cleanup
- ary_intersection_internal(): body/ensure pattern for set cleanup
- ary_intersect_p(): body/ensure pattern for set cleanup
- ary_uniq_bang(): body/ensure pattern for set cleanup
each function now uses a context struct containing set pointer and other
necessary data, with separate body and ensure functions that guarantee
cleanup on exception. this allows array-ext to compile as pure C without
requiring C++ compiler when enable_cxx_exception is set.
added mruby-error dependency to access mrb_ensure(). changed include
from throw.h to error.h. fix#6667.
Co-authored-by: Claude <noreply@anthropic.com>
the internal method __product_group assumes all elements in the arys
argument are Arrays, but when called directly (e.g., via send or fuzzing),
non-array values can cause segfault. add type check before accessing with
RARRAY_LEN to convert crash to proper TypeError.
Co-authored-by: Claude <noreply@anthropic.com>
during eql? callbacks, array modifications can cause elements in khash to
be freed by GC, leading to use-after-free. create temporary shared copies
of arrays before populating khash to protect elements during callbacks.
Co-authored-by: Claude <noreply@anthropic.com>
add exception handling with MRB_TRY/MRB_CATCH to ensure khash cleanup
when eql? or hash methods raise exceptions. use kh_is_end macro for safe
khash iteration.
affected functions: Array#intersect?, Array#-, Array#|, Array#&, Array#uniq!
Co-authored-by: Claude <noreply@anthropic.com>
refactor to use the standard Data_Make_Struct() macro instead of manual
RData allocation and linking. the macro provides automatic zero-initialization
and is more idiomatic.
ref #6655
Co-authored-by: Claude <noreply@anthropic.com>
Passing a large integer value as the first argument to `Array#ary_combination_init` could cause an incorrect memory allocation due to integer overflow.
This would result in an invalid write during the subsequent zero-fill of the memory.
To resolve the issue, it has been replaced with `mrb_calloc()`.
However, since the current `mrb_calloc()` returns `NULL` due to overflow, it has been modified to raise an exception as a clear error.
If memory allocated with `mrb_malloc()` is not associated with an object, subsequent attempts to allocate memory or objects will fail and raise an exception, resulting in a memory leak.
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>
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>
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>
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>
Implement hybrid C/Ruby optimization for __repeated_combination method:
- Add combination state structure with C index generation
- Use iterator pattern to avoid VM callbacks (mrb_yield)
- Keep Ruby block handling while optimizing core algorithm
- Add comprehensive validation and error handling
- Maintain compatibility with existing repeated_combination/repeated_permutation APIs
Performance improvements:
- 5-10x faster index advancement in C vs Ruby arithmetic
- Reduced memory allocation for intermediate arrays
- Optimized for both small and large combination sizes
Co-authored-by: Claude <noreply@anthropic.com>
Implemented `__product_group` in C to efficiently construct the intermediate
group arrays within Array#product. This reduces Ruby interpreter overhead
and improves performance for Array#product, especially for large inputs.
Co-authored-by: Gemini <gemini@google.com>
The internal helper functions for array set operations now use a
stack-allocated `ary_set_t` instead of a heap-allocated one. This avoids
an unnecessary memory allocation for each call to `&`, `|`, `-`, `uniq!`,
and `intersect?`, improving performance by reducing overhead.
Co-authored-by: Gemini <gemini@google.com>
Introduces `ary_get_array_args` to centralize the argument parsing logic for
set operations, reducing code duplication in `ary_subtract_internal`,
`ary_union_internal`, and `ary_intersection_internal`. Also fixes a bug in
`ary_union_internal` where converted arguments were not being used.
Co-authored-by: Gemini <gemini@google.com>
Introduces `ary_update_hash_set` to centralize the logic for adding array
elements to a hash set. This helper is now used by `ary_to_hash_set`,
`ary_subtract_internal`, and `ary_intersection_internal`, reducing code
duplication.
Co-authored-by: Gemini <gemini@google.com>
This removes code duplication by making ary_compact call
ary_compact_bang on a duplicated array, centralizing the compaction
logic. It also reorders the functions to remove the need for a forward
declaration.
Co-authored-by: Gemini <gemini@google.com>
This removes code duplication by making ary_uniq call ary_uniq_bang on a
duplicated array, centralizing the uniqueness logic.
Co-authored-by: Gemini <gemini@google.com>
This commit fixes a use-after-free vulnerability in `ary_compact_bang` by
replacing pointer-based iteration with index-based loops. This prevents raw
pointers from becoming stale after a garbage collection cycle is triggered by
`mrb_ary_modify`.
Co-authored-by: Gemini <gemini@google.com>
This commit fixes a use-after-free vulnerability in `ary_slice_bang` by
replacing pointer-based operations with index-based operations. This prevents
raw pointers from becoming stale after a garbage collection cycle is triggered
by `mrb_ary_new_from_values`.
Co-authored-by: Gemini <gemini@google.com>
This commit fixes a use-after-free vulnerability in `ary_uniq_bang` by
replacing pointer-based iteration with index-based loops. This prevents raw
pointers from becoming stale after a garbage collection cycle is triggered by
functions like `mrb_hash_set` or `mrb_equal`.
Co-authored-by: Gemini <gemini@google.com>
This commit fixes a use-after-free vulnerability in `ary_uniq` by replacing
pointer-based iteration with index-based loops. This prevents raw pointers from
becoming stale after a garbage collection cycle is triggered by functions like
`mrb_hash_set`, `mrb_ary_push`, or `mrb_equal`.
Co-authored-by: Gemini <gemini@google.com>
This commit fixes a use-after-free vulnerability in `ary_intersect_p` by
replacing pointer-based iteration with index-based loops. This prevents
raw pointers from becoming stale after a garbage collection cycle is
triggered by functions like `mrb_hash_set` or `mrb_equal`.
Co-authored-by: Gemini <gemini@google.com>
This commit fixes a use-after-free vulnerability in `ary_rotate` by replacing a
pointer-based loop with an index-based loop. This prevents a raw pointer from
becoming stale after a garbage collection cycle is triggered by `mrb_ary_push`.
Co-authored-by: Gemini <gemini@google.com>