comparison src/list.c @ 23646:5d77a7587927 v8.2.2365

patch 8.2.2365: Vim9: no check for map() changing item type at script level Commit: https://github.com/vim/vim/commit/70250fb4d2ffc2e92db224c6374db418f70691fd Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 16 19:01:53 2021 +0100 patch 8.2.2365: Vim9: no check for map() changing item type at script level Problem: Vim9: no check for map() changing item type at script level. Solution: Check the new value type.
author Bram Moolenaar <Bram@vim.org>
date Sat, 16 Jan 2021 19:15:04 +0100
parents 1816ea68c022
children 83a69ada0274
comparison
equal deleted inserted replaced
23645:541984a4d2e7 23646:5d77a7587927
1983 : filtermap == FILTERMAP_MAPNEW 1983 : filtermap == FILTERMAP_MAPNEW
1984 ? N_("mapnew() argument") 1984 ? N_("mapnew() argument")
1985 : N_("filter() argument")); 1985 : N_("filter() argument"));
1986 int save_did_emsg; 1986 int save_did_emsg;
1987 int idx = 0; 1987 int idx = 0;
1988 type_T *type = NULL;
1989 garray_T type_list;
1988 1990
1989 // map() and filter() return the first argument, also on failure. 1991 // map() and filter() return the first argument, also on failure.
1990 if (filtermap != FILTERMAP_MAPNEW) 1992 if (filtermap != FILTERMAP_MAPNEW)
1991 copy_tv(&argvars[0], rettv); 1993 copy_tv(&argvars[0], rettv);
1994 if (filtermap == FILTERMAP_MAP && in_vim9script())
1995 {
1996 // Check that map() does not change the type of the dict.
1997 ga_init2(&type_list, sizeof(type_T *), 10);
1998 type = typval2type(argvars, &type_list);
1999 }
1992 2000
1993 if (argvars[0].v_type == VAR_BLOB) 2001 if (argvars[0].v_type == VAR_BLOB)
1994 { 2002 {
1995 if (filtermap == FILTERMAP_MAPNEW) 2003 if (filtermap == FILTERMAP_MAPNEW)
1996 { 2004 {
1997 rettv->v_type = VAR_BLOB; 2005 rettv->v_type = VAR_BLOB;
1998 rettv->vval.v_blob = NULL; 2006 rettv->vval.v_blob = NULL;
1999 } 2007 }
2000 if ((b = argvars[0].vval.v_blob) == NULL) 2008 if ((b = argvars[0].vval.v_blob) == NULL)
2001 return; 2009 goto theend;
2002 } 2010 }
2003 else if (argvars[0].v_type == VAR_LIST) 2011 else if (argvars[0].v_type == VAR_LIST)
2004 { 2012 {
2005 if (filtermap == FILTERMAP_MAPNEW) 2013 if (filtermap == FILTERMAP_MAPNEW)
2006 { 2014 {
2008 rettv->vval.v_list = NULL; 2016 rettv->vval.v_list = NULL;
2009 } 2017 }
2010 if ((l = argvars[0].vval.v_list) == NULL 2018 if ((l = argvars[0].vval.v_list) == NULL
2011 || (filtermap == FILTERMAP_FILTER 2019 || (filtermap == FILTERMAP_FILTER
2012 && value_check_lock(l->lv_lock, arg_errmsg, TRUE))) 2020 && value_check_lock(l->lv_lock, arg_errmsg, TRUE)))
2013 return; 2021 goto theend;
2014 } 2022 }
2015 else if (argvars[0].v_type == VAR_DICT) 2023 else if (argvars[0].v_type == VAR_DICT)
2016 { 2024 {
2017 if (filtermap == FILTERMAP_MAPNEW) 2025 if (filtermap == FILTERMAP_MAPNEW)
2018 { 2026 {
2020 rettv->vval.v_dict = NULL; 2028 rettv->vval.v_dict = NULL;
2021 } 2029 }
2022 if ((d = argvars[0].vval.v_dict) == NULL 2030 if ((d = argvars[0].vval.v_dict) == NULL
2023 || (filtermap == FILTERMAP_FILTER 2031 || (filtermap == FILTERMAP_FILTER
2024 && value_check_lock(d->dv_lock, arg_errmsg, TRUE))) 2032 && value_check_lock(d->dv_lock, arg_errmsg, TRUE)))
2025 return; 2033 goto theend;
2026 } 2034 }
2027 else 2035 else
2028 { 2036 {
2029 semsg(_(e_listdictblobarg), ermsg); 2037 semsg(_(e_listdictblobarg), ermsg);
2030 return; 2038 goto theend;
2031 } 2039 }
2032 2040
2033 expr = &argvars[1]; 2041 expr = &argvars[1];
2034 // On type errors, the preceding call has already displayed an error 2042 // On type errors, the preceding call has already displayed an error
2035 // message. Avoid a misleading error message for an empty string that 2043 // message. Avoid a misleading error message for an empty string that
2053 dict_T *d_ret = NULL; 2061 dict_T *d_ret = NULL;
2054 2062
2055 if (filtermap == FILTERMAP_MAPNEW) 2063 if (filtermap == FILTERMAP_MAPNEW)
2056 { 2064 {
2057 if (rettv_dict_alloc(rettv) == FAIL) 2065 if (rettv_dict_alloc(rettv) == FAIL)
2058 return; 2066 goto theend;
2059 d_ret = rettv->vval.v_dict; 2067 d_ret = rettv->vval.v_dict;
2060 } 2068 }
2061 2069
2062 if (filtermap != FILTERMAP_FILTER && d->dv_lock == 0) 2070 if (filtermap != FILTERMAP_FILTER && d->dv_lock == 0)
2063 d->dv_lock = VAR_LOCKED; 2071 d->dv_lock = VAR_LOCKED;
2088 clear_tv(&newtv); 2096 clear_tv(&newtv);
2089 break; 2097 break;
2090 } 2098 }
2091 if (filtermap == FILTERMAP_MAP) 2099 if (filtermap == FILTERMAP_MAP)
2092 { 2100 {
2101 if (type != NULL && check_typval_type(type->tt_member,
2102 &newtv, 0) == FAIL)
2103 {
2104 clear_tv(&newtv);
2105 break;
2106 }
2093 // map(): replace the dict item value 2107 // map(): replace the dict item value
2094 clear_tv(&di->di_tv); 2108 clear_tv(&di->di_tv);
2095 newtv.v_lock = 0; 2109 newtv.v_lock = 0;
2096 di->di_tv = newtv; 2110 di->di_tv = newtv;
2097 } 2111 }
2124 blob_T *b_ret = b; 2138 blob_T *b_ret = b;
2125 2139
2126 if (filtermap == FILTERMAP_MAPNEW) 2140 if (filtermap == FILTERMAP_MAPNEW)
2127 { 2141 {
2128 if (blob_copy(b, rettv) == FAIL) 2142 if (blob_copy(b, rettv) == FAIL)
2129 return; 2143 goto theend;
2130 b_ret = rettv->vval.v_blob; 2144 b_ret = rettv->vval.v_blob;
2131 } 2145 }
2132 2146
2133 // set_vim_var_nr() doesn't set the type 2147 // set_vim_var_nr() doesn't set the type
2134 set_vim_var_type(VV_KEY, VAR_NUMBER); 2148 set_vim_var_type(VV_KEY, VAR_NUMBER);
2173 list_T *l_ret = NULL; 2187 list_T *l_ret = NULL;
2174 2188
2175 if (filtermap == FILTERMAP_MAPNEW) 2189 if (filtermap == FILTERMAP_MAPNEW)
2176 { 2190 {
2177 if (rettv_list_alloc(rettv) == FAIL) 2191 if (rettv_list_alloc(rettv) == FAIL)
2178 return; 2192 goto theend;
2179 l_ret = rettv->vval.v_list; 2193 l_ret = rettv->vval.v_list;
2180 } 2194 }
2181 // set_vim_var_nr() doesn't set the type 2195 // set_vim_var_nr() doesn't set the type
2182 set_vim_var_type(VV_KEY, VAR_NUMBER); 2196 set_vim_var_type(VV_KEY, VAR_NUMBER);
2183 2197
2216 clear_tv(&newtv); 2230 clear_tv(&newtv);
2217 break; 2231 break;
2218 } 2232 }
2219 if (filtermap != FILTERMAP_FILTER) 2233 if (filtermap != FILTERMAP_FILTER)
2220 { 2234 {
2235 if (filtermap == FILTERMAP_MAP && type != NULL
2236 && check_typval_type(type->tt_member,
2237 &newtv, 0) == FAIL)
2238 {
2239 clear_tv(&newtv);
2240 break;
2241 }
2221 // map(), mapnew(): always append the new value to the 2242 // map(), mapnew(): always append the new value to the
2222 // list 2243 // list
2223 if (list_append_tv_move(filtermap == FILTERMAP_MAP 2244 if (list_append_tv_move(filtermap == FILTERMAP_MAP
2224 ? l : l_ret, &newtv) == FAIL) 2245 ? l : l_ret, &newtv) == FAIL)
2225 break; 2246 break;
2254 clear_tv(&newtv); 2275 clear_tv(&newtv);
2255 break; 2276 break;
2256 } 2277 }
2257 if (filtermap == FILTERMAP_MAP) 2278 if (filtermap == FILTERMAP_MAP)
2258 { 2279 {
2280 if (type != NULL && check_typval_type(type->tt_member,
2281 &newtv, 0) == FAIL)
2282 {
2283 clear_tv(&newtv);
2284 break;
2285 }
2259 // map(): replace the list item value 2286 // map(): replace the list item value
2260 clear_tv(&li->li_tv); 2287 clear_tv(&li->li_tv);
2261 newtv.v_lock = 0; 2288 newtv.v_lock = 0;
2262 li->li_tv = newtv; 2289 li->li_tv = newtv;
2263 } 2290 }
2279 restore_vimvar(VV_KEY, &save_key); 2306 restore_vimvar(VV_KEY, &save_key);
2280 restore_vimvar(VV_VAL, &save_val); 2307 restore_vimvar(VV_VAL, &save_val);
2281 2308
2282 did_emsg |= save_did_emsg; 2309 did_emsg |= save_did_emsg;
2283 } 2310 }
2311
2312 theend:
2313 if (type != NULL)
2314 clear_type_list(&type_list);
2284 } 2315 }
2285 2316
2286 /* 2317 /*
2287 * "filter()" function 2318 * "filter()" function
2288 */ 2319 */