patch 8.1.1964: crash when using nested map() and filter()
Problem: Crash when using nested map() and filter(). Solution: Do not set the v:key type to string without clearing the pointer.
This commit is contained in:
		
							
								
								
									
										23
									
								
								src/eval.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								src/eval.c
									
									
									
									
									
								
							| @ -7185,8 +7185,6 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | |||||||
|     hashtab_T	*ht; |     hashtab_T	*ht; | ||||||
|     hashitem_T	*hi; |     hashitem_T	*hi; | ||||||
|     dict_T	*d = NULL; |     dict_T	*d = NULL; | ||||||
|     typval_T	save_val; |  | ||||||
|     typval_T	save_key; |  | ||||||
|     blob_T	*b = NULL; |     blob_T	*b = NULL; | ||||||
|     int		rem; |     int		rem; | ||||||
|     int		todo; |     int		todo; | ||||||
| @ -7225,18 +7223,19 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | |||||||
|      * was not passed as argument. */ |      * was not passed as argument. */ | ||||||
|     if (expr->v_type != VAR_UNKNOWN) |     if (expr->v_type != VAR_UNKNOWN) | ||||||
|     { |     { | ||||||
| 	prepare_vimvar(VV_VAL, &save_val); | 	typval_T	save_val; | ||||||
|  | 	typval_T	save_key; | ||||||
|  |  | ||||||
| 	/* We reset "did_emsg" to be able to detect whether an error | 	prepare_vimvar(VV_VAL, &save_val); | ||||||
| 	 * occurred during evaluation of the expression. */ | 	prepare_vimvar(VV_KEY, &save_key); | ||||||
|  |  | ||||||
|  | 	// We reset "did_emsg" to be able to detect whether an error | ||||||
|  | 	// occurred during evaluation of the expression. | ||||||
| 	save_did_emsg = did_emsg; | 	save_did_emsg = did_emsg; | ||||||
| 	did_emsg = FALSE; | 	did_emsg = FALSE; | ||||||
|  |  | ||||||
| 	prepare_vimvar(VV_KEY, &save_key); |  | ||||||
| 	if (argvars[0].v_type == VAR_DICT) | 	if (argvars[0].v_type == VAR_DICT) | ||||||
| 	{ | 	{ | ||||||
| 	    set_vim_var_type(VV_KEY, VAR_STRING); |  | ||||||
|  |  | ||||||
| 	    ht = &d->dv_hashtab; | 	    ht = &d->dv_hashtab; | ||||||
| 	    hash_lock(ht); | 	    hash_lock(ht); | ||||||
| 	    todo = (int)ht->ht_used; | 	    todo = (int)ht->ht_used; | ||||||
| @ -7274,7 +7273,9 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | |||||||
| 	    int		i; | 	    int		i; | ||||||
| 	    typval_T	tv; | 	    typval_T	tv; | ||||||
|  |  | ||||||
|  | 	    // set_vim_var_nr() doesn't set the type | ||||||
| 	    set_vim_var_type(VV_KEY, VAR_NUMBER); | 	    set_vim_var_type(VV_KEY, VAR_NUMBER); | ||||||
|  |  | ||||||
| 	    for (i = 0; i < b->bv_ga.ga_len; i++) | 	    for (i = 0; i < b->bv_ga.ga_len; i++) | ||||||
| 	    { | 	    { | ||||||
| 		tv.v_type = VAR_NUMBER; | 		tv.v_type = VAR_NUMBER; | ||||||
| @ -7285,7 +7286,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | |||||||
| 		if (tv.v_type != VAR_NUMBER) | 		if (tv.v_type != VAR_NUMBER) | ||||||
| 		{ | 		{ | ||||||
| 		    emsg(_(e_invalblob)); | 		    emsg(_(e_invalblob)); | ||||||
| 		    return; | 		    break; | ||||||
| 		} | 		} | ||||||
| 		tv.v_type = VAR_NUMBER; | 		tv.v_type = VAR_NUMBER; | ||||||
| 		blob_set(b, i, tv.vval.v_number); | 		blob_set(b, i, tv.vval.v_number); | ||||||
| @ -7300,9 +7301,9 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | |||||||
| 		} | 		} | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
| 	else | 	else // argvars[0].v_type == VAR_LIST | ||||||
| 	{ | 	{ | ||||||
| 	    // argvars[0].v_type == VAR_LIST | 	    // set_vim_var_nr() doesn't set the type | ||||||
| 	    set_vim_var_type(VV_KEY, VAR_NUMBER); | 	    set_vim_var_type(VV_KEY, VAR_NUMBER); | ||||||
|  |  | ||||||
| 	    for (li = l->lv_first; li != NULL; li = nli) | 	    for (li = l->lv_first; li != NULL; li = nli) | ||||||
|  | |||||||
| @ -53,6 +53,12 @@ func Test_filter_map_list_expr_funcref() | |||||||
|   call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4'))) |   call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4'))) | ||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
|  | func Test_filter_map_nested() | ||||||
|  |   let x = {"x":10} | ||||||
|  |   let r = map(range(2), 'filter(copy(x), "1")') | ||||||
|  |   call assert_equal([x, x], r) | ||||||
|  | endfunc | ||||||
|  |  | ||||||
| " dict with funcref | " dict with funcref | ||||||
| func Test_filter_map_dict_expr_funcref() | func Test_filter_map_dict_expr_funcref() | ||||||
|   let dict = {"foo": 1, "bar": 2, "baz": 3} |   let dict = {"foo": 1, "bar": 2, "baz": 3} | ||||||
|  | |||||||
| @ -761,6 +761,8 @@ static char *(features[]) = | |||||||
|  |  | ||||||
| static int included_patches[] = | static int included_patches[] = | ||||||
| {   /* Add new patch number below this line */ | {   /* Add new patch number below this line */ | ||||||
|  | /**/ | ||||||
|  |     1964, | ||||||
| /**/ | /**/ | ||||||
|     1963, |     1963, | ||||||
| /**/ | /**/ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user