Mercurial > vim
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; |