Mercurial > vim
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(®match); |
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(®match, 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; |