To: vim_dev@googlegroups.com Subject: Patch 8.2.2117 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2117 Problem: Some functions use any value as a string. Solution: Check that the value is a non-empty string. Files: src/typval.c, src/proto/typval.pro, src/mbyte.c, src/filepath.c, src/testdir/test_vim9_builtin.vim, src/testdir/test_vim9_expr.vim *** ../vim-8.2.2116/src/typval.c 2020-11-18 17:17:11.961928659 +0100 --- src/typval.c 2020-12-09 12:20:22.162620618 +0100 *************** *** 341,346 **** --- 341,362 ---- #endif /* + * Give an error and return FAIL unless "tv" is a non-empty string. + */ + int + check_for_string(typval_T *tv) + { + if (tv->v_type != VAR_STRING + || tv->vval.v_string == NULL + || *tv->vval.v_string == NUL) + { + emsg(_(e_stringreq)); + return FAIL; + } + return OK; + } + + /* * Get the string value of a variable. * If it is a Number variable, the number is converted into a string. * tv_get_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE! *** ../vim-8.2.2116/src/proto/typval.pro 2020-09-01 23:05:57.812835372 +0200 --- src/proto/typval.pro 2020-12-09 12:21:21.498434049 +0100 *************** *** 9,14 **** --- 9,15 ---- varnumber_T tv_get_bool(typval_T *varp); varnumber_T tv_get_bool_chk(typval_T *varp, int *denote); float_T tv_get_float(typval_T *varp); + int check_for_string(typval_T *tv); char_u *tv_get_string(typval_T *varp); char_u *tv_get_string_buf(typval_T *varp, char_u *buf); char_u *tv_get_string_chk(typval_T *varp); *** ../vim-8.2.2116/src/mbyte.c 2020-08-30 19:26:40.736556825 +0200 --- src/mbyte.c 2020-12-09 12:25:43.889584858 +0100 *************** *** 5551,5563 **** void f_charclass(typval_T *argvars, typval_T *rettv UNUSED) { ! if (argvars[0].v_type != VAR_STRING ! || argvars[0].vval.v_string == NULL ! || *argvars[0].vval.v_string == NUL) ! { ! emsg(_(e_stringreq)); return; - } rettv->vval.v_number = mb_get_class(argvars[0].vval.v_string); } #endif --- 5551,5558 ---- void f_charclass(typval_T *argvars, typval_T *rettv UNUSED) { ! if (check_for_string(&argvars[0]) == FAIL) return; rettv->vval.v_number = mb_get_class(argvars[0].vval.v_string); } #endif *** ../vim-8.2.2116/src/filepath.c 2020-10-24 20:49:37.494683051 +0200 --- src/filepath.c 2020-12-09 12:35:25.495620783 +0100 *************** *** 861,870 **** void f_executable(typval_T *argvars, typval_T *rettv) { ! char_u *name = tv_get_string(&argvars[0]); // Check in $PATH and also check directly if there is a directory name. ! rettv->vval.v_number = mch_can_exe(name, NULL, TRUE); } /* --- 861,871 ---- void f_executable(typval_T *argvars, typval_T *rettv) { ! if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) ! return; // Check in $PATH and also check directly if there is a directory name. ! rettv->vval.v_number = mch_can_exe(tv_get_string(&argvars[0]), NULL, TRUE); } /* *************** *** 875,880 **** --- 876,883 ---- { char_u *p = NULL; + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; (void)mch_can_exe(tv_get_string(&argvars[0]), &p, TRUE); rettv->v_type = VAR_STRING; rettv->vval.v_string = p; *************** *** 890,895 **** --- 893,900 ---- char_u *p; int n; + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; #ifndef O_NONBLOCK # define O_NONBLOCK 0 #endif *************** *** 913,918 **** --- 918,925 ---- void f_filewritable(typval_T *argvars, typval_T *rettv) { + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; rettv->vval.v_number = filewritable(tv_get_string(&argvars[0])); } *************** *** 935,940 **** --- 942,949 ---- rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; #ifdef FEAT_SEARCHPATH fname = tv_get_string(&argvars[0]); *************** *** 1014,1019 **** --- 1023,1031 ---- char_u *fbuf = NULL; char_u buf[NUMBUFLEN]; + if (in_vim9script() && (check_for_string(&argvars[0]) == FAIL + || check_for_string(&argvars[1]) == FAIL)) + return; fname = tv_get_string_chk(&argvars[0]); mods = tv_get_string_buf_chk(&argvars[1], buf); if (fname == NULL || mods == NULL) *************** *** 1122,1127 **** --- 1134,1141 ---- char_u *perm = NULL; char_u permbuf[] = "---------"; + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; fname = tv_get_string(&argvars[0]); rettv->v_type = VAR_STRING; *************** *** 1139,1148 **** char_u *fname; stat_T st; ! fname = tv_get_string(&argvars[0]); ! ! rettv->v_type = VAR_NUMBER; if (mch_stat((char *)fname, &st) >= 0) { if (mch_isdir(fname)) --- 1153,1162 ---- char_u *fname; stat_T st; ! if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) ! return; + fname = tv_get_string(&argvars[0]); if (mch_stat((char *)fname, &st) >= 0) { if (mch_isdir(fname)) *************** *** 1169,1176 **** char_u *fname; stat_T st; fname = tv_get_string(&argvars[0]); - if (mch_stat((char *)fname, &st) >= 0) rettv->vval.v_number = (varnumber_T)st.st_mtime; else --- 1183,1191 ---- char_u *fname; stat_T st; + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; fname = tv_get_string(&argvars[0]); if (mch_stat((char *)fname, &st) >= 0) rettv->vval.v_number = (varnumber_T)st.st_mtime; else *************** *** 1214,1219 **** --- 1229,1236 ---- stat_T st; char_u *type = NULL; + if (in_vim9script() && check_for_string(&argvars[0]) == FAIL) + return; fname = tv_get_string(&argvars[0]); rettv->v_type = VAR_STRING; *** ../vim-8.2.2116/src/testdir/test_vim9_builtin.vim 2020-12-05 21:46:50.154387600 +0100 --- src/testdir/test_vim9_builtin.vim 2020-12-09 12:35:57.555500410 +0100 *************** *** 185,190 **** --- 185,202 ---- count('ABC ABC ABC', 'b', false)->assert_equal(0) enddef + def Test_executable() + CheckDefExecFailure(['echo executable(true)'], 'E928:') + CheckDefExecFailure(['echo executable(v:null)'], 'E928:') + CheckDefExecFailure(['echo executable("")'], 'E928:') + enddef + + def Test_exepath() + CheckDefExecFailure(['echo exepath(true)'], 'E928:') + CheckDefExecFailure(['echo exepath(v:null)'], 'E928:') + CheckDefExecFailure(['echo exepath("")'], 'E928:') + enddef + def Test_expand() split SomeFile expand('%', true, true)->assert_equal(['SomeFile']) *************** *** 241,246 **** --- 253,291 ---- CheckDefAndScriptSuccess(lines) enddef + def Test_filereadable() + CheckDefExecFailure(['echo filereadable(true)'], 'E928:') + CheckDefExecFailure(['echo filereadable(v:null)'], 'E928:') + CheckDefExecFailure(['echo filereadable("")'], 'E928:') + enddef + + def Test_filewritable() + CheckDefExecFailure(['echo filewritable(true)'], 'E928:') + CheckDefExecFailure(['echo filewritable(v:null)'], 'E928:') + CheckDefExecFailure(['echo filewritable("")'], 'E928:') + enddef + + def Test_finddir() + CheckDefExecFailure(['echo finddir(true)'], 'E928:') + CheckDefExecFailure(['echo finddir(v:null)'], 'E928:') + CheckDefExecFailure(['echo finddir("")'], 'E928:') + enddef + + def Test_findfile() + CheckDefExecFailure(['echo findfile(true)'], 'E928:') + CheckDefExecFailure(['echo findfile(v:null)'], 'E928:') + CheckDefExecFailure(['echo findfile("")'], 'E928:') + enddef + + def Test_fnamemodify() + CheckDefExecFailure(['echo fnamemodify(true, ":p")'], 'E928:') + CheckDefExecFailure(['echo fnamemodify(v:null, ":p")'], 'E928:') + CheckDefExecFailure(['echo fnamemodify("", ":p")'], 'E928:') + CheckDefExecFailure(['echo fnamemodify("file", true)'], 'E928:') + CheckDefExecFailure(['echo fnamemodify("file", v:null)'], 'E928:') + CheckDefExecFailure(['echo fnamemodify("file", "")'], 'E928:') + enddef + def Test_filter_wrong_dict_key_type() assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1012:') enddef *************** *** 313,318 **** --- 358,387 ---- d->assert_equal({items: []}) enddef + def Test_getfperm() + CheckDefExecFailure(['echo getfperm(true)'], 'E928:') + CheckDefExecFailure(['echo getfperm(v:null)'], 'E928:') + CheckDefExecFailure(['echo getfperm("")'], 'E928:') + enddef + + def Test_getfsize() + CheckDefExecFailure(['echo getfsize(true)'], 'E928:') + CheckDefExecFailure(['echo getfsize(v:null)'], 'E928:') + CheckDefExecFailure(['echo getfsize("")'], 'E928:') + enddef + + def Test_getftime() + CheckDefExecFailure(['echo getftime(true)'], 'E928:') + CheckDefExecFailure(['echo getftime(v:null)'], 'E928:') + CheckDefExecFailure(['echo getftime("")'], 'E928:') + enddef + + def Test_getftype() + CheckDefExecFailure(['echo getftype(true)'], 'E928:') + CheckDefExecFailure(['echo getftype(v:null)'], 'E928:') + CheckDefExecFailure(['echo getftype("")'], 'E928:') + enddef + def Test_getqflist_return_type() var l = getqflist() l->assert_equal([]) *** ../vim-8.2.2116/src/testdir/test_vim9_expr.vim 2020-12-07 21:49:48.416837683 +0100 --- src/testdir/test_vim9_expr.vim 2020-12-09 12:39:02.918812498 +0100 *************** *** 1971,1977 **** CheckDefExecFailure(['var x: dict = {a: "x", b: 134}'], 'E1012:', 1) CheckDefFailure(['var x = ({'], 'E723:', 2) ! CheckDefExecFailure(['{}[getftype("")]'], 'E716: Key not present in Dictionary: ""', 1) enddef def Test_expr7_dict_vim9script() --- 1971,1977 ---- CheckDefExecFailure(['var x: dict = {a: "x", b: 134}'], 'E1012:', 1) CheckDefFailure(['var x = ({'], 'E723:', 2) ! CheckDefExecFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1) enddef def Test_expr7_dict_vim9script() *** ../vim-8.2.2116/src/version.c 2020-12-09 12:01:00.173093519 +0100 --- src/version.c 2020-12-09 12:39:39.670677447 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2117, /**/ -- Close your shells, or I'll kill -9 you Tomorrow I'll quota you Remember the disks'll always be full And then while I'm away I'll write ~ everyday And I'll send-pr all my buggings to you. [ CVS log "Beatles style" for FreeBSD ports/INDEX, Satoshi Asami ] /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///