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; | ||||
|     hashitem_T	*hi; | ||||
|     dict_T	*d = NULL; | ||||
|     typval_T	save_val; | ||||
|     typval_T	save_key; | ||||
|     blob_T	*b = NULL; | ||||
|     int		rem; | ||||
|     int		todo; | ||||
| @ -7225,18 +7223,19 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | ||||
|      * was not passed as argument. */ | ||||
|     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 | ||||
| 	 * occurred during evaluation of the expression. */ | ||||
| 	prepare_vimvar(VV_VAL, &save_val); | ||||
| 	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; | ||||
| 	did_emsg = FALSE; | ||||
|  | ||||
| 	prepare_vimvar(VV_KEY, &save_key); | ||||
| 	if (argvars[0].v_type == VAR_DICT) | ||||
| 	{ | ||||
| 	    set_vim_var_type(VV_KEY, VAR_STRING); | ||||
|  | ||||
| 	    ht = &d->dv_hashtab; | ||||
| 	    hash_lock(ht); | ||||
| 	    todo = (int)ht->ht_used; | ||||
| @ -7274,7 +7273,9 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) | ||||
| 	    int		i; | ||||
| 	    typval_T	tv; | ||||
|  | ||||
| 	    // set_vim_var_nr() doesn't set the type | ||||
| 	    set_vim_var_type(VV_KEY, VAR_NUMBER); | ||||
|  | ||||
| 	    for (i = 0; i < b->bv_ga.ga_len; i++) | ||||
| 	    { | ||||
| 		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) | ||||
| 		{ | ||||
| 		    emsg(_(e_invalblob)); | ||||
| 		    return; | ||||
| 		    break; | ||||
| 		} | ||||
| 		tv.v_type = VAR_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); | ||||
|  | ||||
| 	    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'))) | ||||
| 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 | ||||
| func Test_filter_map_dict_expr_funcref() | ||||
|   let dict = {"foo": 1, "bar": 2, "baz": 3} | ||||
|  | ||||
| @ -761,6 +761,8 @@ static char *(features[]) = | ||||
|  | ||||
| static int included_patches[] = | ||||
| {   /* Add new patch number below this line */ | ||||
| /**/ | ||||
|     1964, | ||||
| /**/ | ||||
|     1963, | ||||
| /**/ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user