comparison src/userfunc.c @ 23285:112fa621b127 v8.2.2188

patch 8.2.2188: Vim9: crash when calling global function from :def function Commit: https://github.com/vim/vim/commit/cd45ed03bfdd7fac53d562ad402df74bd26e7754 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Dec 22 17:35:54 2020 +0100 patch 8.2.2188: Vim9: crash when calling global function from :def function Problem: Vim9: crash when calling global function from :def function. Solution: Set the outer context. Define the partial for the context on the original function. Use a refcount to keep track of which ufunc is using a dfunc. (closes #7525)
author Bram Moolenaar <Bram@vim.org>
date Tue, 22 Dec 2020 17:45:03 +0100
parents 35583da6397e
children c76240efdf02
comparison
equal deleted inserted replaced
23284:3d54c7fa353c 23285:112fa621b127
1258 fp->uf_cleared = TRUE; 1258 fp->uf_cleared = TRUE;
1259 1259
1260 // clear this function 1260 // clear this function
1261 func_clear_items(fp); 1261 func_clear_items(fp);
1262 funccal_unref(fp->uf_scoped, fp, force); 1262 funccal_unref(fp->uf_scoped, fp, force);
1263 if ((fp->uf_flags & FC_COPY) == 0) 1263 unlink_def_function(fp);
1264 clear_def_function(fp);
1265 } 1264 }
1266 1265
1267 /* 1266 /*
1268 * Free a function and remove it from the list of functions. Does not free 1267 * Free a function and remove it from the list of functions. Does not free
1269 * what a function contains, call func_clear() first. 1268 * what a function contains, call func_clear() first.
1305 } 1304 }
1306 1305
1307 /* 1306 /*
1308 * Copy already defined function "lambda" to a new function with name "global". 1307 * Copy already defined function "lambda" to a new function with name "global".
1309 * This is for when a compiled function defines a global function. 1308 * This is for when a compiled function defines a global function.
1310 * Caller should take care of adding a partial for a closure. 1309 */
1311 */ 1310 int
1312 ufunc_T * 1311 copy_func(char_u *lambda, char_u *global, ectx_T *ectx)
1313 copy_func(char_u *lambda, char_u *global)
1314 { 1312 {
1315 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL); 1313 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
1316 ufunc_T *fp = NULL; 1314 ufunc_T *fp = NULL;
1317 1315
1318 if (ufunc == NULL) 1316 if (ufunc == NULL)
1317 {
1319 semsg(_(e_lambda_function_not_found_str), lambda); 1318 semsg(_(e_lambda_function_not_found_str), lambda);
1320 else 1319 return FAIL;
1321 { 1320 }
1322 // TODO: handle ! to overwrite 1321
1323 fp = find_func(global, TRUE, NULL); 1322 // TODO: handle ! to overwrite
1324 if (fp != NULL) 1323 fp = find_func(global, TRUE, NULL);
1325 { 1324 if (fp != NULL)
1326 semsg(_(e_funcexts), global); 1325 {
1327 return NULL; 1326 semsg(_(e_funcexts), global);
1328 } 1327 return FAIL;
1329 1328 }
1330 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(global) + 1); 1329
1331 if (fp == NULL) 1330 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(global) + 1);
1332 return NULL; 1331 if (fp == NULL)
1333 1332 return FAIL;
1334 fp->uf_varargs = ufunc->uf_varargs; 1333
1335 fp->uf_flags = (ufunc->uf_flags & ~FC_VIM9) | FC_COPY; 1334 fp->uf_varargs = ufunc->uf_varargs;
1336 fp->uf_def_status = ufunc->uf_def_status; 1335 fp->uf_flags = (ufunc->uf_flags & ~FC_VIM9) | FC_COPY;
1337 fp->uf_dfunc_idx = ufunc->uf_dfunc_idx; 1336 fp->uf_def_status = ufunc->uf_def_status;
1338 if (ga_copy_strings(&ufunc->uf_args, &fp->uf_args) == FAIL 1337 fp->uf_dfunc_idx = ufunc->uf_dfunc_idx;
1339 || ga_copy_strings(&ufunc->uf_def_args, &fp->uf_def_args) 1338 if (ga_copy_strings(&ufunc->uf_args, &fp->uf_args) == FAIL
1340 == FAIL 1339 || ga_copy_strings(&ufunc->uf_def_args, &fp->uf_def_args)
1341 || ga_copy_strings(&ufunc->uf_lines, &fp->uf_lines) == FAIL) 1340 == FAIL
1341 || ga_copy_strings(&ufunc->uf_lines, &fp->uf_lines) == FAIL)
1342 goto failed;
1343
1344 fp->uf_name_exp = ufunc->uf_name_exp == NULL ? NULL
1345 : vim_strsave(ufunc->uf_name_exp);
1346 if (ufunc->uf_arg_types != NULL)
1347 {
1348 fp->uf_arg_types = ALLOC_MULT(type_T *, fp->uf_args.ga_len);
1349 if (fp->uf_arg_types == NULL)
1342 goto failed; 1350 goto failed;
1343 1351 mch_memmove(fp->uf_arg_types, ufunc->uf_arg_types,
1344 fp->uf_name_exp = ufunc->uf_name_exp == NULL ? NULL 1352 sizeof(type_T *) * fp->uf_args.ga_len);
1345 : vim_strsave(ufunc->uf_name_exp); 1353 }
1346 if (ufunc->uf_arg_types != NULL) 1354 if (ufunc->uf_def_arg_idx != NULL)
1347 { 1355 {
1348 fp->uf_arg_types = ALLOC_MULT(type_T *, fp->uf_args.ga_len); 1356 fp->uf_def_arg_idx = ALLOC_MULT(int, fp->uf_def_args.ga_len + 1);
1349 if (fp->uf_arg_types == NULL) 1357 if (fp->uf_def_arg_idx == NULL)
1350 goto failed; 1358 goto failed;
1351 mch_memmove(fp->uf_arg_types, ufunc->uf_arg_types, 1359 mch_memmove(fp->uf_def_arg_idx, ufunc->uf_def_arg_idx,
1352 sizeof(type_T *) * fp->uf_args.ga_len); 1360 sizeof(int) * fp->uf_def_args.ga_len + 1);
1353 } 1361 }
1354 if (ufunc->uf_def_arg_idx != NULL) 1362 if (ufunc->uf_va_name != NULL)
1355 { 1363 {
1356 fp->uf_def_arg_idx = ALLOC_MULT(int, fp->uf_def_args.ga_len + 1); 1364 fp->uf_va_name = vim_strsave(ufunc->uf_va_name);
1357 if (fp->uf_def_arg_idx == NULL) 1365 if (fp->uf_va_name == NULL)
1358 goto failed; 1366 goto failed;
1359 mch_memmove(fp->uf_def_arg_idx, ufunc->uf_def_arg_idx, 1367 }
1360 sizeof(int) * fp->uf_def_args.ga_len + 1); 1368 fp->uf_ret_type = ufunc->uf_ret_type;
1361 } 1369
1362 if (ufunc->uf_va_name != NULL) 1370 fp->uf_refcount = 1;
1363 { 1371 STRCPY(fp->uf_name, global);
1364 fp->uf_va_name = vim_strsave(ufunc->uf_va_name); 1372 hash_add(&func_hashtab, UF2HIKEY(fp));
1365 if (fp->uf_va_name == NULL) 1373
1366 goto failed; 1374 // the referenced dfunc_T is now used one more time
1367 } 1375 link_def_function(fp);
1368 fp->uf_ret_type = ufunc->uf_ret_type; 1376
1369 1377 // Create a partial to store the context of the function, if not done
1370 fp->uf_refcount = 1; 1378 // already.
1371 STRCPY(fp->uf_name, global); 1379 if ((ufunc->uf_flags & FC_CLOSURE) && ufunc->uf_partial == NULL)
1372 hash_add(&func_hashtab, UF2HIKEY(fp)); 1380 {
1373 } 1381 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
1374 return fp; 1382
1383 if (pt == NULL)
1384 goto failed;
1385 if (fill_partial_and_closure(pt, ufunc, ectx) == FAIL)
1386 goto failed;
1387 ufunc->uf_partial = pt;
1388 --pt->pt_refcount; // not referenced here yet
1389 }
1390 if (ufunc->uf_partial != NULL)
1391 {
1392 fp->uf_partial = ufunc->uf_partial;
1393 ++fp->uf_partial->pt_refcount;
1394 }
1395
1396 return OK;
1375 1397
1376 failed: 1398 failed:
1377 func_clear_free(fp, TRUE); 1399 func_clear_free(fp, TRUE);
1378 return NULL; 1400 return FAIL;
1379 } 1401 }
1380 1402
1381 static int funcdepth = 0; 1403 static int funcdepth = 0;
1382 1404
1383 /* 1405 /*
3513 fp->uf_flags &= ~FC_DEAD; 3535 fp->uf_flags &= ~FC_DEAD;
3514 #ifdef FEAT_PROFILE 3536 #ifdef FEAT_PROFILE
3515 fp->uf_profiling = FALSE; 3537 fp->uf_profiling = FALSE;
3516 fp->uf_prof_initialized = FALSE; 3538 fp->uf_prof_initialized = FALSE;
3517 #endif 3539 #endif
3518 clear_def_function(fp); 3540 unlink_def_function(fp);
3519 } 3541 }
3520 } 3542 }
3521 } 3543 }
3522 else 3544 else
3523 { 3545 {