diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-05-24 00:00:42 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-05-24 00:00:42 -0700 |
commit | 8c249e7aa60489b353658c934b0668a045d7fa0c (patch) | |
tree | aede72783ea6714efeed6e1168265a0478592b7a /lib.c | |
parent | 0a9f9ae8d11a43108f0b8fffae954da4f9539b7f (diff) | |
download | txr-8c249e7aa60489b353658c934b0668a045d7fa0c.tar.gz txr-8c249e7aa60489b353658c934b0668a045d7fa0c.tar.bz2 txr-8c249e7aa60489b353658c934b0668a045d7fa0c.zip |
lib: fix issue uncovered by recent vm CALL insn change.
The functions funcall1 through funcall4, when invoking a VM
function, are not defending against the case when there
are more arguments than the function can take.
As a result, some :mass-delegate tests in tests/012/oop.tl
are failing. They expect an :error result, but the calls
are succeeding in spite of passing too many parameters
via the delegate interface.
The tests/012/lambda.tl suite should catch this, but
it has unfortunate weaknesses.
* lib.c (funcall1, funcall2, funcall3, funcall4):
When dispatching the general VM case via
vm_execute_closure, check that if the closure has
fewer fixed parameters than arguments we are passing,
it must be variadic, or else there is an error.
* tests/012/lambda.tl (call-lambda-fixed): New function.
Unlike call-lambda, which uses the apply dot syntax,
this switches on the argument list shape and dispatches
direct calls. These compile to the CALL instruction
cases with four arguments or less which will exercise
funcall, funcall1, ... funcall4. Also, adding some missing
test cases that probe behavior with excess arguments.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 18 |
1 files changed, 13 insertions, 5 deletions
@@ -8525,7 +8525,9 @@ val funcall1(val fun, val arg) case 4: return vm_funcall4(fun, z(arg), colon_k, colon_k, colon_k); default: - { + if (!fun->f.variadic && fun->f.fixparam == 0) { + wrongargs(fun); + } else { args_decl_constsize(args, ARGS_MIN); args_add(args, arg); return vm_execute_closure(fun, args); @@ -8604,7 +8606,9 @@ val funcall2(val fun, val arg1, val arg2) case 4: return vm_funcall4(fun, z(arg1), z(arg2), colon_k, colon_k); default: - { + if (!fun->f.variadic && fun->f.fixparam < 2) { + wrongargs(fun); + } else { args_decl_constsize(args, ARGS_MIN); args_add2(args, arg1, arg2); return vm_execute_closure(fun, args); @@ -8685,7 +8689,9 @@ val funcall3(val fun, val arg1, val arg2, val arg3) case 4: return vm_funcall4(fun, z(arg1), z(arg2), z(arg3), colon_k); default: - { + if (!fun->f.variadic && fun->f.fixparam < 3) { + wrongargs(fun); + } else { args_decl_constsize(args, ARGS_MIN); args_add3(args, arg1, arg2, arg3); return vm_execute_closure(fun, args); @@ -8761,12 +8767,14 @@ val funcall4(val fun, val arg1, val arg2, val arg3, val arg4) wrongargs(fun); if (fun->f.functype == FVM) { - if (fun->f.fixparam == 4) + if (fun->f.fixparam == 4) { return vm_funcall4(fun, z(arg1), z(arg2), z(arg3), z(arg4)); - else { + } else if (fun->f.variadic || fun->f.fixparam > 4) { args_decl(args, ARGS_MIN); args_add4(args, arg1, arg2, arg3, arg4); return vm_execute_closure(fun, args); + } else { + wrongargs(fun); } } |