mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-proc-ext: Proc#curry should check max arity for lambdas
`lambda {|a, b=nil|}.curry(3)` used to silently return a curried Proc;
CRuby raises `ArgumentError` because the lambda accepts at most 2 args.
Use `self.parameters` to compute the upper bound (count `:req`/`:opt`
entries, unbounded if `:rest`/`:keyrest` is present) and add the
corresponding range check alongside the existing minimum check.
close #2855
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -75,9 +75,22 @@ class Proc
|
||||
if lambda?
|
||||
type = :lambda
|
||||
self_arity = self.arity
|
||||
if (self_arity >= 0 && arity != self_arity) ||
|
||||
(self_arity < 0 && abs[self_arity] > arity)
|
||||
raise ArgumentError, "wrong number of arguments (given #{arity}, expected #{abs[self_arity]})"
|
||||
min_req = abs[self_arity]
|
||||
if self_arity < 0
|
||||
max_arity = 0
|
||||
has_rest = false
|
||||
self.parameters.each do |p|
|
||||
case p[0]
|
||||
when :rest, :keyrest then has_rest = true
|
||||
when :req, :opt then max_arity += 1
|
||||
end
|
||||
end
|
||||
if arity < min_req || (!has_rest && arity > max_arity)
|
||||
expected = (!has_rest && max_arity != min_req) ? "#{min_req}..#{max_arity}" : min_req.to_s
|
||||
raise ArgumentError, "wrong number of arguments (given #{arity}, expected #{expected})"
|
||||
end
|
||||
elsif arity != self_arity
|
||||
raise ArgumentError, "wrong number of arguments (given #{arity}, expected #{self_arity})"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -64,6 +64,13 @@ assert('Proc#curry') do
|
||||
|
||||
assert_false(proc{}.curry.lambda?)
|
||||
assert_true(lambda{}.curry.lambda?)
|
||||
|
||||
# #2855: lambda with optional param: curry must validate against max arity
|
||||
l = lambda {|a, b=nil|}
|
||||
assert_raise(ArgumentError) { l.curry(3) } # over max
|
||||
assert_kind_of Proc, l.curry(2) # within range
|
||||
assert_kind_of Proc, l.curry(1) # at min
|
||||
assert_kind_of Proc, lambda {|a, *b|}.curry(99) # rest -> unbounded
|
||||
end
|
||||
|
||||
assert('Proc#parameters') do
|
||||
|
||||
Reference in New Issue
Block a user