comparison src/vim9execute.c @ 31573:fc9ce07dc8a4 v9.0.1119

patch 9.0.1119: type of arguments not checked when calling a partial Commit: https://github.com/vim/vim/commit/0d89d8ae89c861572496c5ae9683d986b28c957b Author: Bram Moolenaar <Bram@vim.org> Date: Sat Dec 31 14:01:24 2022 +0000 patch 9.0.1119: type of arguments not checked when calling a partial Problem: Type of arguments not checked when calling a partial. Solution: Give an error for a wrong argument type. (closes https://github.com/vim/vim/issues/11753)
author Bram Moolenaar <Bram@vim.org>
date Sat, 31 Dec 2022 15:15:02 +0100
parents 67d9fbe516a3
children 53c3df37a2b0
comparison
equal deleted inserted replaced
31572:d16bf8370f60 31573:fc9ce07dc8a4
375 ptref = ptref->pt_outer_partial; 375 ptref = ptref->pt_outer_partial;
376 return &ptref->pt_outer; 376 return &ptref->pt_outer;
377 } 377 }
378 378
379 /* 379 /*
380 * Check "argcount" arguments on the stack against what "ufunc" expects.
381 * "off" is the offset of arguments on the stack.
382 * Return OK or FAIL.
383 */
384 static int
385 check_ufunc_arg_types(ufunc_T *ufunc, int argcount, int off, ectx_T *ectx)
386 {
387 if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
388 {
389 typval_T *argv = STACK_TV_BOT(0) - argcount - off;
390
391 // The function can change at runtime, check that the argument
392 // types are correct.
393 for (int i = 0; i < argcount; ++i)
394 {
395 type_T *type = NULL;
396
397 // assume a v:none argument, using the default value, is always OK
398 if (argv[i].v_type == VAR_SPECIAL
399 && argv[i].vval.v_number == VVAL_NONE)
400 continue;
401
402 if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
403 type = ufunc->uf_arg_types[i];
404 else if (ufunc->uf_va_type != NULL)
405 type = ufunc->uf_va_type->tt_member;
406 if (type != NULL && check_typval_arg_type(type,
407 &argv[i], NULL, i + 1) == FAIL)
408 return FAIL;
409 }
410 }
411 return OK;
412 }
413
414 /*
380 * Call compiled function "cdf_idx" from compiled code. 415 * Call compiled function "cdf_idx" from compiled code.
381 * This adds a stack frame and sets the instruction pointer to the start of the 416 * This adds a stack frame and sets the instruction pointer to the start of the
382 * called function. 417 * called function.
383 * If "pt_arg" is not NULL use "pt_arg->pt_outer" for ec_outer_ref->or_outer. 418 * If "pt_arg" is not NULL use "pt_arg->pt_outer" for ec_outer_ref->or_outer.
384 * 419 *
496 semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few, 531 semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few,
497 missing), missing); 532 missing), missing);
498 return FAIL; 533 return FAIL;
499 } 534 }
500 535
536 // Check the argument types.
537 if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL)
538 return FAIL;
539
501 // Reserve space for: 540 // Reserve space for:
502 // - missing arguments 541 // - missing arguments
503 // - stack frame 542 // - stack frame
504 // - local variables 543 // - local variables
505 // - if needed: a counter for number of closures created in 544 // - if needed: a counter for number of closures created in
1343 return FAIL; // bail out if loading the script caused an error 1382 return FAIL; // bail out if loading the script caused an error
1344 } 1383 }
1345 1384
1346 if (ufunc != NULL) 1385 if (ufunc != NULL)
1347 { 1386 {
1348 if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL) 1387 if (check_ufunc_arg_types(ufunc, argcount, 0, ectx) == FAIL)
1349 { 1388 return FAIL;
1350 int i;
1351 typval_T *argv = STACK_TV_BOT(0) - argcount;
1352
1353 // The function can change at runtime, check that the argument
1354 // types are correct.
1355 for (i = 0; i < argcount; ++i)
1356 {
1357 type_T *type = NULL;
1358
1359 if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
1360 type = ufunc->uf_arg_types[i];
1361 else if (ufunc->uf_va_type != NULL)
1362 type = ufunc->uf_va_type->tt_member;
1363 if (type != NULL && check_typval_arg_type(type,
1364 &argv[i], NULL, i + 1) == FAIL)
1365 return FAIL;
1366 }
1367 }
1368 1389
1369 return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict); 1390 return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
1370 } 1391 }
1371 1392
1372 return FAIL; 1393 return FAIL;