comparison src/userfunc.c @ 20709:a2262c80a4e0 v8.2.0908

patch 8.2.0908: crash when changing the function table while listing it Commit: https://github.com/vim/vim/commit/3fffa97159a427067b60c80ed4645e168cc5c4bd Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jun 5 21:06:10 2020 +0200 patch 8.2.0908: crash when changing the function table while listing it Problem: Crash when changing the function table while listing it. Solution: Bail out when the function table changes. (closes https://github.com/vim/vim/issues/6209)
author Bram Moolenaar <Bram@vim.org>
date Fri, 05 Jun 2020 21:15:04 +0200
parents 1ea55bad1234
children 9faab49c880f
comparison
equal deleted inserted replaced
20708:66b20c503d2c 20709:a2262c80a4e0
2368 p = vim_strchr(name, '_'); 2368 p = vim_strchr(name, '_');
2369 if (p != NULL) 2369 if (p != NULL)
2370 return p + 1; 2370 return p + 1;
2371 } 2371 }
2372 return NULL; 2372 return NULL;
2373 }
2374
2375 /*
2376 * List functions. When "regmatch" is NULL all of then.
2377 * Otherwise functions matching "regmatch".
2378 */
2379 static void
2380 list_functions(regmatch_T *regmatch)
2381 {
2382 long_u used = func_hashtab.ht_used;
2383 long_u todo = used;
2384 hashitem_T *ht_array = func_hashtab.ht_array;
2385 hashitem_T *hi;
2386
2387 for (hi = ht_array; todo > 0 && !got_int; ++hi)
2388 {
2389 if (!HASHITEM_EMPTY(hi))
2390 {
2391 ufunc_T *fp = HI2UF(hi);
2392
2393 --todo;
2394 if ((fp->uf_flags & FC_DEAD) == 0
2395 && (regmatch == NULL
2396 ? !message_filtered(fp->uf_name)
2397 && !func_name_refcount(fp->uf_name)
2398 : !isdigit(*fp->uf_name)
2399 && vim_regexec(regmatch, fp->uf_name, 0)))
2400 {
2401 list_func_head(fp, FALSE);
2402 if (used != func_hashtab.ht_used
2403 || ht_array != func_hashtab.ht_array)
2404 {
2405 emsg(_("E454: function list was modified"));
2406 return;
2407 }
2408 }
2409 }
2410 }
2373 } 2411 }
2374 2412
2375 /* 2413 /*
2376 * ":function" also supporting nested ":def". 2414 * ":function" also supporting nested ":def".
2377 * Returns a pointer to the function or NULL if no function defined. 2415 * Returns a pointer to the function or NULL if no function defined.
2405 char nesting_def[MAX_FUNC_NESTING]; 2443 char nesting_def[MAX_FUNC_NESTING];
2406 dictitem_T *v; 2444 dictitem_T *v;
2407 funcdict_T fudi; 2445 funcdict_T fudi;
2408 static int func_nr = 0; // number for nameless function 2446 static int func_nr = 0; // number for nameless function
2409 int paren; 2447 int paren;
2410 int todo;
2411 hashitem_T *hi; 2448 hashitem_T *hi;
2412 int do_concat = TRUE; 2449 int do_concat = TRUE;
2413 linenr_T sourcing_lnum_off; 2450 linenr_T sourcing_lnum_off;
2414 linenr_T sourcing_lnum_top; 2451 linenr_T sourcing_lnum_top;
2415 int is_heredoc = FALSE; 2452 int is_heredoc = FALSE;
2426 * ":function" without argument: list functions. 2463 * ":function" without argument: list functions.
2427 */ 2464 */
2428 if (ends_excmd2(eap->cmd, eap->arg)) 2465 if (ends_excmd2(eap->cmd, eap->arg))
2429 { 2466 {
2430 if (!eap->skip) 2467 if (!eap->skip)
2431 { 2468 list_functions(NULL);
2432 todo = (int)func_hashtab.ht_used;
2433 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
2434 {
2435 if (!HASHITEM_EMPTY(hi))
2436 {
2437 --todo;
2438 fp = HI2UF(hi);
2439 if ((fp->uf_flags & FC_DEAD)
2440 || message_filtered(fp->uf_name))
2441 continue;
2442 if (!func_name_refcount(fp->uf_name))
2443 list_func_head(fp, FALSE);
2444 }
2445 }
2446 }
2447 eap->nextcmd = check_nextcmd(eap->arg); 2469 eap->nextcmd = check_nextcmd(eap->arg);
2448 return NULL; 2470 return NULL;
2449 } 2471 }
2450 2472
2451 /* 2473 /*
2463 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC); 2485 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
2464 *p = c; 2486 *p = c;
2465 if (regmatch.regprog != NULL) 2487 if (regmatch.regprog != NULL)
2466 { 2488 {
2467 regmatch.rm_ic = p_ic; 2489 regmatch.rm_ic = p_ic;
2468 2490 list_functions(&regmatch);
2469 todo = (int)func_hashtab.ht_used;
2470 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
2471 {
2472 if (!HASHITEM_EMPTY(hi))
2473 {
2474 --todo;
2475 fp = HI2UF(hi);
2476 if ((fp->uf_flags & FC_DEAD) == 0
2477 && !isdigit(*fp->uf_name)
2478 && vim_regexec(&regmatch, fp->uf_name, 0))
2479 list_func_head(fp, FALSE);
2480 }
2481 }
2482 vim_regfree(regmatch.regprog); 2491 vim_regfree(regmatch.regprog);
2483 } 2492 }
2484 } 2493 }
2485 if (*p == '/') 2494 if (*p == '/')
2486 ++p; 2495 ++p;