Mercurial > vim
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 */ |