Commit Graph

312 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 7feba44aa3 mruby-bigint: add scratch buffer to D&C to_s for reduced allocations
Add dc_to_s_scratch_t structure to preallocate work buffers for the
base case of divide-and-conquer decimal string conversion. This
eliminates repeated malloc/free calls in the inner loop where digits
are extracted 9 at a time.

Previously, each iteration of the base case loop allocated and freed
a quotient buffer. Now the same two buffers are reused with pointer
swapping, reducing allocation overhead by ~10-18% for large numbers.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 12:47:45 +09:00
Yukihiro "Matz" Matsumoto b479f97458 mruby-bigint: fix heap-buffer-overflow in bitwise OR/XOR early returns
When mpz_or or mpz_xor copies an operand when the other is zero,
the copied mpz_t may have an inflated sz field (larger than actual
allocated limbs). Add trim() after mpz_set to normalize the size.

This is a follow-up fix to commit 61aa2234d8 which addressed the
same issue in shift operations.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 12:47:45 +09:00
Yukihiro "Matz" Matsumoto 61aa2234d8 mruby-bigint: add missing trim in shift functions
Add trim() calls after mpz_set/mpz_move in shift operations where
actual bit manipulation is skipped:

- mpz_mul_2exp when e==0 (no shift needed)
- mpz_mul_2exp when bs==0 (limb-only shift)
- mpz_div_2exp when e==0 (no shift needed)
- mpz_div_2exp when bs==0 (limb-only shift)

This prevents inflated sz values from propagating through operations,
complementing the earlier fix to urshift/ulshift when n==0.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 22:27:04 +09:00
Yukihiro "Matz" Matsumoto f2f385f572 mruby-bigint: fix missing trim in urshift/ulshift when n==0
When shift amount is 0, urshift() and ulshift() called mpz_set() which
copies data without trimming leading zero limbs. This caused bigint
values to have inflated sz fields, making ucmp() comparisons incorrect.

For example, a 256-bit remainder from division could have sz=18 instead
of sz=8 because the divisor had 18 limbs. This made it compare greater
than values with fewer limbs, even when numerically smaller.

The bug also caused memory leaks when the incorrect comparison led to
taking wrong code paths in division, triggering size overflow exceptions
after memory was allocated.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 21:04:13 +09:00
Yukihiro "Matz" Matsumoto 26a1064d99 mruby-bigint: fix memory leak in mpz_mul_all_ones
Add MRB_TRY/MRB_CATCH to ensure local mpz_t variables are freed when
an exception (e.g., RangeError from shift overflow) occurs during
the all-ones multiplication optimization.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 17:57:22 +09:00
Yukihiro "Matz" Matsumoto 9471b132c4 mruby-bigint: fix potential memory leak in mpz_to_s_dc
Use stack allocation with zero-initialization and MRB_TRY/MRB_CATCH
to ensure heap-allocated mpz_t data is freed even when an exception
occurs during conversion.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 16:42:59 +09:00
Yukihiro "Matz" Matsumoto ece641c56f mruby-bigint: optimize to_s with 10^k = 2^k * 5^k factorization
use the mathematical identity 10^k = 2^k * 5^k to speed up the
divide-and-conquer decimal string conversion. dividing by 5^k
is faster than dividing by 10^k because 5^k has ~30% fewer bits
(log2(5) ≈ 2.32 vs log2(10) ≈ 3.32). the 2^k component is handled
with fast bit shifts.

benchmarks show 3-8% improvement for large numbers:
- 800K bits: 1.00s -> 0.97s
- 1.6M bits: 3.95s -> 3.84s
- 2.4M bits: 8.79s -> 8.46s

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 09:21:32 +09:00
Yukihiro "Matz" Matsumoto de3c1a1317 mruby-bigint: use lookup table for digit pair conversion in to_s
Apply Lemire's small table technique: use a 200-byte lookup table to
convert digit pairs (00-99) instead of computing each digit separately.
Reduces operations from 9 to 5 per 9-digit batch in the base case.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 09:21:29 +09:00
Yukihiro "Matz" Matsumoto 951a5753af mruby-bigint: rename mpz_to_s_dc_rec to mpz_to_s_dc_recur
Follow the codebase convention of using _recur suffix for recursive
functions (e.g., codedump_recur, dump_recur).

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-10 11:58:08 +09:00
Yukihiro "Matz" Matsumoto 48d5678f2a mruby-bigint: optimize to_s base case with batch digit extraction
Extract 9 decimal digits at once by dividing by 10^9 instead of 10.
This reduces the number of divisions in the base case by 9x, improving
performance of large bigint to_s conversion by approximately 2x.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-10 09:58:47 +09:00
Yukihiro "Matz" Matsumoto 990ff90fb4 mruby-bigint: add divide-and-conquer optimization for to_s
For base-10 conversion of numbers with >1000 digits, use a recursive
divide-and-conquer algorithm that splits the number using precomputed
powers of 10. This reduces complexity from O(n^2) to O(n log^2 n).

The algorithm:
1. Precompute 10^1, 10^2, 10^4, 10^8, ... by repeated squaring
2. Find the largest power that splits digits roughly in half
3. Divide by this power to get high and low parts
4. Recursively convert each part, padding low part with zeros
5. Base case: use simple divide-by-10 for <= 1000 digits

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-10 08:50:06 +09:00
Yukihiro "Matz" Matsumoto 9d04c74ed8 mruby-bigint: fix carry placement in uadd()
The final carry was stored at z->p[y->sz], but when x is larger
than y, this index falls within the already-computed result and
corrupts it. Store at z->p[i] instead, which correctly points to
max(x->sz, y->sz) after all loops complete.

This bug caused incorrect results when adding a small number to
an all-ones number with 1124+ limbs (35968+ bits).

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-10 08:30:18 +09:00
Yukihiro "Matz" Matsumoto 512fffdac8 mruby-bigint: fix division bug with non-standard qhat refinement
The udiv function had two buggy modifications to Knuth's Algorithm D:
1. A "three-limb pre-adjustment" that only decremented qhat once
2. A "3-limb refinement" loop with incorrect carry handling

These caused incorrect quotients for certain decimal divisions like
10^52 / 10^26. Restored standard Knuth Algorithm D which uses only
2-limb qhat refinement with correction via subtract and add-back.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 22:09:51 +09:00
Yukihiro "Matz" Matsumoto 1f590521b0 mruby-bigint: add sparse number optimization for multiplication
Numbers with few bits set (popcount <= 8) are multiplied using
shift-add instead of Karatsuba. This is O(k*n) where k is the
popcount, much faster than O(n^1.585) for sparse patterns like
2^100000 + 2^50000 commonly generated by fuzzers.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 17:14:44 +09:00
Yukihiro "Matz" Matsumoto 3e49b5187a mruby-bigint: add squaring optimization for internal multiplication
Add optimized squaring algorithm that exploits symmetry for ~1.5x speedup
over general multiplication. Includes both schoolbook and Karatsuba variants.

- mpz_sqr_basic_limbs: O(n(n+1)/2) multiplications instead of O(n^2)
- mpz_sqr_karatsuba: 3 recursive squarings instead of 3 multiplications
- mpz_sqr: high-level wrapper with fast paths for power-of-2 and all-ones

The optimization triggers when mpz_mul is called with identical pointers
(u == v), which occurs in internal operations like mpz_pow.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 15:17:36 +09:00
Yukihiro "Matz" Matsumoto ef64ca32a1 mruby-bigint: optimize multiplication for power-of-2 numbers
Add fast path for multiplying by powers of 2 (2^n). Uses left shift
instead of Karatsuba multiplication: x * 2^n = x << n.

This optimizes "mostly-zero" patterns common in fuzzing tests, where
numbers like 2^2097150 (single bit set) would otherwise trigger slow
Karatsuba multiplication.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 12:29:50 +09:00
Yukihiro "Matz" Matsumoto b7593cde15 mruby-bigint: optimize multiplication for all-ones numbers
Add fast path for multiplying numbers of form 2^n - 1 (all bits set).

Uses algebraic identities:
- (2^n - 1) * (2^m - 1) = 2^(n+m) - 2^n - 2^m + 1
- (2^n - 1) * y = (y << n) - y

These are O(n) operations instead of O(n^1.585) for Karatsuba.
Fuzzing test cases using all-ones patterns now complete in 0.01s
instead of 13+ seconds.

Also raises KARATSUBA_THRESHOLD from 8 to 32 for ~32% speedup
on general large number multiplication.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 12:25:22 +09:00
Yukihiro "Matz" Matsumoto df778e09d2 mruby-bigint: raise Karatsuba threshold from 8 to 32
Reduces recursion overhead for large number multiplication.
Benchmarks show ~32% speedup for million-bit operands.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 11:36:38 +09:00
Yukihiro "Matz" Matsumoto 0a5ec60e5c mruby-bigint: fix OOM by limiting left shift size in mpz_mul_2exp
Add MRB_BIGINT_BIT_LIMIT (1 billion bits / 128MB) to prevent
unreasonably large allocations when left-shifting by huge amounts.
Raises RangeError instead of attempting multi-GB allocations.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 08:33:58 +09:00
Yukihiro "Matz" Matsumoto a6b7f3b018 mruby-bigint: fix memory leak by trimming bitwise operation results
mpz_and, mpz_or, and mpz_xor were not calling trim() on their results,
causing inflated size values with trailing zero limbs. This led to
incorrect comparisons in ucmp() and caused udiv() to take wrong code
paths, resulting in memory leaks when exceptions occurred.

Also added defensive overflow checks in mpz_init_heap and udiv.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 08:18:15 +09:00
Yukihiro "Matz" Matsumoto 0e42c95df2 mruby-bigint: add exponent size check in mrb_bint_pow
prevent resource exhaustion when computing power with extremely large
exponents (e.g., 81.pow(51742871469327219)). the check estimates the
result size and raises RangeError if it would exceed 1 million bits.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-06 07:51:07 +09:00
Yukihiro "Matz" Matsumoto 53ee1a7826 bigint.c: fix memory leak in mpz_div_2exp
mpz_div_2exp() was calling mpz_init_heap() on output parameter z
without first freeing z's existing memory. When called from
mpz_barrett_reduce() with pre-allocated temporaries, this caused
memory leaks.

Add mpz_clear(ctx, z) before mpz_init_heap() in both affected code
paths, matching the pattern already used in mpz_mod_2exp().

Fixes ClusterFuzz issue detected with input "8.pow 7*2515881+186,8 ^4>>-509".

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-30 18:20:41 +09:00
Yukihiro "Matz" Matsumoto 8f259fb560 mruby-bigint, mruby-numeric-ext: fix Integer#pow with negative modulus
Support negative modulus in Integer#pow(exp, mod) with proper Ruby
semantics. Previously, negative modulus caused an infinite loop in
Barrett reduction. Now:

- Use absolute value of modulus for computation
- Apply signed modulo adjustment (result + m for non-zero result
  when m is negative)
- Add early return for zero base with positive exponent (0^n = 0)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-30 16:25:49 +09:00
Yukihiro "Matz" Matsumoto 54fbf6c3ec bigint.c: fix buffer overflow in mpz_div_2exp with large shift
When right-shifting by more bits than the number contains, the loop
condition `i < x->sz - digs` would underflow (since size_t is unsigned),
causing out-of-bounds memory access.

Fixed by checking if digs >= x->sz upfront and returning zero in that
case, since shifting right by more bits than the number has always
yields zero.

Discovered via ClusterFuzz with input "7<<78<<-772".

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-30 14:46:26 +09:00
Yukihiro "Matz" Matsumoto ff0e20453f bigint.c: fix GCD infinite loop and size handling bugs
Fixed three bugs that caused infinite loops in GCD calculations:

1. mpz_set_int() didn't shrink sz when setting a smaller value.
   mpz_realloc() only grows allocations, so setting a 1-limb value
   to an mpz_t with sz=3 would leave sz=3, breaking algorithms
   that depend on correct sz values.

2. mpz_set_uint64() had the same issue.

3. mpz_gcd() used mpz_init_set() which preserves the sign.
   GCD should work with absolute values since gcd(a,b) = gcd(|a|,|b|).
   With negative inputs, the sign would oscillate during mod operations,
   preventing the Euclidean algorithm from converging.

4. mpz_div_2exp() when e==0 and z==x would corrupt data by calling
   mpz_init_heap() which overwrites z->p before copying from x.

These bugs were discovered via ClusterFuzz with complex rational
number calculations.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-30 12:04:56 +09:00
Yukihiro "Matz" Matsumoto 27c9037d48 bigint.c: fix FPE caused by inconsistent zero sign state
Fix two functions that could create bigints with sn != 0 but value of 0:

- mpz_mod_limb: single-limb case set r->sn = x->sn even when result was 0
- mpz_mul_2exp: set z->sn = sn unconditionally after zero-producing ops

This inconsistent state caused GCD loop (!zero_p(&b)) to continue with
a zero divisor, eventually causing FPE in mpz_mod_limb with m = 0.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-29 23:39:30 +09:00
Yukihiro "Matz" Matsumoto 29b3405283 bigint.c: handle in-place operation in mpz_mod_2exp()
when mpz_mod_2exp() is called with z == x (in-place operation), the
function was calling mpz_clear(ctx, z) which freed x's memory, then
attempting to access x->p[i] - reading freed memory. this caused
Barrett reduction to produce incorrect results in modular
exponentiation.

the fix checks if z == x and handles in-place modification by
adjusting the size and masking directly, without clearing. this is
similar to the memory leak fix for pool→heap transitions.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 18:20:44 +09:00
Yukihiro "Matz" Matsumoto a5e25393b8 mruby-bigint: fix memory leak in mpz_mod_2exp by clearing before reinit
mpz_mod_2exp() was reinitializing its output parameter without clearing
existing heap memory. When the parameter contained heap allocations from
pool->heap transitions in mpz_mul()->mpz_realloc(), reinitializing would
overwrite the pointer and leak memory. Added mpz_clear() before each
mpz_init() or mpz_init_heap() call to properly free existing heap memory.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 18:20:44 +09:00
Yukihiro "Matz" Matsumoto 5ed0cd4ecb bigint.c: increase karatsuba scratch allocation safety margin
the previous fixed safety margin of 8 limbs was insufficient for certain
edge cases involving deep recursion levels in karatsuba multiplication,
as discovered by oss-fuzz. changed to proportional margin (~12.5% plus
fixed overhead of 16) that scales with input size.

this prevents potential buffer overruns in deeply nested karatsuba
multiplications while maintaining efficiency for typical cases.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 18:20:44 +09:00
Yukihiro "Matz" Matsumoto 3f2611ebcd bigint.c: fix buffer overflow in uadd with mismatched operand sizes
fix out-of-bounds read when adding bigints of different sizes. the
unrolled loop accessed both operands up to the size of x without
checking if y had enough limbs. when y->sz < x->sz, this caused reads
beyond y's allocation. now use min(x->sz, y->sz) for the overlap
region and handle remaining limbs from the larger operand separately.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-19 08:54:30 +09:00
Yukihiro "Matz" Matsumoto 281b38c0b6 bigint.c: add missing mrb_as_bint calls in mod and rem
mrb_bint_mod() and mrb_bint_rem() were missing conversion of the first
operand x to bigint before calling bint_as_mpz(). this caused crashes
when x was not already a bigint. added mrb_as_bint(mrb, x) calls to
ensure both operands are properly converted.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-18 10:14:13 +09:00
Yukihiro "Matz" Matsumoto 8113c0d24a bigint.c: fix division by zero in udiv normalization
after left-shifting the divisor in udiv(), trailing zero limbs could
remain, causing division by zero. added trim(&y) after ulshift() to
remove zero limbs, and safety check to handle edge cases where divisor
becomes zero after normalization.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-18 09:33:24 +09:00
Yukihiro "Matz" Matsumoto 74c0769319 mruby-bigint: fix memory leak in mpz_mod() when reusing initialized mpz_t
mpz_mod() was calling mpz_init_heap() on its output parameter, assuming it
was uninitialized. However, callers like mpz_powm_i() pass already-
initialized variables, causing the old allocations to leak. Changed to use
mpz_realloc() which properly handles both cases.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-15 22:40:29 +09:00
Yukihiro "Matz" Matsumoto 9133124bef mruby-bigint: add safety margin to karatsuba scratch allocation
prevents buffer overrun in karatsuba multiplication scratch space due to
rounding errors in recursive partitioning. empirically determined 8-limb
margin fixes valgrind-detected overrun with large exponentiations.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-15 22:40:21 +09:00
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
Meder Kydyraliev efd13872e4 Fix superfulous curly brackets 2025-10-23 21:17:36 +11: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 0c849e9020 mruby-bigint: add explicit cast to mp_limb for range-checked values
add explicit cast when assigning mrb_int to mp_limb. the value is
already validated to fit within mp_limb range by checking against
DIG_BASE, but explicit cast silences msvc warning c4244.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-16 17:06:31 +09:00
Yukihiro "Matz" Matsumoto 4f52868923 mruby-bigint: clean up preprocessor directives in mpz_clear
Co-authored-by: Claude <noreply@anthropic.com>
2025-10-13 11:30:15 +09:00
Yukihiro "Matz" Matsumoto f69fe329a9 mruby-bigint: fix mrb_bint_copy to properly clone bigints
mrb_bint_copy was creating reference to destination then destroying it
with mpz_init, causing copy to happen in orphaned memory. this made
clone return 0 instead of copying the bigint value.

fix extracts common mpz_t-to-rbigint transfer logic into bint_set
helper, used by both bint_new and mrb_bint_copy. eliminates code
duplication and properly copies source data to destination rbigint
structure, handling both embedded and heap storage cases.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-13 09:19:29 +09:00
Yukihiro "Matz" Matsumoto 003bdf5031 mruby-bigint: fix null pointer dereference in xor fast path
when xoring bigint with small integer, the fast path assumes source
bigint has allocated limbs. malformed bigints with sn > 0 but sz == 0
caused null pointer access. add defensive check to allocate storage
before accessing c.p[0].

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-13 09:09:47 +09:00
Yukihiro "Matz" Matsumoto 48e7592801 mruby-bigint: fix clang warning for struct initialization
add extra braces for nested struct initialization to satisfy
clang's -Wmissing-braces warning.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-11 13:59:54 +09:00
Yukihiro "Matz" Matsumoto 7f5904ea94 mruby-bigint: normalize mrb_bint_new_str return value
Fix mrb_bint_new_str to normalize bigint objects to regular integers
when possible. This ensures consistent object types for values that
fit in mrb_int range, fixing comparison failures in tests.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:10 +09:00
Yukihiro "Matz" Matsumoto 14d1ad0038 mruby-bigint: remove broken MSVC _umul128 optimization path
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>
2025-08-23 11:02:14 +09:00
Yukihiro "Matz" Matsumoto 589f256ffa mruby-bigint: fix carry calculation in MSVC 64-bit multiplication
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>
2025-08-23 10:49:50 +09:00
Yukihiro "Matz" Matsumoto e7925141fb mruby-bigint: replace non-ascii characters with ascii equivalents
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>
2025-08-23 10:49:50 +09:00
Yukihiro "Matz" Matsumoto 2580d69782 mruby-bigint: fix signed/unsigned comparison warning
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>
2025-08-22 22:28:07 +09:00
Yukihiro "Matz" Matsumoto 19db03ea67 mruby-bigint: fix vs 2022 compiler warnings
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>
2025-08-22 06:10:07 +09:00
Yukihiro "Matz" Matsumoto 4656cd4847 mrbgems: add newline before else keyword 2025-08-21 21:49:45 +09:00
Yukihiro "Matz" Matsumoto 8fd02f28a3 bigint.c: fix uninitialized embedded array in bint_new
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>
2025-08-21 21:48:21 +09:00