Commit Graph

118 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 78fe8a0476 mruby-rational: fix infinite recursion with bigint comparison
rational_eq_b was using wrong struct fields (p1->numerator/denominator
which access i.num/i.den) for bigint-backed rationals that use b.num/b.den.
Also added missing MRB_TT_BIGINT case to prevent fallthrough to default
case which caused ping-pong recursion between Rational#== and Integer#==.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 19:23:15 +09:00
Yukihiro "Matz" Matsumoto bbcadd6bf9 mruby-rational: fix left shift overflow in rational_new_f
Shifting 1 left by MRB_INT_BIT-1 (e.g., 63 on 64-bit) bits into the sign
bit is undefined behavior. Change the overflow check from >= MRB_INT_BIT
to >= MRB_INT_BIT-1 to prevent this.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-05 17:47:57 +09:00
Yukihiro "Matz" Matsumoto a9825e92df mruby-rational: fix crash in rational_new_f with negative exponent
rational_new_b() expects both arguments to be bigints, but rational_new_f()
was passing an integer value for the numerator when the exponent was negative.
This caused a segfault in mrb_bint_reduce() which called RBIGINT() on the
integer value.

Test case: 5r**-92 (from oss-fuzz)

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-03 13:13:02 +09:00
Yukihiro "Matz" Matsumoto 5eca2fae1e rational.c: fix undefined behavior from large shift exponents
In rational_new_f(), the code performed ((mrb_int)1)<<exp without
checking if exp >= MRB_INT_BIT. Shifting by a value >= bit width
is undefined behavior in C.

Also fixed the negative exponent case which incorrectly used
deno >>= exp (right-shift by negative is UB). The correct logic
is deno <<= -exp to multiply denominator by 2^(-exp).

Both cases now check for overflow before shifting and fall back
to bigint operations when necessary.

Discovered via ClusterFuzz with input "92r**11".

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-30 14:28:44 +09:00
Yukihiro "Matz" Matsumoto ce570c28bb mruby-rational: inline int_lshift into rational_new_f
Remove the static int_lshift function and directly call mrb_bint_lshift
at the only call site. This simplifies the code and avoids static
function name collision with src/numeric.c for future amalgamation
support.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 08:50:30 +09:00
Yukihiro "Matz" Matsumoto 1cf225dfbe mruby-rational: add comprehensive call-seq documentation for Rational methods
Added complete call-seq documentation for all Rational methods in
mrblib/rational.rb (4 methods):

## Rational Class Methods:

- inspect: returns string representation for debugging with parentheses
  format, showing the rational value in "(numerator/denominator)" form

- to_s: returns string representation in "numerator/denominator" format
  for display and conversion purposes

- <=>: spaceship operator for comparison with other numeric types,
  returns -1/0/+1 for less/equal/greater comparisons, enables Comparable
  module functionality with proper nil handling for incomparable values

## Numeric Extension Methods:

- to_r: converts any numeric value to rational representation with
  denominator of 1, part of the standard numeric conversion protocol

Co-authored-by: Atlassian Rovo Dev
2025-08-14 10:52:45 +09:00
Yukihiro "Matz" Matsumoto 86ef7a912d mruby-rational (int_lshift): check before actual left bit shift 2025-05-21 13:25:08 +09:00
Yukihiro "Matz" Matsumoto f4b01ed19e mruby-rational (int_lshift): exponential may be bigger than int bits 2025-05-21 10:40:02 +09:00
Yukihiro "Matz" Matsumoto d908daa8b9 mruby-rational (rational_hash): hash value is uint32_t 2025-03-25 08:10:49 +09:00
Yukihiro "Matz" Matsumoto e5e8dd11c0 mruby-rational: make Rational() private 2025-03-07 17:17:45 +09:00
Yukihiro "Matz" Matsumoto 8276143f03 object.h: remove MRB_SET_FROZEN_FLAG/MRB_UNSET_FROZEN_FLAG macros
Simple `o->frozen = 1/0` now works.
2025-01-07 13:56:30 +09:00
Yukihiro "Matz" Matsumoto 3885e14049 mruby-rational: explicitly add return for error cases too 2024-10-31 14:06:10 +09:00
Yukihiro "Matz" Matsumoto 7b5608e78a mruby-rational: refactor float to rational conversion
- the function `float_decode_internal` was removed
- simplified `rational_new_f()`
- do not need to call `ldexp`
- allocate less bigint objects
2024-10-15 21:10:11 +09:00
Yukihiro "Matz" Matsumoto 51b11a6919 mruby-rational: add comments
We used `mrb_bint_mul(mrb, n, ONE)` to normalize `n`. The code confused
ChatGPT that could not read the intention.
2024-10-15 21:10:10 +09:00
Yukihiro "Matz" Matsumoto 763c9cba03 mruby-rational (int_lshift): add cast to stop overflow warning 2024-10-11 08:44:12 +09:00
Yukihiro "Matz" Matsumoto 453e9eabf0 mruby-rational (rat_add_b): might have called rational_new_b with int
`rational_new_b` should be called with bigint objects.
2024-10-10 07:55:51 +09:00
Yukihiro "Matz" Matsumoto afefb5261b mruby-rational (rat_sub_b): avoid normalization of big integers 2024-09-15 03:04:32 +09:00
Yukihiro "Matz" Matsumoto 50225acec4 mruby-rational (rat_mul_b): should not normalize multiplication results 2024-09-15 02:50:57 +09:00
Yukihiro "Matz" Matsumoto 4a71d4604e mruby-rational: add typecast to check if a value is fit in mrb_int 2024-08-27 22:48:40 +09:00
Yukihiro "Matz" Matsumoto 4ea6d74d83 mruby-rational: introduce the constants ONE and ZERO 2024-08-21 18:38:51 +09:00
Yukihiro "Matz" Matsumoto 39b9a1a06a mruby-rational (rational_new): fix compilation condition 2024-08-17 16:29:51 +09:00
Yukihiro "Matz" Matsumoto 44908e5cba mruby-rational: support bigint numerators & denominators 2024-08-16 15:12:03 +09:00
Yukihiro "Matz" Matsumoto fcab7ef377 numeric.c (int_div): fixed a bug regarding bigint / non-integer
Non-integer means Complex or Rational.
2024-07-15 21:35:42 +09:00
Yukihiro "Matz" Matsumoto 3b9aec90dd mruby-rational: define <=> method in Ruby, not in C 2024-06-17 08:02:42 +09:00
Yukihiro "Matz" Matsumoto b44dc1c0b9 mruby-rational: use presym for initialization 2024-06-14 06:17:20 +09:00
Yukihiro "Matz" Matsumoto 7c2be58e2a mruby-rational (rational_pow): fix wrong power calculation
`a/b ** -n` can be calculated by `b/a ** n` for correctness.
2024-05-25 16:39:32 +09:00
Yukihiro "Matz" Matsumoto d148bf8c0b mruby-rational: adjust local variable declarations with initialization 2024-05-25 16:39:32 +09:00
Yukihiro "Matz" Matsumoto 6e09555749 Merge pull request #6150 from dearblue/itself
Introduce `mrb_obj_itself()`
2024-02-01 16:15:42 +09:00
dearblue 3111990089 Introduce mrb_obj_itself()
Some method definitions were changed to use this function.
2024-01-20 22:07:29 +09:00
dearblue 35375257f6 Remove unnecessary Rational._new method 2024-01-20 21:52:49 +09:00
Yukihiro "Matz" Matsumoto 2cf6f7f5c7 mruby-rational: move misplaced #ifndef MRB_NO_FLOAT 2024-01-08 07:19:30 +09:00
dearblue 8ecfacefca Prohibit Class#allocate in a different way
The method introduced by #5979 causes a fault by swapping classes.

```console
% bin/mruby -e 'Method = Proc; p Object.method(:inspect)'
zsh: segmentation fault (core dumped)  bin/mruby -e 'Method = Proc; p Object.method(:inspect)'
```

After applying this patch, a `TypeError` exception will be raised.

```console
% bin/mruby -e 'Method = Proc; p Object.method(:inspect)'
trace (most recent call last):
        [1] -e:1
-e:1:in method: allocation failure of Proc (TypeError)
```

However, if the `mrb_vtype` is the same object, the same care must still be taken as before.

```console
% bin/mruby -e 'Method = Binding; p method(:puts).eval("12345")'
trace (most recent call last):
        [1] -e:1
-e:1:in eval: wrong argument type nil (expected Proc) (TypeError)
```
2023-12-22 21:59:34 +09:00
Yukihiro "Matz" Matsumoto 89f7bb1056 use more lightweight mrb_funcall_argv instead of mrb_funcall_id 2023-06-12 14:22:04 +09:00
Yukihiro "Matz" Matsumoto 795044f82c internal.h: add mrb_check_num_exact prototype to the header 2023-05-30 08:54:05 +09:00
dearblue d3128ce58a Allow Class#allocate to be prohibited
Calling `Class#allocate` with `UnboundMethod#bind_call` usually succeeds without problems.
If this behavior does not make us happy, we can now prohibit it with `MRB_SET_INSTANCE_TT(klass, MRB_TT_UNDEF)`.

At the same time, it applies to the `Binding`, `Complex`, `Data`, `Float`, `Integer`, `Method`, `Rational` and `UnboundMethod` classes.
2023-04-09 21:14:07 +09:00
Yukihiro "Matz" Matsumoto 9c5dc42e59 small cosmetic changes.
I prefer `i++` style unless absolutely necessary.
This commit is an addition to 41e4148.
2022-11-19 17:11:56 +09:00
fn ⌃ ⌥ f3ec5f744f rational.c: implement nil.to_r and Float#to_r 2022-10-24 17:31:52 -07:00
Yukihiro "Matz" Matsumoto 579379c517 rational.c (rational_hash): generate hash code from rational numbers. 2022-08-06 06:43:42 +09:00
Yukihiro "Matz" Matsumoto 6da34fa735 numeric.c (int_div): add checks for division by zero. 2022-07-29 17:48:02 +09:00
Yukihiro "Matz" Matsumoto 67f47c9b42 rational.c (mrb_rational_copy): allow copying of rational numbers. 2022-07-11 11:19:22 +09:00
Yukihiro "Matz" Matsumoto cf7aa74f7c mruby-rational/rational.c: update error message. 2022-06-21 22:17:17 +09:00
Yukihiro "Matz" Matsumoto 019a2ddff4 mruby-rational/rational.c: implement Rational#**; close #5724 2022-06-21 16:53:17 +09:00
Yukihiro "Matz" Matsumoto 04de280997 mruby-rational/rational.c: wrap prototype with mrb_float
When `MRB_NO_FLOAT` is defined, `mrb_float` is not defined.
2022-06-21 16:37:32 +09:00
Yukihiro "Matz" Matsumoto 6f78cd6c99 mruby-rational/rational.c: remove unused prototype [ci skip] 2022-06-21 14:01:38 +09:00
dearblue 23611332d9 Introduced mrb_static_assert_object_size()
Asserts the size of the object structure is less than or equal to 6 words.
2022-05-28 11:08:27 +09:00
Yukihiro "Matz" Matsumoto fe03e01078 numeric.c: enhance integer division to support Rational and Complex.
No longer need to override division methods in mrbgems.
2022-03-18 12:27:46 +09:00
Yukihiro "Matz" Matsumoto 2772e07dc8 rational.c: avoid mrb_funcall; call functions directly. 2022-03-12 13:31:38 +09:00
Yukihiro "Matz" Matsumoto 10001ff67f rational.c, complex.c: expose arithmetic operation functions.
* mrb_{rational,complex}_{add,sub,mul,div}
2022-03-12 08:35:07 +09:00
Yukihiro "Matz" Matsumoto b118ba9fb3 rational.c: avoid indirect calls using mrb_funcall(). 2022-02-25 17:53:55 +09:00
Yukihiro "Matz" Matsumoto c088af87b8 object.c: Call functions directly from mrb_ensure_int_type(); #5622 2022-01-05 19:00:14 +09:00