comparison src/evalfunc.c @ 22766:a7082e865ffd v8.2.1931

patch 8.2.1931: Vim9: arguments of extend() not checked at compile time Commit: https://github.com/vim/vim/commit/fbcbffe1ad327f4f0da518abfd5fd7be7fec22b5 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Oct 31 19:33:38 2020 +0100 patch 8.2.1931: Vim9: arguments of extend() not checked at compile time Problem: Vim9: arguments of extend() not checked at compile time. Solution: Add argument type checking for extend().
author Bram Moolenaar <Bram@vim.org>
date Sat, 31 Oct 2020 19:45:03 +0100
parents ad54acb1bf2c
children 3996539f38b4
comparison
equal deleted inserted replaced
22765:e484fdc8ca20 22766:a7082e865ffd
274 // A function to check one argument type. The first argument is the type to 274 // A function to check one argument type. The first argument is the type to
275 // check. If needed, other argument types can be obtained with the context. 275 // check. If needed, other argument types can be obtained with the context.
276 // E.g. if "arg_idx" is 1, then (type - 1) is the first argument type. 276 // E.g. if "arg_idx" is 1, then (type - 1) is the first argument type.
277 typedef int (*argcheck_T)(type_T *, argcontext_T *); 277 typedef int (*argcheck_T)(type_T *, argcontext_T *);
278 278
279 /*
280 * Check "type" is a float or a number.
281 */
279 static int 282 static int
280 arg_float_or_nr(type_T *type, argcontext_T *context) 283 arg_float_or_nr(type_T *type, argcontext_T *context)
281 { 284 {
282 if (type->tt_type == VAR_ANY 285 if (type->tt_type == VAR_ANY
283 || type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER) 286 || type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER)
284 return OK; 287 return OK;
285 arg_type_mismatch(&t_number, type, context->arg_idx + 1); 288 arg_type_mismatch(&t_number, type, context->arg_idx + 1);
286 return FAIL; 289 return FAIL;
287 } 290 }
288 291
292 /*
293 * Check "type" is a number.
294 */
289 static int 295 static int
290 arg_number(type_T *type, argcontext_T *context) 296 arg_number(type_T *type, argcontext_T *context)
291 { 297 {
292 return check_type(&t_number, type, TRUE, context->arg_idx + 1); 298 return check_type(&t_number, type, TRUE, context->arg_idx + 1);
293 } 299 }
294 300
301 /*
302 * Check "type" is a string.
303 */
304 static int
305 arg_string(type_T *type, argcontext_T *context)
306 {
307 return check_type(&t_string, type, TRUE, context->arg_idx + 1);
308 }
309
310 /*
311 * Check "type" is a list or a blob.
312 */
295 static int 313 static int
296 arg_list_or_blob(type_T *type, argcontext_T *context) 314 arg_list_or_blob(type_T *type, argcontext_T *context)
297 { 315 {
298 if (type->tt_type == VAR_ANY 316 if (type->tt_type == VAR_ANY
299 || type->tt_type == VAR_LIST || type->tt_type == VAR_BLOB) 317 || type->tt_type == VAR_LIST || type->tt_type == VAR_BLOB)
301 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1); 319 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
302 return FAIL; 320 return FAIL;
303 } 321 }
304 322
305 /* 323 /*
306 * Check the type is an item of the list or blob of the previous arg. 324 * Check "type" is a list or a dict.
325 */
326 static int
327 arg_list_or_dict(type_T *type, argcontext_T *context)
328 {
329 if (type->tt_type == VAR_ANY
330 || type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
331 return OK;
332 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
333 return FAIL;
334 }
335
336 /*
337 * Check "type" is the same type as the previous argument
338 * Must not be used for the first argcheck_T entry.
339 */
340 static int
341 arg_same_as_prev(type_T *type, argcontext_T *context)
342 {
343 type_T *prev_type = context->arg_types[context->arg_idx - 1];
344
345 return check_type(prev_type, type, TRUE, context->arg_idx + 1);
346 }
347
348 /*
349 * Check "type" is an item of the list or blob of the previous arg.
307 * Must not be used for the first argcheck_T entry. 350 * Must not be used for the first argcheck_T entry.
308 */ 351 */
309 static int 352 static int
310 arg_item_of_prev(type_T *type, argcontext_T *context) 353 arg_item_of_prev(type_T *type, argcontext_T *context)
311 { 354 {
322 365
323 return check_type(expected, type, TRUE, context->arg_idx + 1); 366 return check_type(expected, type, TRUE, context->arg_idx + 1);
324 } 367 }
325 368
326 /* 369 /*
370 * Check "type" which is the third argument of extend().
371 */
372 static int
373 arg_extend3(type_T *type, argcontext_T *context)
374 {
375 type_T *first_type = context->arg_types[context->arg_idx - 2];
376
377 if (first_type->tt_type == VAR_LIST)
378 return arg_number(type, context);
379 if (first_type->tt_type == VAR_DICT)
380 return arg_string(type, context);
381 return OK;
382 }
383
384
385 /*
327 * Lists of functions that check the argument types of a builtin function. 386 * Lists of functions that check the argument types of a builtin function.
328 */ 387 */
329 argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; 388 argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
389 argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
390 argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
330 argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; 391 argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
331 392
332 /* 393 /*
333 * Functions that return the return type of a builtin function. 394 * Functions that return the return type of a builtin function.
334 * Note that "argtypes" is NULL if "argcount" is zero. 395 * Note that "argtypes" is NULL if "argcount" is zero.
565 { 626 {
566 {"abs", 1, 1, FEARG_1, arg1_float_or_nr, 627 {"abs", 1, 1, FEARG_1, arg1_float_or_nr,
567 ret_any, FLOAT_FUNC(f_abs)}, 628 ret_any, FLOAT_FUNC(f_abs)},
568 {"acos", 1, 1, FEARG_1, NULL, 629 {"acos", 1, 1, FEARG_1, NULL,
569 ret_float, FLOAT_FUNC(f_acos)}, 630 ret_float, FLOAT_FUNC(f_acos)},
570 {"add", 2, 2, FEARG_1, NULL, 631 {"add", 2, 2, FEARG_1, NULL /* arg2_listblob_item */,
571 ret_first_arg, f_add}, 632 ret_first_arg, f_add},
572 {"and", 2, 2, FEARG_1, NULL, 633 {"and", 2, 2, FEARG_1, NULL,
573 ret_number, f_and}, 634 ret_number, f_and},
574 {"append", 2, 2, FEARG_2, NULL, 635 {"append", 2, 2, FEARG_2, NULL,
575 ret_number, f_append}, 636 ret_number, f_append},
791 ret_float, FLOAT_FUNC(f_exp)}, 852 ret_float, FLOAT_FUNC(f_exp)},
792 {"expand", 1, 3, FEARG_1, NULL, 853 {"expand", 1, 3, FEARG_1, NULL,
793 ret_any, f_expand}, 854 ret_any, f_expand},
794 {"expandcmd", 1, 1, FEARG_1, NULL, 855 {"expandcmd", 1, 1, FEARG_1, NULL,
795 ret_string, f_expandcmd}, 856 ret_string, f_expandcmd},
796 {"extend", 2, 3, FEARG_1, NULL, 857 {"extend", 2, 3, FEARG_1, arg23_extend,
797 ret_first_arg, f_extend}, 858 ret_first_arg, f_extend},
798 {"feedkeys", 1, 2, FEARG_1, NULL, 859 {"feedkeys", 1, 2, FEARG_1, NULL,
799 ret_void, f_feedkeys}, 860 ret_void, f_feedkeys},
800 {"file_readable", 1, 1, FEARG_1, NULL, // obsolete 861 {"file_readable", 1, 1, FEARG_1, NULL, // obsolete
801 ret_number, f_filereadable}, 862 ret_number, f_filereadable},