diff --git a/runtime/autoload/dist/vim9.vim b/runtime/autoload/dist/vim9.vim index 87b3dbb872..d824673912 100644 --- a/runtime/autoload/dist/vim9.vim +++ b/runtime/autoload/dist/vim9.vim @@ -3,7 +3,7 @@ vim9script # Vim runtime support library # # Maintainer: The Vim Project -# Last Change: 2026 Mar 10 +# Last Change: 2026 Apr 06 export def IsSafeExecutable(filetype: string, executable: string): bool if empty(exepath(executable)) @@ -62,7 +62,7 @@ if has('unix') export def Launch(args: string) # Use job_start, because using !xdg-open is known not to work with zsh # ignore signals on exit - job_start(split(args), {'stoponexit': ''}) + job_start(['sh', '-c', args], {'stoponexit': '', 'in_io': 'null', 'out_io': 'null', 'err_io': 'null'}) enddef endif elseif has('win32') @@ -139,13 +139,7 @@ export def Open(file: string) setlocal shell& defer setbufvar('%', '&shell', shell) endif - if has('unix') && !has('win32unix') && !exists('$WSL_DISTRO_NAME') - # Linux: using job_start, so do not use shellescape. - Launch($"{Viewer()} {file}") - else - # Windows/WSL/Cygwin: NEEDS shellescape because Launch uses '!' - Launch($"{Viewer()} {shellescape(file, 1)}") - endif + Launch($"{Viewer()} {shellescape(file, 1)}") enddef # Uncomment this line to check for compilation errors early diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index 73829a2d5c..110327e95b 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -20,6 +20,7 @@ " 2025 Jul 16 by Vim Project: update minimum vim version " 2026 Feb 06 by Vim Project: consider 'nowrapscan' (#19333) " 2026 Feb 07 by Vim Project: make the path traversal detection more robust (#19341) +" 2026 Apr 06 by Vim Project: fix bugs with lz4 support (#19925) " " Contains many ideas from Michael Toren's " @@ -704,7 +705,9 @@ fun! tar#Extract() endif elseif filereadable(tarbase.".tlz4") - let extractcmd= substitute(extractcmd,"-","-I lz4","") + if has("linux") + let extractcmd= substitute(extractcmd,"-","-I lz4 -","") + endif call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname)) if v:shell_error != 0 call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tlz4 {fname}: failed!") @@ -713,8 +716,10 @@ fun! tar#Extract() endif elseif filereadable(tarbase.".tar.lz4") - let extractcmd= substitute(extractcmd,"-","-I lz4","") - call system(extractcmd." ".shellescape(tarbase).".tar.lz4".shellescape(fname)) + if has("linux") + let extractcmd= substitute(extractcmd,"-","-I lz4 -","") + endif + call system(extractcmd." ".shellescape(tarbase).".tar.lz4 ".shellescape(fname)) if v:shell_error != 0 call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.lz4 {fname}: failed!") else diff --git a/runtime/autoload/vimball.vim b/runtime/autoload/vimball.vim index 6456984411..fb4df5eb66 100644 --- a/runtime/autoload/vimball.vim +++ b/runtime/autoload/vimball.vim @@ -6,6 +6,7 @@ " GetLatestVimScripts: 1502 1 :AutoInstall: vimball.vim " Last Change: " 2025 Feb 28 by Vim Project: add support for bzip3 (#16755) +" 2026 Apr 05 by Vim Project: Detect Path Traversal Attacks " Copyright: (c) 2004-2011 by Charles E. Campbell " The VIM LICENSE applies to Vimball.vim, and Vimball.txt " (see |copyright|) except use "Vimball" instead of "Vim". @@ -18,15 +19,14 @@ if &cp || exists("g:loaded_vimball") finish endif let g:loaded_vimball = "v37" -if v:version < 702 +if v:version < 704 echohl WarningMsg - echo "***warning*** this version of vimball needs vim 7.2" + echo "***warning*** this version of vimball needs vim 7.4" echohl Normal finish endif let s:keepcpo= &cpo set cpo&vim -"DechoTabOn " ===================================================================== " Constants: {{{1 @@ -47,20 +47,6 @@ if !exists("s:USAGE") let g:netrw_cygwin= 0 endif endif - - " set up g:vimball_mkdir if the mkdir() call isn't defined - if !exists("*mkdir") - if exists("g:netrw_local_mkdir") - let g:vimball_mkdir= g:netrw_local_mkdir - elseif executable("mkdir") - let g:vimball_mkdir= "mkdir" - elseif executable("makedir") - let g:vimball_mkdir= "makedir" - endif - if !exists(g:vimball_mkdir) - call vimball#ShowMesg(s:WARNING,"(vimball) g:vimball_mkdir undefined") - endif - endif endif " ===================================================================== @@ -81,7 +67,6 @@ endif " filesize " [file] fun! vimball#MkVimball(line1,line2,writelevel,...) range -" call Dfunc("MkVimball(line1=".a:line1." line2=".a:line2." writelevel=".a:writelevel." vimballname<".a:1.">) a:0=".a:0) if a:1 =~ '\.vim$' || a:1 =~ '\.txt$' let vbname= substitute(a:1,'\.\a\{3}$','.vmb','') else @@ -90,15 +75,12 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range if vbname !~ '\.vmb$' let vbname= vbname.'.vmb' endif -" call Decho("vbname<".vbname.">") if !a:writelevel && a:1 =~ '[\/]' call vimball#ShowMesg(s:ERROR,"(MkVimball) vimball name<".a:1."> should not include slashes; use ! to insist") -" call Dret("MkVimball : vimball name<".a:1."> should not include slashes") return endif if !a:writelevel && filereadable(vbname) call vimball#ShowMesg(s:ERROR,"(MkVimball) file<".vbname."> exists; use ! to insist") -" call Dret("MkVimball : file<".vbname."> already exists; use ! to insist") return endif @@ -120,17 +102,14 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range " record current tab, initialize while loop index let curtabnr = tabpagenr() let linenr = a:line1 -" call Decho("curtabnr=".curtabnr) while linenr <= a:line2 let svfile = getline(linenr) -" call Decho("svfile<".svfile.">") if !filereadable(svfile) call vimball#ShowMesg(s:ERROR,"unable to read file<".svfile.">") - call s:ChgDir(curdir) - call vimball#RestoreSettings() -" call Dret("MkVimball") + call s:ChgDir(curdir) + call vimball#RestoreSettings() return endif @@ -145,20 +124,18 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range let lastline= line("$") + 1 if lastline == 2 && getline("$") == "" - call setline(1,'" Vimball Archiver by Charles E. Campbell') - call setline(2,'UseVimball') - call setline(3,'finish') - let lastline= line("$") + 1 + call setline(1,'" Vimball Archiver by Charles E. Campbell') + call setline(2,'UseVimball') + call setline(3,'finish') + let lastline= line("$") + 1 endif call setline(lastline ,substitute(svfile,'$',' [[[1','')) call setline(lastline+1,0) " write the file from the tab -" call Decho("exe $r ".fnameescape(svfile)) exe "$r ".fnameescape(svfile) call setline(lastline+1,line("$") - lastline - 1) -" call Decho("lastline=".lastline." line$=".line("$")) " restore to normal tab exe "tabn ".curtabnr @@ -170,13 +147,10 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range call s:ChgDir(curdir) setlocal ff=unix if a:writelevel -" call Decho("exe w! ".fnameescape(vbname)) exe "w! ".fnameescape(vbname) else -" call Decho("exe w ".fnameescape(vbname)) exe "w ".fnameescape(vbname) endif -" call Decho("Vimball<".vbname."> created") echo "Vimball<".vbname."> created" " remove the evidence @@ -187,7 +161,6 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range " restore options call vimball#RestoreSettings() -" call Dret("MkVimball") endfun " --------------------------------------------------------------------- @@ -195,17 +168,9 @@ endfun " (invoked the the UseVimball command embedded in " vimballs' prologue) fun! vimball#Vimball(really,...) -" call Dfunc("vimball#Vimball(really=".a:really.") a:0=".a:0) - - if v:version < 701 || (v:version == 701 && !exists('*fnameescape')) - echoerr "your vim is missing the fnameescape() function (pls upgrade to vim 7.2 or later)" -" call Dret("vimball#Vimball : needs 7.1 with patch 299 or later") - return - endif if getline(1) !~ '^" Vimball Archiver' echoerr "(Vimball) The current file does not appear to be a Vimball!" -" call Dret("vimball#Vimball") return endif @@ -215,7 +180,6 @@ fun! vimball#Vimball(really,...) let vimballfile = expand("%:tr") " set up vimball tab -" call Decho("setting up vimball tab") tabnew sil! file Vimball let vbtabnr= tabpagenr() @@ -227,21 +191,18 @@ fun! vimball#Vimball(really,...) " If, however, the user did not specify a full path, set the home to be below the current directory let home= expand(a:1) if has("win32") || has("win95") || has("win64") || has("win16") - if home !~ '^\a:[/\\]' - let home= getcwd().'/'.a:1 - endif + if home !~ '^\a:[/\\]' + let home= getcwd().'/'.a:1 + endif elseif home !~ '^/' - let home= getcwd().'/'.a:1 + let home= getcwd().'/'.a:1 endif else let home= vimball#VimballHome() endif -" call Decho("home<".home.">") " save current directory and remove older same-named vimball, if any let curdir = getcwd() -" call Decho("home<".home.">") -" call Decho("curdir<".curdir.">") call s:ChgDir(home) let s:ok_unablefind= 1 @@ -260,56 +221,48 @@ fun! vimball#Vimball(really,...) endif " apportion vimball contents to various files -" call Decho("exe tabn ".curtabnr) exe "tabn ".curtabnr -" call Decho("linenr=".linenr." line$=".line("$")) while 1 < linenr && linenr < line("$") let fname = substitute(getline(linenr),'\t\[\[\[1$','','') let fname = substitute(fname,'\\','/','g') + let fname = resolve(simplify(fname)) let fsize = substitute(getline(linenr+1),'^\(\d\+\).\{-}$','\1','')+0 let fenc = substitute(getline(linenr+1),'^\d\+\s*\(\S\{-}\)$','\1','') let filecnt = filecnt + 1 -" call Decho("fname<".fname."> fsize=".fsize." filecnt=".filecnt. " fenc=".fenc) + if fname =~ '\.\.' + echomsg "(Vimball) Path Traversal Attack detected, aborting..." + exe "tabn ".curtabnr + bw! Vimball + call s:ChgDir(curdir) + return + endif if a:really echomsg "extracted <".fname.">: ".fsize." lines" else echomsg "would extract <".fname.">: ".fsize." lines" endif -" call Decho("using L#".linenr.": will extract file<".fname.">") -" call Decho("using L#".(linenr+1).": fsize=".fsize) " Allow AsNeeded/ directory to take place of plugin/ directory " when AsNeeded/filename is filereadable or was present in VimballRecord if fname =~ '\ instead of <".fname.">") - let fname= anfname - endif + let anfname= substitute(fname,'\)") let fnamebuf= substitute(fname,'\\','/','g') - let dirpath = substitute(home,'\\','/','g') -" call Decho("init: fnamebuf<".fnamebuf.">") -" call Decho("init: dirpath <".dirpath.">") + let dirpath = substitute(home,'\\','/','g') while fnamebuf =~ '/' let dirname = dirpath."/".substitute(fnamebuf,'/.*$','','') - let dirpath = dirname + let dirpath = dirname let fnamebuf = substitute(fnamebuf,'^.\{-}/\(.*\)$','\1','') -" call Decho("dirname<".dirname.">") -" call Decho("dirpath<".dirpath.">") if !isdirectory(dirname) -" call Decho("making <".dirname.">") - if exists("g:vimball_mkdir") - call system(g:vimball_mkdir." ".shellescape(dirname)) - else - call mkdir(dirname) - endif - call s:RecordInVar(home,"rmdir('".dirname."')") + call mkdir(dirname) + call s:RecordInVar(home,"rmdir('".dirname."')") endif endwhile endif @@ -319,13 +272,11 @@ fun! vimball#Vimball(really,...) " (skip over path/filename and qty-lines) let linenr = linenr + 2 let lastline = linenr + fsize - 1 -" call Decho("exe ".linenr.",".lastline."yank a") " no point in handling a zero-length file if lastline >= linenr exe "silent ".linenr.",".lastline."yank a" " copy "a" buffer into tab -" call Decho('copy "a buffer into tab#'.vbtabnr) exe "tabn ".vbtabnr setlocal ma sil! %d @@ -336,38 +287,31 @@ fun! vimball#Vimball(really,...) " write tab to file if a:really let fnamepath= home."/".fname -" call Decho("exe w! ".fnameescape(fnamepath)) - if fenc != "" - exe "silent w! ++enc=".fnameescape(fenc)." ".fnameescape(fnamepath) - else - exe "silent w! ".fnameescape(fnamepath) - endif - echo "wrote ".fnameescape(fnamepath) - call s:RecordInVar(home,"call delete('".fnamepath."')") + if fenc != "" + exe "silent w! ++enc=".fnameescape(fenc)." ".fnameescape(fnamepath) + else + exe "silent w! ".fnameescape(fnamepath) + endif + echo "wrote ".fnameescape(fnamepath) + call s:RecordInVar(home,"call delete('".fnamepath."')") endif " return to tab with vimball -" call Decho("exe tabn ".curtabnr) exe "tabn ".curtabnr " set up help if it's a doc/*.txt file -" call Decho("didhelp<".didhelp."> fname<".fname.">") if a:really && didhelp == "" && fname =~ 'doc/[^/]\+\.\(txt\|..x\)$' - let didhelp= substitute(fname,'^\(.*\") + let didhelp= substitute(fname,'^\(.*\") if didhelp != "" let htpath= home."/".didhelp -" call Decho("exe helptags ".htpath) exe "helptags ".fnameescape(htpath) echo "did helptags" endif @@ -388,8 +332,6 @@ fun! vimball#Vimball(really,...) exe "sil! tabc! ".vbtabnr call vimball#RestoreSettings() call s:ChgDir(curdir) - -" call Dret("vimball#Vimball") endfun " --------------------------------------------------------------------- @@ -399,23 +341,18 @@ endfun " Usage: RmVimball (assume current file is a vimball; remove) " RmVimball vimballname fun! vimball#RmVimball(...) -" call Dfunc("vimball#RmVimball() a:0=".a:0) if exists("g:vimball_norecord") -" call Dret("vimball#RmVimball : (g:vimball_norecord)") return endif if a:0 == 0 let curfile= expand("%:tr") -" call Decho("case a:0=0: curfile<".curfile."> (used expand(%:tr))") else if a:1 =~ '[\/]' call vimball#ShowMesg(s:USAGE,"RmVimball vimballname [path]") -" call Dret("vimball#RmVimball : suspect a:1<".a:1.">") return endif let curfile= a:1 -" call Decho("case a:0=".a:0.": curfile<".curfile.">") endif if curfile =~ '\.vmb$' let curfile= substitute(curfile,'\.vmb','','') @@ -428,75 +365,60 @@ fun! vimball#RmVimball(...) let home= vimball#VimballHome() endif let curdir = getcwd() -" call Decho("home <".home.">") -" call Decho("curfile<".curfile.">") -" call Decho("curdir <".curdir.">") call s:ChgDir(home) if filereadable(".VimballRecord") -" call Decho(".VimballRecord is readable") -" call Decho("curfile<".curfile.">") keepalt keepjumps 1split sil! keepalt keepjumps e .VimballRecord let keepsrch= @/ -" call Decho('search for ^\M'.curfile.'.\m: ') -" call Decho('search for ^\M'.curfile.'.\m{vba|vmb}: ') -" call Decho('search for ^\M'.curfile.'\m[-0-9.]*\.{vba|vmb}: ') if search('^\M'.curfile."\m: ".'cw') - let foundit= 1 + let foundit= 1 elseif search('^\M'.curfile.".\mvmb: ",'cw') - let foundit= 2 + let foundit= 2 elseif search('^\M'.curfile.'\m[-0-9.]*\.vmb: ','cw') - let foundit= 2 + let foundit= 2 elseif search('^\M'.curfile.".\mvba: ",'cw') - let foundit= 1 + let foundit= 1 elseif search('^\M'.curfile.'\m[-0-9.]*\.vba: ','cw') - let foundit= 1 + let foundit= 1 else let foundit = 0 endif if foundit - if foundit == 1 - let exestring = substitute(getline("."),'^\M'.curfile.'\m\S\{-}\.vba: ','','') - else - let exestring = substitute(getline("."),'^\M'.curfile.'\m\S\{-}\.vmb: ','','') - endif + if foundit == 1 + let exestring = substitute(getline("."),'^\M'.curfile.'\m\S\{-}\.vba: ','','') + else + let exestring = substitute(getline("."),'^\M'.curfile.'\m\S\{-}\.vmb: ','','') + endif let s:VBRstring= substitute(exestring,'call delete(','','g') let s:VBRstring= substitute(s:VBRstring,"[')]",'','g') -" call Decho("exe ".exestring) - sil! keepalt keepjumps exe exestring - sil! keepalt keepjumps d - let exestring= strlen(substitute(exestring,'call delete(.\{-})|\=',"D","g")) -" call Decho("exestring<".exestring.">") - echomsg "removed ".exestring." files" + sil! keepalt keepjumps exe exestring + sil! keepalt keepjumps d + let exestring= strlen(substitute(exestring,'call delete(.\{-})|\=',"D","g")) + echomsg "removed ".exestring." files" else let s:VBRstring= '' - let curfile = substitute(curfile,'\.vmb','','') -" call Decho("unable to find <".curfile."> in .VimballRecord") - if !exists("s:ok_unablefind") + let curfile = substitute(curfile,'\.vmb','','') + if !exists("s:ok_unablefind") call vimball#ShowMesg(s:WARNING,"(RmVimball) unable to find <".curfile."> in .VimballRecord") - endif + endif endif sil! keepalt keepjumps g/^\s*$/d sil! keepalt keepjumps wq! let @/= keepsrch endif call s:ChgDir(curdir) - -" call Dret("vimball#RmVimball") endfun " --------------------------------------------------------------------- " vimball#Decompress: attempts to automatically decompress vimballs {{{2 fun! vimball#Decompress(fname,...) -" call Dfunc("Decompress(fname<".a:fname.">) a:0=".a:0) - " decompression: if expand("%") =~ '.*\.gz' && executable("gunzip") " handle *.gz with gunzip silent exe "!gunzip ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) gunzip may have failed with <".a:fname.">") + call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) gunzip may have failed with <".a:fname.">") endif let fname= substitute(a:fname,'\.gz$','','') exe "e ".escape(fname,' \') @@ -506,7 +428,7 @@ fun! vimball#Decompress(fname,...) " handle *.gz with gzip -d silent exe "!gzip -d ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "gzip -d" may have failed with <'.a:fname.">") + call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "gzip -d" may have failed with <'.a:fname.">") endif let fname= substitute(a:fname,'\.gz$','','') exe "e ".escape(fname,' \') @@ -516,7 +438,7 @@ fun! vimball#Decompress(fname,...) " handle *.bz2 with bunzip2 silent exe "!bunzip2 ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) bunzip2 may have failed with <".a:fname.">") + call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) bunzip2 may have failed with <".a:fname.">") endif let fname= substitute(a:fname,'\.bz2$','','') exe "e ".escape(fname,' \') @@ -526,7 +448,7 @@ fun! vimball#Decompress(fname,...) " handle *.bz2 with bzip2 -d silent exe "!bzip2 -d ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "bzip2 -d" may have failed with <'.a:fname.">") + call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "bzip2 -d" may have failed with <'.a:fname.">") endif let fname= substitute(a:fname,'\.bz2$','','') exe "e ".escape(fname,' \') @@ -536,7 +458,7 @@ fun! vimball#Decompress(fname,...) " handle *.bz3 with bunzip3 silent exe "!bunzip3 ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) bunzip3 may have failed with <".a:fname.">") + call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) bunzip3 may have failed with <".a:fname.">") endif let fname= substitute(a:fname,'\.bz3$','','') exe "e ".escape(fname,' \') @@ -546,7 +468,7 @@ fun! vimball#Decompress(fname,...) " handle *.bz3 with bzip3 -d silent exe "!bzip3 -d ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "bzip3 -d" may have failed with <'.a:fname.">") + call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "bzip3 -d" may have failed with <'.a:fname.">") endif let fname= substitute(a:fname,'\.bz3$','','') exe "e ".escape(fname,' \') @@ -556,7 +478,7 @@ fun! vimball#Decompress(fname,...) " handle *.zip with unzip silent exe "!unzip ".shellescape(a:fname) if v:shell_error != 0 - call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) unzip may have failed with <".a:fname.">") + call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) unzip may have failed with <".a:fname.">") endif let fname= substitute(a:fname,'\.zip$','','') exe "e ".escape(fname,' \') @@ -564,14 +486,11 @@ fun! vimball#Decompress(fname,...) endif if a:0 == 0| setlocal noma bt=nofile fmr=[[[,]]] fdm=marker | endif - -" call Dret("Decompress") endfun " --------------------------------------------------------------------- " vimball#ShowMesg: {{{2 fun! vimball#ShowMesg(level,msg) -" call Dfunc("vimball#ShowMesg(level=".a:level." msg<".a:msg.">)") let rulerkeep = &ruler let showcmdkeep = &showcmd @@ -596,13 +515,10 @@ fun! vimball#ShowMesg(level,msg) let &ruler = rulerkeep let &showcmd = showcmdkeep - -" call Dret("vimball#ShowMesg") endfun " ===================================================================== " s:ChgDir: change directory (in spite of Windoze) {{{2 fun! s:ChgDir(newdir) -" call Dfunc("ChgDir(newdir<".a:newdir.">)") if (has("win32") || has("win95") || has("win64") || has("win16")) try exe 'silent cd '.fnameescape(substitute(a:newdir,'/','\\','g')) @@ -618,33 +534,22 @@ fun! s:ChgDir(newdir) exe 'silent cd '.fnameescape(a:newdir) endtry endif -" call Dret("ChgDir : curdir<".getcwd().">") endfun " --------------------------------------------------------------------- " s:RecordInVar: record a un-vimball command in the .VimballRecord file {{{2 fun! s:RecordInVar(home,cmd) -" call Dfunc("RecordInVar(home<".a:home."> cmd<".a:cmd.">)") - if a:cmd =~ '^rmdir' -" if !exists("s:recorddir") -" let s:recorddir= substitute(a:cmd,'^rmdir',"call s:Rmdir",'') -" else -" let s:recorddir= s:recorddir."|".substitute(a:cmd,'^rmdir',"call s:Rmdir",'') -" endif - elseif !exists("s:recordfile") + if !exists("s:recordfile") let s:recordfile= a:cmd else let s:recordfile= s:recordfile."|".a:cmd endif -" call Dret("RecordInVar : s:recordfile<".(exists("s:recordfile")? s:recordfile : "")."> s:recorddir<".(exists("s:recorddir")? s:recorddir : "").">") endfun " --------------------------------------------------------------------- " s:RecordInFile: {{{2 fun! s:RecordInFile(home) -" call Dfunc("s:RecordInFile()") if exists("g:vimball_norecord") -" call Dret("s:RecordInFile : g:vimball_norecord") return endif @@ -654,22 +559,19 @@ fun! s:RecordInFile(home) keepalt keepjumps 1split let cmd= expand("%:tr").": " -" call Decho("cmd<".cmd.">") sil! keepalt keepjumps e .VimballRecord setlocal ma $ if exists("s:recordfile") && exists("s:recorddir") - let cmd= cmd.s:recordfile."|".s:recorddir + let cmd= cmd.s:recordfile."|".s:recorddir elseif exists("s:recorddir") - let cmd= cmd.s:recorddir + let cmd= cmd.s:recorddir elseif exists("s:recordfile") - let cmd= cmd.s:recordfile + let cmd= cmd.s:recordfile else -" call Dret("s:RecordInFile : neither recordfile nor recorddir exist") - return + return endif -" call Decho("cmd<".cmd.">") " put command into buffer, write .VimballRecord `file keepalt keepjumps put=cmd @@ -678,35 +580,28 @@ fun! s:RecordInFile(home) call s:ChgDir(curdir) if exists("s:recorddir") -" call Decho("unlet s:recorddir<".s:recorddir.">") - unlet s:recorddir + unlet s:recorddir endif if exists("s:recordfile") -" call Decho("unlet s:recordfile<".s:recordfile.">") - unlet s:recordfile + unlet s:recordfile endif - else -" call Decho("s:record[file|dir] doesn't exist") endif - -" call Dret("s:RecordInFile") endfun " --------------------------------------------------------------------- " vimball#VimballHome: determine/get home directory path (usually from rtp) {{{2 fun! vimball#VimballHome() -" call Dfunc("vimball#VimballHome()") if exists("g:vimball_home") let home= g:vimball_home else " go to vim plugin home for home in split(&rtp,',') + [''] if isdirectory(home) && filewritable(home) | break | endif - let basehome= substitute(home,'[/\\]\.vim$','','') + let basehome= substitute(home,'[/\\]\.vim$','','') if isdirectory(basehome) && filewritable(basehome) - let home= basehome."/.vim" - break - endif + let home= basehome."/.vim" + break + endif endfor if home == "" " just pick the first directory @@ -717,18 +612,9 @@ fun! vimball#VimballHome() endif endif " insure that the home directory exists -" call Decho("picked home<".home.">") if !isdirectory(home) - if exists("g:vimball_mkdir") -" call Decho("home<".home."> isn't a directory -- making it now with g:vimball_mkdir<".g:vimball_mkdir.">") -" call Decho("system(".g:vimball_mkdir." ".shellescape(home).")") - call system(g:vimball_mkdir." ".shellescape(home)) - else -" call Decho("home<".home."> isn't a directory -- making it now with mkdir()") - call mkdir(home) - endif + call mkdir(home) endif -" call Dret("vimball#VimballHome <".home.">") return home endfun @@ -758,13 +644,11 @@ fun! vimball#SaveSettings() endif " vimballs should be in unix format setlocal ff=unix -" call Dret("SaveSettings") endfun " --------------------------------------------------------------------- " vimball#RestoreSettings: {{{2 fun! vimball#RestoreSettings() -" call Dfunc("RestoreSettings()") let @a = s:regakeep if exists("+acd") let &acd = s:acdkeep @@ -780,14 +664,12 @@ fun! vimball#RestoreSettings() let &l:ff = s:ffkeep if s:makeep[0] != 0 " restore mark a -" call Decho("restore mark-a: makeep=".string(makeep)) call setpos("'a",s:makeep) endif if exists("+acd") unlet s:acdkeep endif unlet s:regakeep s:eikeep s:fenkeep s:hidkeep s:ickeep s:repkeep s:vekeep s:makeep s:lzkeep s:pmkeep s:ffkeep -" call Dret("RestoreSettings") endfun let &cpo = s:keepcpo @@ -795,4 +677,4 @@ unlet s:keepcpo " --------------------------------------------------------------------- " Modelines: {{{1 -" vim: fdm=marker +" vim: fdm=marker et diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim index 1ce9cfc2f7..f4482fd7fc 100644 --- a/runtime/autoload/zip.vim +++ b/runtime/autoload/zip.vim @@ -21,6 +21,7 @@ " 2026 Feb 08 by Vim Project: use system() instead of :! " 2026 Mar 08 by Vim Project: Make ZipUpdatePS() check for powershell " 2026 Apr 01 by Vim Project: Detect more path traversal attacks +" 2026 Apr 05 by Vim Project: Detect more path traversal attacks " License: Vim License (see vim's :help license) " Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, @@ -395,9 +396,16 @@ fun! zip#Write(fname) if has("unix") let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','') let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','') + " fname should not start with a leading slash to avoid writing anywhere into the system + if fname =~ '^/' + call s:Mess('Error', "***error*** (zip#Write) Path Traversal Attack detected, not writing!") + call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!") + return + endif else let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','') let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','') + " TODO: what to check on MS-Windows to avoid writing absolute paths? endif if fname =~ '^[.]\{1,2}/' let gnu_cmd = g:zip_zipcmd . ' -d ' . s:Escape(fnamemodify(zipfile,":p"),0) . ' ' . s:Escape(fname,0) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index f49f40f451..e0c3f3bcab 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.2. Last change: 2026 Mar 25 +*builtin.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -82,7 +82,7 @@ browsedir({title}, {initdir}) String put up a directory requester bufadd({name}) Number add a buffer to the buffer list bufexists({buf}) Number |TRUE| if buffer {buf} exists buflisted({buf}) Number |TRUE| if buffer {buf} is listed -bufload({buf}) Number load buffer {buf} if not loaded yet +bufload({buf}) none load buffer {buf} if not loaded yet bufloaded({buf}) Number |TRUE| if buffer {buf} is loaded bufname([{buf}]) String name of the buffer {buf} bufnr([{buf} [, {create}]]) Number number of the buffer {buf} @@ -105,7 +105,7 @@ ch_evalraw({handle}, {string} [, {options}]) any evaluate {string} on raw {handle} ch_getbufnr({handle}, {what}) Number get buffer number for {handle}/{what} ch_getjob({channel}) Job get the Job of {channel} -ch_info({handle}) String info about channel {handle} +ch_info({handle}) Dict info about channel {handle} ch_listen({address} [, {options}]) Channel listen on {address} ch_log({msg} [, {handle}]) none write {msg} in the channel log file @@ -120,7 +120,7 @@ ch_readraw({handle} [, {options}]) ch_sendexpr({handle}, {expr} [, {options}]) any send {expr} over JSON {handle} ch_sendraw({handle}, {expr} [, {options}]) - any send {expr} over raw {handle} + none send {expr} over raw {handle} ch_setoptions({handle}, {options}) none set options for {handle} ch_status({handle} [, {options}]) @@ -192,7 +192,7 @@ extendnew({expr1}, {expr2} [, {expr3}]) List/Dict like |extend()| but creates a new List or Dictionary -feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer +feedkeys({string} [, {mode}]) none add key sequence to typeahead buffer filecopy({from}, {to}) Number |TRUE| if copying file {from} to {to} worked filereadable({file}) Number |TRUE| if {file} is a readable file @@ -219,7 +219,7 @@ foldtext() String line displayed for closed fold foldtextresult({lnum}) String text for closed fold at {lnum} foreach({expr1}, {expr2}) List/Tuple/Dict/Blob/String for each item in {expr1} call {expr2} -foreground() Number bring the Vim window to the foreground +foreground() none bring the Vim window to the foreground fullcommand({name} [, {vim9}]) String get full command from {name} funcref({name} [, {arglist}] [, {dict}]) Funcref reference to function {name} @@ -351,7 +351,7 @@ inputsecret({prompt} [, {text}]) insert({object}, {item} [, {idx}]) List insert {item} in {object} [before {idx}] -instanceof({object}, {class}) Number |TRUE| if {object} is an instance of +instanceof({object}, {class}) Bool |TRUE| if {object} is an instance of {class} interrupt() none interrupt script execution invert({expr}) Number bitwise invert @@ -391,7 +391,7 @@ list2tuple({list}) Tuple turn {list} of items into a tuple listener_add({callback} [, {buf} [, {unbuffered}]]) Number add a callback to listen to changes listener_flush([{buf}]) none invoke listener callbacks -listener_remove({id}) none remove a listener callback +listener_remove({id}) Number remove a listener callback localtime() Number current time log({expr}) Float natural logarithm (base e) of {expr} log10({expr}) Float logarithm of Float {expr} to base 10 @@ -455,8 +455,8 @@ popup_clear() none close all popup windows popup_close({id} [, {result}]) none close popup window {id} popup_create({what}, {options}) Number create a popup window popup_dialog({what}, {options}) Number create a popup window used as a dialog -popup_filter_menu({id}, {key}) Number filter for a menu popup window -popup_filter_yesno({id}, {key}) Number filter for a dialog popup window +popup_filter_menu({id}, {key}) Bool filter for a menu popup window +popup_filter_yesno({id}, {key}) Bool filter for a dialog popup window popup_findecho() Number get window ID of popup for `:echowin` popup_findinfo() Number get window ID of info popup window popup_findpreview() Number get window ID of preview popup window @@ -486,7 +486,7 @@ prompt_setinterrupt({buf}, {text}) none set prompt interrupt function prompt_setprompt({buf}, {text}) none set prompt text prop_add({lnum}, {col}, {props}) - none add one text property + Number add one text property prop_add_list({props}, [[{lnum}, {col}, {end-lnum}, {end-col}], ...]) none add multiple text properties prop_clear({lnum} [, {lnum-end} [, {props}]]) @@ -531,7 +531,7 @@ reltimefloat({time}) Float turn the time value into a Float reltimestr({time}) String turn time value into a String remote_expr({server}, {string} [, {idvar} [, {timeout}]]) String send expression -remote_foreground({server}) Number bring Vim server to the foreground +remote_foreground({server}) none bring Vim server to the foreground remote_peek({serverid} [, {retvar}]) Number check for reply string remote_read({serverid} [, {timeout}]) @@ -581,7 +581,7 @@ setbufvar({buf}, {varname}, {val}) none set {varname} in buffer {buf} to {val} setcellwidths({list}) none set character cell width overrides setcharpos({expr}, {list}) Number set the {expr} position to {list} -setcharsearch({dict}) Dict set character search from {dict} +setcharsearch({dict}) none set character search from {dict} setcmdline({str} [, {pos}]) Number set command-line setcmdpos({pos}) Number set cursor position in command-line setcursorcharpos({list}) Number move cursor to position in {list} @@ -644,7 +644,7 @@ sound_playfile({path} [, {callback}]) Number play sound file {path} sound_stop({id}) none stop playing sound {id} soundfold({word}) String sound-fold {word} -spellbadword() String badly spelled word at cursor +spellbadword() List badly spelled word at cursor spellsuggest({word} [, {max} [, {capital}]]) List spelling suggestions split({expr} [, {pat} [, {keepempty}]]) @@ -701,8 +701,7 @@ synconcealed({lnum}, {col}) List info about concealing synstack({lnum}, {col}) List stack of syntax IDs at {lnum} and {col} system({expr} [, {input}]) String output of shell command/filter {expr} -systemlist({expr} [, {input}]) - List output of shell command/filter {expr} +systemlist({expr} [, {input}]) List output of shell command/filter {expr} tabpagebuflist([{arg}]) List list of buffer numbers in tab page tabpagenr([{arg}]) Number number of current or last tab page tabpagewinnr({tabarg} [, {arg}]) @@ -741,7 +740,7 @@ term_setrestore({buf}, {command}) term_setsize({buf}, {rows}, {cols}) none set the size of a terminal term_start({cmd} [, {options}]) Number open a terminal window and run a job -term_wait({buf} [, {time}]) Number wait for screen to be updated +term_wait({buf} [, {time}]) none wait for screen to be updated terminalprops() Dict properties of the terminal test_alloc_fail({id}, {countdown}, {repeat}) none make memory allocation fail @@ -749,11 +748,11 @@ test_autochdir() none enable 'autochdir' during startup test_feedinput({string}) none add key sequence to input buffer test_garbagecollect_now() none free memory right now for testing test_garbagecollect_soon() none free memory soon for testing -test_getvalue({string}) any get value of an internal variable +test_getvalue({string}) Number get value of an internal variable test_gui_event({event}, {args}) bool generate a GUI event for testing test_ignore_error({expr}) none ignore a specific error test_mswin_event({event}, {args}) - bool generate MS-Windows event for testing + Bool generate MS-Windows event for testing test_null_blob() Blob null value for testing test_null_channel() Channel null value for testing test_null_dict() Dict null value for testing @@ -770,7 +769,7 @@ test_setmouse({row}, {col}) none set the mouse position for testing test_settime({expr}) none set current time for testing test_srand_seed([{seed}]) none set seed for testing srand() test_unknown() any unknown value for testing -test_void() any void value for testing +test_void() none void value for testing timer_info([{id}]) List information about timers timer_pause({id}, {pause}) none pause or unpause a timer timer_start({time}, {callback} [, {options}]) @@ -790,7 +789,7 @@ tuple2list({tuple}) List turn {tuple} of items into a list type({expr}) Number type of value {expr} typename({expr}) String representation of the type of {expr} undofile({name}) String undo file name for {name} -undotree([{buf}]) List undo file tree for buffer {buf} +undotree([{buf}]) Dict undo file tree for buffer {buf} uniq({list} [, {func} [, {dict}]]) List remove adjacent duplicates from a list uri_decode({string}) String URI-decode a string @@ -805,7 +804,7 @@ virtcol2col({winid}, {lnum}, {col}) Number byte index of a character on screen visualmode([{expr}]) String last visual mode used wildmenumode() Number whether 'wildmenu' mode is active -wildtrigger() Number start wildcard expansion +wildtrigger() none start wildcard expansion win_execute({id}, {command} [, {silent}]) String execute {command} in window {id} win_findbuf({bufnr}) List find windows containing {bufnr} @@ -1275,7 +1274,7 @@ balloon_show({expr}) *balloon_show()* {only available when compiled with the |+balloon_eval| or |+balloon_eval_term| feature} - Return type: |Number| + Return type: void balloon_split({msg}) *balloon_split()* @@ -1502,7 +1501,7 @@ bufload({buf}) *bufload()* Can also be used as a |method|: > eval 'somename'->bufload() < - Return type: |Number| + Return type: void bufloaded({buf}) *bufloaded()* @@ -1897,7 +1896,7 @@ clearmatches([{win}]) *clearmatches()* Can also be used as a |method|: > GetWin()->clearmatches() < - Return type: |Number| + Return type: void cmdcomplete_info() *cmdcomplete_info()* @@ -2017,7 +2016,7 @@ complete({startcol}, {matches}) *complete()* *E785* second argument: > GetMatches()->complete(col('.')) < - Return type: |Number| + Return type: void complete_add({expr}) *complete_add()* @@ -2661,7 +2660,7 @@ echoraw({string}) *echoraw()* call echoraw(&t_TI) < Use with care, you can mess up the terminal this way. - Return type: |Number| + Return type: void empty({expr}) *empty()* @@ -2704,7 +2703,7 @@ err_teapot([{expr}]) *err_teapot()* indicating that coffee is temporarily not available. If {expr} is present it must be a String. - Return type: |Number| + Return type: void escape({string}, {chars}) *escape()* @@ -3221,7 +3220,7 @@ feedkeys({string} [, {mode}]) *feedkeys()* Can also be used as a |method|: > GetInput()->feedkeys() < - Return type: |Number| + Return type: void filecopy({from}, {to}) *filecopy()* @@ -3658,7 +3657,7 @@ foreground() *foreground()* allow a window to bring itself to the foreground. Use |remote_foreground()| instead. - Return type: |Number| + Return type: void {only in the Win32, Motif and GTK GUI versions and the Win32 console version} @@ -3810,7 +3809,7 @@ garbagecollect([{atexit}]) *garbagecollect()* type a character. To force garbage collection immediately use |test_garbagecollect_now()|. - Return type: |String| + Return type: void get({list}, {idx} [, {default}]) *get()* *get()-list* @@ -6273,7 +6272,7 @@ instanceof({object}, {class}) *instanceof()* *E614* *E616* *E693* < Can also be used as a |method|: > myobj->instanceof(mytype) < - Return type: |Number| + Return type: |vim9-boolean| interrupt() *interrupt()* @@ -6881,7 +6880,7 @@ listener_flush([{buf}]) *listener_flush()* Can also be used as a |method|: > GetBuffer()->listener_flush() < - Return type: |Number| + Return type: void listener_remove({id}) *listener_remove()* @@ -7225,7 +7224,7 @@ mapset({dict}) mapset(d) endfor < - Return type: |Number| + Return type: void match({expr}, {pat} [, {start} [, {count}]]) *match()* @@ -8488,8 +8487,10 @@ prompt_setcallback({buf}, {expr}) *prompt_setcallback()* < Can also be used as a |method|: > GetBuffer()->prompt_setcallback(callback) +< + Return type: void -< {only available when compiled with the |+channel| feature} + {only available when compiled with the |+channel| feature} prompt_setinterrupt({buf}, {expr}) *prompt_setinterrupt()* Set a callback for buffer {buf} to {expr}. When {expr} is an @@ -8503,7 +8504,7 @@ prompt_setinterrupt({buf}, {expr}) *prompt_setinterrupt()* Can also be used as a |method|: > GetBuffer()->prompt_setinterrupt(callback) < - Return type: |Number| + Return type: void {only available when compiled with the |+channel| feature} @@ -8517,7 +8518,7 @@ prompt_setprompt({buf}, {text}) *prompt_setprompt()* Can also be used as a |method|: > GetBuffer()->prompt_setprompt('command: ') < - Return type: |Number| + Return type: void {only available when compiled with the |+channel| feature} @@ -8880,7 +8881,7 @@ redraw_listener_remove({id}) *redraw_listener_remove()* Can also be used as a |method|: > GetRedrawListenerId()->redraw_listener_remove() < - Return type: |Number| + Return type: void reduce({object}, {func} [, {initial}]) *reduce()* *E998* @@ -9052,7 +9053,7 @@ remote_foreground({server}) *remote_foreground()* Can also be used as a |method|: > ServerName()->remote_foreground() < - Return type: |Number| + Return type: void {only in the Win32, Motif and GTK GUI versions and the Win32 console version} @@ -9136,7 +9137,7 @@ remote_startserver({name}) *remote_startserver()* *E941* *E942* Can also be used as a |method|: > ServerName()->remote_startserver() < - Return type: |Number| + Return type: void {only available when compiled with the |+clientserver| feature} @@ -9884,7 +9885,7 @@ setbufvar({buf}, {varname}, {val}) *setbufvar()* third argument: > GetValue()->setbufvar(buf, varname) < - Return type: |Number| + Return type: void setcellwidths({list}) *setcellwidths()* @@ -9921,7 +9922,7 @@ setcellwidths({list}) *setcellwidths()* match with what Vim knows about each emoji. If it doesn't look right you need to adjust the {list} argument. - Return type: |Number| + Return type: void setcharpos({expr}, {list}) *setcharpos()* @@ -9964,7 +9965,7 @@ setcharsearch({dict}) *setcharsearch()* Can also be used as a |method|: > SavedSearch()->setcharsearch() < - Return type: dict + Return type: void setcmdline({str} [, {pos}]) *setcmdline()* @@ -10031,7 +10032,7 @@ setenv({name}, {val}) *setenv()* second argument: > GetPath()->setenv('PATH') < - Return type: |Number| + Return type: void setfperm({fname}, {mode}) *setfperm()* *chmod* @@ -10390,7 +10391,7 @@ settabvar({tabnr}, {varname}, {val}) *settabvar()* third argument: > GetValue()->settabvar(tab, name) < - Return type: |Number| + Return type: void settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()* @@ -10415,7 +10416,7 @@ settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()* fourth argument: > GetValue()->settabwinvar(tab, winnr, name) < - Return type: |Number| + Return type: void settagstack({nr}, {dict} [, {action}]) *settagstack()* @@ -10468,7 +10469,7 @@ setwinvar({winnr}, {varname}, {val}) *setwinvar()* third argument: > GetValue()->setwinvar(winnr, name) < - Return type: |Number| + Return type: void sha256({expr}) *sha256()* @@ -10730,7 +10731,7 @@ sound_clear() *sound_clear()* On some Linux systems you may need the libcanberra-pulse package, otherwise sound may not stop. - Return type: |Number| + Return type: void {only available when compiled with the |+sound| feature} @@ -10800,7 +10801,7 @@ sound_stop({id}) *sound_stop()* Can also be used as a |method|: > soundid->sound_stop() < - Return type: |Number| + Return type: void {only available when compiled with the |+sound| feature} @@ -12085,7 +12086,7 @@ timer_pause({timer}, {paused}) *timer_pause()* Can also be used as a |method|: > GetTimer()->timer_pause(1) < - Return type: |Number| + Return type: void {only available when compiled with the |+timers| feature} @@ -12145,7 +12146,7 @@ timer_stop({timer}) *timer_stop()* Can also be used as a |method|: > GetTimer()->timer_stop() < - Return type: |Number| + Return type: void {only available when compiled with the |+timers| feature} @@ -12155,7 +12156,7 @@ timer_stopall() *timer_stopall()* invoked. Useful if a timer is misbehaving. If there are no timers there is no error. - Return type: |Number| + Return type: void {only available when compiled with the |+timers| feature} @@ -12645,7 +12646,7 @@ wildtrigger() *wildtrigger()* Return value is always 0. - Return type: |Number| + Return type: void win_execute({id}, {command} [, {silent}]) *win_execute()* @@ -12997,7 +12998,7 @@ winrestview({dict}) *winrestview()* Can also be used as a |method|: > GetView()->winrestview() < - Return type: |Number| + Return type: void winsaveview() *winsaveview()* diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt index 7ad10fa0cf..55b95c632f 100644 --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -1,4 +1,4 @@ -*channel.txt* For Vim version 9.2. Last change: 2026 Mar 13 +*channel.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -549,7 +549,7 @@ ch_close({handle}) *ch_close()* Can also be used as a |method|: > GetChannel()->ch_close() < - Return type: |Number| + Return type: void ch_close_in({handle}) *ch_close_in()* Close the "in" part of {handle}. See |channel-close-in|. @@ -559,7 +559,7 @@ ch_close_in({handle}) *ch_close_in()* Can also be used as a |method|: > GetChannel()->ch_close_in() < - Return type: |Number| + Return type: void ch_evalexpr({handle}, {expr} [, {options}]) *ch_evalexpr()* @@ -674,7 +674,9 @@ ch_listen({address} [, {options}]) *E1573* *E1574* *ch_listen()* Returns a Channel. Use |ch_status()| to check for failure. {address} is a String, see |channel-address| for the possible - accepted forms. Note: IPv6 is not yet supported. + accepted forms, however binding to all interfaces is not + allowed for security reasons. + Note: IPv6 is not yet supported. If {options} is given it must be a |Dictionary|. See |channel-open-options|. @@ -708,7 +710,7 @@ ch_log({msg} [, {handle}]) *ch_log()* Can also be used as a |method|: > 'did something'->ch_log() < - Return type: dict + Return type: void ch_logfile({fname} [, {mode}]) *ch_logfile()* Start logging channel activity to {fname}. @@ -736,7 +738,7 @@ ch_logfile({fname} [, {mode}]) *ch_logfile()* Can also be used as a |method|: > 'logfile'->ch_logfile('w') < - Return type: |Number| + Return type: void ch_open({address} [, {options}]) *ch_open()* Open a channel to {address}. See |channel|. @@ -825,7 +827,7 @@ ch_sendraw({handle}, {expr} [, {options}]) *ch_sendraw()* Can also be used as a |method|: > GetChannel()->ch_sendraw(rawexpr) < - Return type: dict or |String| + Return type: void ch_setoptions({handle}, {options}) *ch_setoptions()* Set options on {handle}: @@ -844,7 +846,7 @@ ch_setoptions({handle}, {options}) *ch_setoptions()* Can also be used as a |method|: > GetChannel()->ch_setoptions(options) < - Return type: |Number| + Return type: void ch_status({handle} [, {options}]) *ch_status()* Return the status of {handle}: @@ -1038,7 +1040,7 @@ job_setoptions({job}, {options}) *job_setoptions()* Can also be used as a |method|: > GetJob()->job_setoptions(options) < - Return type: |Number| + Return type: void job_start({command} [, {options}]) *job_start()* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 5026cef139..9a3da1ad9f 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.2. Last change: 2026 Apr 03 +*options.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -5311,7 +5311,8 @@ A jump table for the options with a short description can be found at |Q_op|. command line has no uppercase characters, the added character is converted to lowercase. CTRL-R CTRL-W can be used to add the word at the end of the current - match, excluding the characters that were already typed. + match, excluding the characters that were already typed (starting from + the beginning of the word). NOTE: This option is reset when 'compatible' is set. *'indentexpr'* *'inde'* diff --git a/runtime/doc/pi_vimball.txt b/runtime/doc/pi_vimball.txt index fdf7173068..07fc68f7eb 100644 --- a/runtime/doc/pi_vimball.txt +++ b/runtime/doc/pi_vimball.txt @@ -1,4 +1,4 @@ -*pi_vimball.txt* For Vim version 9.2. Last change: 2026 Feb 14 +*pi_vimball.txt* For Vim version 9.2. Last change: 2026 Apr 05 ---------------- Vimball Archiver @@ -93,21 +93,6 @@ MAKING A VIMBALL *:MkVimball* make. -MAKING DIRECTORIES VIA VIMBALLS *g:vimball_mkdir* - - First, the |mkdir()| command is tried (not all systems support it). - - If it doesn't exist, then if g:vimball_mkdir doesn't exist, it is set - as follows: > - |g:netrw_localmkdir|, if it exists - "mkdir" , if it is executable - "makedir" , if it is executable - Otherwise , it is undefined. -< One may explicitly specify the directory making command using - g:vimball_mkdir. This command is used to make directories that - are needed as indicated by the vimball. - - CONTROLLING THE VIMBALL EXTRACTION DIRECTORY *g:vimball_home* You may override the use of the 'runtimepath' by specifying a diff --git a/runtime/doc/pi_zip.txt b/runtime/doc/pi_zip.txt index b1bc7fd7dc..e9294b4059 100644 --- a/runtime/doc/pi_zip.txt +++ b/runtime/doc/pi_zip.txt @@ -1,4 +1,4 @@ -*pi_zip.txt* For Vim version 9.2. Last change: 2026 Feb 14 +*pi_zip.txt* For Vim version 9.2. Last change: 2026 Apr 05 +====================+ | Zip File Interface | @@ -33,6 +33,10 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* also write to the file. Currently, one may not make a new file in zip archives via the plugin. + The zip plugin tries to detect some common path traversal attack + patterns, but it may not catch all possible cases. Please be very + careful when using this plugin with untrusted input. + COMMANDS~ *zip-x* x : extract a listed file when the cursor is atop it diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt index e968a21075..6b99ac47ee 100644 --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -1,4 +1,4 @@ -*popup.txt* For Vim version 9.2. Last change: 2026 Mar 02 +*popup.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -254,7 +254,7 @@ popup_clear([{force}]) when it is the current window. If a terminal is running in a popup it is killed. - Return type: |Number| + Return type: void popup_close({id} [, {result}]) *popup_close()* @@ -269,7 +269,7 @@ popup_close({id} [, {result}]) *popup_close()* Can also be used as a |method|: > GetPopup()->popup_close() < - Return type: |Number| + Return type: void popup_create({what}, {options}) *popup_create()* @@ -351,7 +351,7 @@ popup_filter_menu({id}, {key}) *popup_filter_menu()* To add shortcut keys, see the example here: |popup_menu-shortcut-example| - Return type: |Number| + Return type: |vim9-boolean| popup_filter_yesno({id}, {key}) *popup_filter_yesno()* @@ -363,7 +363,7 @@ popup_filter_yesno({id}, {key}) *popup_filter_yesno()* keys are ignored. See the example here: |popup_dialog-example| - Return type: |Number| + Return type: |vim9-boolean| popup_findecho() *popup_findecho()* @@ -471,7 +471,7 @@ popup_hide({id}) *popup_hide()* Can also be used as a |method|: > GetPopup()->popup_hide() < - Return type: |Number| + Return type: void popup_list() *popup_list()* @@ -542,7 +542,7 @@ popup_move({id}, {options}) *popup_move()* Can also be used as a |method|: > GetPopup()->popup_move(options) < - Return type: |Number| + Return type: void popup_notification({what}, {options}) *popup_notification()* @@ -624,7 +624,7 @@ popup_setoptions({id}, {options}) *popup_setoptions()* Can also be used as a |method|: > GetPopup()->popup_setoptions(options) < - Return type: |Number| + Return type: void popup_settext({id}, {text}) *popup_settext()* @@ -636,7 +636,7 @@ popup_settext({id}, {text}) *popup_settext()* Can also be used as a |method|: > GetPopup()->popup_settext('hello') < - Return type: |Number| + Return type: void popup_show({id}) *popup_show()* diff --git a/runtime/doc/tags b/runtime/doc/tags index 699bbfa0c4..fc1e47e4a4 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -8145,7 +8145,6 @@ g:vim_indent_cont indent.txt /*g:vim_indent_cont* g:vim_json_conceal syntax.txt /*g:vim_json_conceal* g:vim_json_warnings syntax.txt /*g:vim_json_warnings* g:vimball_home pi_vimball.txt /*g:vimball_home* -g:vimball_mkdir pi_vimball.txt /*g:vimball_mkdir* g:vimsyn_comment_strings syntax.txt /*g:vimsyn_comment_strings* g:vimsyn_embed syntax.txt /*g:vimsyn_embed* g:vimsyn_folding syntax.txt /*g:vimsyn_folding* diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 7a4f9cd537..6c9430dc81 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -1,4 +1,4 @@ -*terminal.txt* For Vim version 9.2. Last change: 2026 Apr 02 +*terminal.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -596,7 +596,7 @@ term_dumpwrite({buf}, {filename} [, {options}]) *term_dumpwrite()* name: > GetFilename()->term_dumpwrite(bufnr) < - Return type: |Number| + Return type: void term_getaltscreen({buf}) *term_getaltscreen()* @@ -817,7 +817,7 @@ term_sendkeys({buf}, {keys}) *term_sendkeys()* Can also be used as a |method|: > GetBufnr()->term_sendkeys(keys) < - Return type: |Number| + Return type: void term_setansicolors({buf}, {colors}) *term_setansicolors()* @@ -852,7 +852,7 @@ term_setansicolors({buf}, {colors}) *term_setansicolors()* Can also be used as a |method|: > GetBufnr()->term_setansicolors(colors) < - Return type: |Number| + Return type: void {only available with GUI enabled and/or the |+termguicolors| feature} @@ -870,7 +870,7 @@ term_setapi({buf}, {expr}) *term_setapi()* When used as a method the base is used for {buf}: > GetBufnr()->term_setapi({expr}) < - Return type: |Number| + Return type: void term_setkill({buf}, {how}) *term_setkill()* @@ -888,7 +888,7 @@ term_setkill({buf}, {how}) *term_setkill()* Can also be used as a |method|: > GetBufnr()->term_setkill(how) < - Return type: |Number| + Return type: void term_setrestore({buf}, {command}) *term_setrestore()* @@ -903,7 +903,7 @@ term_setrestore({buf}, {command}) *term_setrestore()* Can also be used as a |method|: > GetBufnr()->term_setrestore(command) < - Return type: |Number| + Return type: void term_setsize({buf}, {rows}, {cols}) *term_setsize()* *E955* @@ -919,7 +919,7 @@ term_setsize({buf}, {rows}, {cols}) *term_setsize()* *E955* Can also be used as a |method|: > GetBufnr()->term_setsize(rows, cols) < - Return type: |Number| + Return type: void term_start({cmd} [, {options}]) *term_start()* @@ -1027,7 +1027,7 @@ term_wait({buf} [, {time}]) *term_wait()* Can also be used as a |method|: > GetBufnr()->term_wait() < - Return type: |Number| + Return type: void ============================================================================== 3. Terminal communication *terminal-communication* diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index ba98e048ef..24e3a4aa25 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -1,4 +1,4 @@ -*testing.txt* For Vim version 9.2. Last change: 2026 Feb 14 +*testing.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -46,14 +46,14 @@ test_alloc_fail({id}, {countdown}, {repeat}) *test_alloc_fail()* Can also be used as a |method|: > GetAllocId()->test_alloc_fail() < - Return type: |Number| + Return type: void test_autochdir() *test_autochdir()* Set a flag to enable the effect of 'autochdir' before Vim startup has finished. - Return type: |Number| + Return type: void test_feedinput({string}) *test_feedinput()* @@ -64,7 +64,7 @@ test_feedinput({string}) *test_feedinput()* Can also be used as a |method|: > GetText()->test_feedinput() < - Return type: |Number| + Return type: void test_garbagecollect_now() *test_garbagecollect_now()* @@ -75,13 +75,13 @@ test_garbagecollect_now() *test_garbagecollect_now()* This will not work when called from a :def function, because variables on the stack will be freed. - Return type: |Number| + Return type: void test_garbagecollect_soon() *test_garbagecollect_soon()* Set the flag to call the garbagecollector as if in the main loop. Only to be used in tests. - Return type: |Number| + Return type: void test_getvalue({name}) *test_getvalue()* Get the value of an internal variable. These values for @@ -237,7 +237,7 @@ test_ignore_error({expr}) *test_ignore_error()* Can also be used as a |method|: > GetErrorText()->test_ignore_error() < - Return type: |Number| + Return type: void test_mswin_event({event}, {args}) *test_mswin_event()* Generate a low-level MS-Windows {event} with arguments {args} @@ -381,7 +381,7 @@ test_option_not_set({name}) *test_option_not_set()* Can also be used as a |method|: > GetOptionName()->test_option_not_set() < - Return type: |Number| + Return type: void test_override({name}, {val}) *test_override()* Overrides certain parts of Vim's internal processing to be @@ -438,7 +438,7 @@ test_override({name}, {val}) *test_override()* < Can also be used as a |method|: > GetOverrideVal()-> test_override('starting') < - Return type: |Number| + Return type: void test_refcount({expr}) *test_refcount()* Return the reference count of {expr}. When {expr} is of a @@ -457,7 +457,7 @@ test_setmouse({row}, {col}) *test_setmouse()* call test_setmouse(4, 20) call feedkeys("\", "xt") < - Return type: |Number| + Return type: void test_settime({expr}) *test_settime()* @@ -472,13 +472,13 @@ test_settime({expr}) *test_settime()* Can also be used as a |method|: > GetTime()->test_settime() < - Return type: |Number| + Return type: void test_srand_seed([{seed}]) *test_srand_seed()* When {seed} is given this sets the seed value used by `srand()`. When omitted the test seed is removed. - Return type: |Number| + Return type: void test_unknown() *test_unknown()* Return a value with unknown type. Only useful for testing. diff --git a/runtime/doc/textprop.txt b/runtime/doc/textprop.txt index fbe4231c7f..f57a238e29 100644 --- a/runtime/doc/textprop.txt +++ b/runtime/doc/textprop.txt @@ -1,4 +1,4 @@ -*textprop.txt* For Vim version 9.2. Last change: 2026 Feb 14 +*textprop.txt* For Vim version 9.2. Last change: 2026 Apr 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -270,6 +270,8 @@ prop_add_list({props}, [{item}, ...]) *prop_add_list()* < Can also be used as a |method|: > GetProp()->prop_add_list([[1, 1, 1, 2], [1, 4, 1, 8]]) +< + Return type: void prop_clear({lnum} [, {lnum-end} [, {props}]]) *prop_clear()* @@ -283,7 +285,7 @@ prop_clear({lnum} [, {lnum-end} [, {props}]]) *prop_clear()* Can also be used as a |method|: > GetLnum()->prop_clear() < - Return type: |Number| + Return type: void prop_find({props} [, {direction}]) *prop_find()* @@ -444,7 +446,7 @@ prop_type_add({name}, {props}) *prop_type_add()* *E969* *E970* Can also be used as a |method|: > GetPropName()->prop_type_add(props) < - Return type: |Number| + Return type: void prop_type_change({name}, {props}) *prop_type_change()* @@ -455,7 +457,7 @@ prop_type_change({name}, {props}) *prop_type_change()* Can also be used as a |method|: > GetPropName()->prop_type_change(props) < - Return type: |Number| + Return type: void prop_type_delete({name} [, {props}]) *prop_type_delete()* @@ -472,7 +474,7 @@ prop_type_delete({name} [, {props}]) *prop_type_delete()* Can also be used as a |method|: > GetPropName()->prop_type_delete() < - Return type: |Number| + Return type: void prop_type_get({name} [, {props}]) *prop_type_get()* diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw.vim b/runtime/pack/dist/opt/netrw/autoload/netrw.vim index 1520ff969e..8e5fdb5397 100644 --- a/runtime/pack/dist/opt/netrw/autoload/netrw.vim +++ b/runtime/pack/dist/opt/netrw/autoload/netrw.vim @@ -23,6 +23,7 @@ " 2026 Feb 27 by Vim Project Make the hostname validation more strict " 2026 Mar 01 by Vim Project include portnumber in hostname checking #19533 " 2026 Apr 01 by Vim Project use fnameescape() with netrw#FileUrlEdit() +" 2026 Apr 05 by Vim Project Fix netrw#RFC2396() #19913 " Copyright: Copyright (C) 2016 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright @@ -8826,8 +8827,7 @@ endfunction " netrw#RFC2396: converts %xx into characters {{{2 function netrw#RFC2396(fname) - let fname = escape(substitute(a:fname,'%\(\x\x\)','\=printf("%c","0x".submatch(1))','ge')," \t") - return fname + return substitute(a:fname, '%\(\x\x\)', '\=printf("%c","0x".submatch(1))', 'ge') endfunction " netrw#UserMaps: supports user-specified maps {{{2 diff --git a/runtime/syntax/log.vim b/runtime/syntax/log.vim index abf3d716c2..296d46a329 100644 --- a/runtime/syntax/log.vim +++ b/runtime/syntax/log.vim @@ -1,6 +1,6 @@ " Vim syntax file " Language: Generic log file -" Maintainer: Mao-Yining +" Maintainer: Mao-Yining " Former Maintainer: MTDL9 " Latest Revision: 2025-10-31 @@ -10,10 +10,9 @@ endif syntax case ignore -" Operators +" Symbols / special characters "--------------------------------------------------------------------------- -syn match logOperator display '[;,\?\:\.\<=\>\~\/\@\!$\%&\+\-\|\^(){}\*#]' -syn match logBrackets display '[][]' +syn match logSymbol display '[!@#$%^&*;:?]' " For Visual Separator and Apache CLF "--------------------------------------------------------------------------- @@ -22,10 +21,10 @@ syn match logSeparator display '- - ' " Strings " ------------------------------ -syn region LogString start=/"/ end=/"/ end=/$/ skip=/\\./ contains=logJavaError -syn region LogString start=/`/ end=/`/ end=/$/ skip=/\\./ contains=logJavaError +syn region logString start=/"/ end=/"/ end=/$/ skip=/\\./ contains=logJavaError +syn region logString start=/`/ end=/`/ end=/$/ skip=/\\./ contains=logJavaError " Quoted strings, but no match on quotes like `don't`, possessive `s'` and `'s` -syn region LogString start=/\(s\)\@' syn match logNumberHex display '\<\x\{4,}\>' " Numbers in Hardware Description Languages e.g. Verilog -" These must be placed after LogString to ensure they take precedence +" These must be placed after logString to ensure they take precedence syn match logNumber display '\'d\d\+\>' syn match logNumberBin display '\'b[01]\+\>' syn match logNumberOct display '\'o\o\+\>' @@ -68,9 +67,9 @@ syn match logDate display '\<\d\{1,2}[- ]\a\{3}[- ]\d\{4}\>' " Weekday string syn keyword logDate Mon Tue Wed Thu Fri Sat Sun " Matches 12:09:38 or 00:03:38.129Z or 01:32:12.102938 +0700 or 01:32:12.1234567890 or 21:14:18+11:00 -syn match logTime display '\d\{2}:\d\{2}:\d\{2}\(\.\d\{2,9}\)\?\(\s\?[-+]\(\d\{1,2\}:\d\{2\}\|\d\{2,4}\)\|Z\)\?\>' nextgroup=logTimeZone,logSysColumns skipwhite +syn match logTime display '\d\{2}:\d\{2}:\d\{2}\(\.\d\{2,9}\)\?\(\s\?[-+]\(\d\{1,2\}:\d\{2\}\|\d\{2,4}\)\|Z\)\?\>' nextgroup=logTimeZone,logSysColumn skipwhite " Time zone e.g. Z, +08:00, PST -syn match logTimeZone display 'Z\|[+-]\d\{2}:\d\{2}\|\a\{3}\>' contained skipwhite nextgroup=logSysColumns +syn match logTimeZone display 'Z\|[+-]\d\{2}:\d\{2}\|\a\{3}\>' contained skipwhite nextgroup=logSysColumn " Matches time durations like 1ms or 1y 2d 23ns 3.14s 1.2e4s 3E+20h syn match logDuration display '\(\(\(\d\+d\)\?\d\+h\)\?\d\+m\)\?\d\+\(\.\d\+\)\?[mun]\?s\>' @@ -95,13 +94,13 @@ syn match logFilePath display '\(^\|\s\|=\)\zs\\\\\f\+\ze' " Java Errors "--------------------------------------------------------------------------- -syn match logJavaError '\%(\%(Error\|Exception\):\s*\)\zs\w.\{-}\ze\(\\n\|$\)' contained +syn match logJavaError '\%(\%(Error\|Exception\):\s*\)\zs\w.\{-}\ze\(\\n\|$\)' contained " Syslog Columns "--------------------------------------------------------------------------- " Syslog hostname, program and process number columns -syn match logSysColumns '\w\(\w\|\.\|-\)\+ \(\w\|\.\|-\)\+\(\[\d\+\]\)\?:' contains=logOperator,@logLvs,LogSysProcess contained -syn match logSysProcess '\(\w\|\.\|-\)\+\(\[\d\+\]\)\?:' contains=logOperator,logNumber,logBrackets contained +syn match logSysColumn '\w\(\w\|\.\|-\)\+ \(\w\|\.\|-\)\+\(\[\d\+\]\)\?:' contained contains=@logLvs,logSysProcess +syn match logSysProcess '\(\w\|\.\|-\)\+\(\[\d\+\]\)\?:' contained contains=logNumber " XML Tags "--------------------------------------------------------------------------- @@ -109,47 +108,47 @@ syn match logSysProcess '\(\w\|\.\|-\)\+\(\[\d\+\]\)\?:' contains=logOperator, syn match logXmlHeader // contains=logString,logXmlAttribute,logXmlNamespace syn match logXmlDoctype /]*>/ contains=logString,logXmlAttribute,logXmlNamespace syn match logXmlTag /<\/\?\(\(\w\|-\)\+:\)\?\(\w\|-\)\+\(\(\n\|\s\)\+\(\(\w\|-\)\+:\)\?\(\w\|-\)\+\(="[^"]*"\|='[^']*'\)\?\)*\s*\/\?>/ contains=logString,logXmlAttribute,logXmlNamespace -syn match logXmlAttribute contained "\w\+=" contains=logOperator -syn match logXmlAttribute contained "\(\n\|\s\)\(\(\w\|-\)\+:\)\?\(\w\|-\)\+\(=\)\?" contains=logXmlNamespace,logOperator -syn match logXmlNamespace contained "\(\w\|-\)\+:" contains=logOperator +syn match logXmlAttribute contained "\w\+=" +syn match logXmlAttribute contained "\(\n\|\s\)\(\(\w\|-\)\+:\)\?\(\w\|-\)\+\(=\)\?" contains=logXmlNamespace +syn match logXmlNamespace contained "\(\w\|-\)\+:" syn region logXmlComment start=// syn match logXmlCData // syn match logXmlEntity /&#\?\w\+;/ " Levels "--------------------------------------------------------------------------- -syn keyword logLvFatal FATAL Fatal fatal -syn keyword logLvEmergency EMERG[ENCY] Emerg[ency] emerg[ency] -syn keyword logLvAlert ALERT Alert alert -syn keyword logLvCritical CRIT[ICAL] Crit[ical] crit[ical] -syn keyword logLvError E ERR[ORS] Err[ors] err[ors] -syn keyword logLvFail F FAIL[ED] Fail[ed] fail[ed] FAILURE Failure failure -syn keyword logLvFault FAULT Fault fault -syn keyword logLvNack NACK Nack nack NAK Nak nak -syn keyword logLvWarning W WARN[ING] Warn[ing] warn[ing] -syn keyword logLvBad BAD Bad bad -syn keyword logLvNotice NOTICE Notice notice -syn keyword logLvInfo I INFO Info info -syn keyword logLvDebug D DEBUG Debug debug DBG Dbg dbg -syn keyword logLvTrace TRACE Trace trace -syn keyword logLvVerbose V VERBOSE Verbose verbose -syn keyword logLvPass PASS[ED] Pass[ed] pass[ed] -syn keyword logLvSuccess SUCCEED[ED] Succeed[ed] succeed[ed] SUCCESS Success success +syn keyword logLvFatal FATAL +syn keyword logLvEmergency EMERG[ENCY] +syn keyword logLvAlert ALERT +syn keyword logLvCritical CRIT[ICAL] +syn keyword logLvError E ERR[ORS] +syn keyword logLvFail F FAIL[ED] FAILURE +syn keyword logLvFault FAULT +syn keyword logLvNack NACK NAK +syn keyword logLvWarning W WARN[ING] +syn keyword logLvBad BAD +syn keyword logLvNotice NOTICE +syn keyword logLvInfo I INFO +syn keyword logLvDebug D DEBUG +syn keyword logLvTrace TRACE Trace +syn keyword logLvVerbose V VERBOSE +syn keyword logLvPass PASS[ED] +syn keyword logLvSuccess SUCCEED[ED] SUCCESS " Composite log levels e.g. *_INFO -syn match logLvFatal display '\<\u\+_FATAL\>' -syn match logLvEmergency display '\<\u\+_EMERG\(ENCY\)\?\>' -syn match logLvAlert display '\<\u\+_ALERT\>' -syn match logLvCritical display '\<\u\+_CRIT\(ICAL\)\?\>' -syn match logLvError display '\<\u\+_ERR\(OR\)\?\>' -syn match logLvFail display '\<\u\+_FAIL\(URE\)\?\>' -syn match logLvWarning display '\<\u\+_WARN\(ING\)\?\>' -syn match logLvNotice display '\<\u\+_NOTICE\>' -syn match logLvInfo display '\<\u\+_INFO\>' -syn match logLvDebug display '\<\u\+_DEBUG\>' -syn match logLvTrace display '\<\u\+_TRACE\>' +syn match logLvFatal display '\<\u\+_FATAL\>' +syn match logLvEmergency display '\<\u\+_EMERG\(ENCY\)\?\>' +syn match logLvAlert display '\<\u\+_ALERT\>' +syn match logLvCritical display '\<\u\+_CRIT\(ICAL\)\?\>' +syn match logLvError display '\<\u\+_ERR\(OR\)\?\>' +syn match logLvFail display '\<\u\+_FAIL\(URE\)\?\>' +syn match logLvWarning display '\<\u\+_WARN\(ING\)\?\>' +syn match logLvNotice display '\<\u\+_NOTICE\>' +syn match logLvInfo display '\<\u\+_INFO\>' +syn match logLvDebug display '\<\u\+_DEBUG\>' +syn match logLvTrace display '\<\u\+_TRACE\>' -syn cluster logLvs contains=LogLvFatal,LogLvEmergency,LogLvAlert,LogLvCritical,LogLvError,LogLvFail,LogLvFault,LogLvNack,LogLvWarning,LogLvBad,LogLvNotice,LogLvInfo,LogLvDebug,LogLvTrace,LogLvVerbose,LogLvPass,LogLvSuccess +syn cluster logLvs contains=logLvFatal,logLvEmergency,logLvAlert,logLvCritical,logLvError,logLvFail,logLvFault,logLvNack,logLvWarning,logLvBad,logLvNotice,logLvInfo,logLvDebug,logLvTrace,logLvVerbose,logLvPass,logLvSuccess " Highlight links "--------------------------------------------------------------------------- @@ -179,7 +178,7 @@ hi def link logFilePath Structure hi def link logJavaError ErrorMsg -hi def link logSysColumns Statement +hi def link logSysColumn Statement hi def link logSysProcess Function hi def link logXmlHeader Function @@ -191,32 +190,31 @@ hi def link logXmlComment Comment hi def link logXmlCData String hi def link logXmlEntity Special -hi def link logOperator Special -hi def link logBrackets Special +hi def link logSymbol Delimiter hi def link logSeparator Comment -hi def link LogLvFatal ErrorMsg -hi def link LogLvEmergency ErrorMsg -hi def link LogLvAlert ErrorMsg -hi def link LogLvCritical ErrorMsg -hi def link LogLvError ErrorMsg -hi def link LogLvFail ErrorMsg -hi def link LogLvFault ErrorMsg -hi def link LogLvNack ErrorMsg -hi def link LogLvWarning WarningMsg -hi def link LogLvBad WarningMsg -hi def link LogLvNotice Exception -hi def link LogLvInfo LogBlue -hi def link LogLvDebug Debug -hi def link LogLvTrace Special -hi def link LogLvVerbose Special -hi def link LogLvPass LogGreen -hi def link LogLvSuccess LogGreen +hi def link logLvFatal ErrorMsg +hi def link logLvEmergency ErrorMsg +hi def link logLvAlert ErrorMsg +hi def link logLvCritical ErrorMsg +hi def link logLvError ErrorMsg +hi def link logLvFail ErrorMsg +hi def link logLvFault ErrorMsg +hi def link logLvNack ErrorMsg +hi def link logLvWarning WarningMsg +hi def link logLvBad WarningMsg +hi def link logLvNotice Exception +hi def link logLvInfo logBlue +hi def link logLvDebug Debug +hi def link logLvTrace Special +hi def link logLvVerbose Special +hi def link logLvPass logGreen +hi def link logLvSuccess logGreen " Custom highlight group " ------------------------------ -hi logGreen ctermfg=lightgreen guifg=#a4c672 -hi logBlue ctermfg=lightblue guifg=#92bcfc +hi logGreen ctermfg=LightGreen guifg=LightGreen +hi logBlue ctermfg=LightBlue guifg=LightBlue let b:current_syntax = 'log' diff --git a/runtime/syntax/zathurarc.vim b/runtime/syntax/zathurarc.vim index 32997c2d2d..3e35522e96 100644 --- a/runtime/syntax/zathurarc.vim +++ b/runtime/syntax/zathurarc.vim @@ -4,6 +4,7 @@ " Documentation: https://pwmt.org/projects/zathura/documentation/ " Upstream: https://github.com/Freed-Wu/zathurarc.vim " Latest Revision: 2024-09-16 +" 2026 Apr 04 by Vim project: add page-v-padding and page-h-padding if exists('b:current_syntax') finish @@ -22,7 +23,33 @@ syntax region zathurarcString start=`'` skip=`\\'` end=`'` syntax keyword zathurarcMode normal fullscreen presentation index syntax keyword zathurarcBoolean true false syntax keyword zathurarcCommand include map set unmap -syntax keyword zathurarcOption abort-clear-search adjust-open advance-pages-per-row completion-bg completion-fg completion-group-bg completion-group-fg completion-highlight-bg completion-highlight-fg continuous-hist-save database dbus-raise-window dbus-service default-bg default-fg double-click-follow exec-command filemonitor first-page-column font guioptions highlight-active-color highlight-color highlight-fg highlight-transparency incremental-search index-active-bg index-active-fg index-bg index-fg inputbar-bg inputbar-fg link-hadjust link-zoom n-completion-items notification-bg notification-error-bg notification-error-fg notification-fg notification-warning-bg notification-warning-fg page-cache-size page-padding page-right-to-left page-thumbnail-size pages-per-row recolor recolor-darkcolor recolor-keephue recolor-lightcolor recolor-reverse-video render-loading render-loading-bg render-loading-fg sandbox scroll-full-overlap scroll-hstep scroll-page-aware scroll-step scroll-wrap search-hadjust selection-clipboard selection-notification show-directories show-hidden show-recent statusbar-basename statusbar-bg statusbar-fg statusbar-h-padding statusbar-home-tilde statusbar-page-percent statusbar-v-padding synctex synctex-editor-command vertical-center window-height window-icon window-icon-document window-title-basename window-title-home-tilde window-title-page window-width zoom-center zoom-max zoom-min zoom-step +syntax keyword zathurarcOption abort-clear-search adjust-open advance-pages-per-row +syntax keyword zathurarcOption completion-bg completion-fg completion-group-bg +syntax keyword zathurarcOption completion-group-fg completion-highlight-bg +syntax keyword zathurarcOption completion-highlight-fg continuous-hist-save database +syntax keyword zathurarcOption dbus-raise-window dbus-service default-bg default-fg +syntax keyword zathurarcOption double-click-follow exec-command filemonitor +syntax keyword zathurarcOption first-page-column font guioptions highlight-active-color +syntax keyword zathurarcOption highlight-color highlight-fg highlight-transparency +syntax keyword zathurarcOption incremental-search index-active-bg index-active-fg index-bg +syntax keyword zathurarcOption index-fg inputbar-bg inputbar-fg link-hadjust link-zoom +syntax keyword zathurarcOption n-completion-items notification-bg notification-error-bg +syntax keyword zathurarcOption notification-error-fg notification-fg +syntax keyword zathurarcOption notification-warning-bg notification-warning-fg +syntax keyword zathurarcOption page-cache-size page-h-padding page-v-padding +syntax keyword zathurarcOption page-right-to-left page-thumbnail-size pages-per-row recolor +syntax keyword zathurarcOption recolor-darkcolor recolor-keephue recolor-lightcolor +syntax keyword zathurarcOption recolor-reverse-video render-loading render-loading-bg +syntax keyword zathurarcOption render-loading-fg sandbox scroll-full-overlap scroll-hstep +syntax keyword zathurarcOption scroll-page-aware scroll-step scroll-wrap search-hadjust +syntax keyword zathurarcOption selection-clipboard selection-notification show-directories +syntax keyword zathurarcOption show-hidden show-recent statusbar-basename statusbar-bg +syntax keyword zathurarcOption statusbar-fg statusbar-h-padding statusbar-home-tilde +syntax keyword zathurarcOption statusbar-page-percent statusbar-v-padding synctex +syntax keyword zathurarcOption synctex-editor-command vertical-center window-height +syntax keyword zathurarcOption window-icon window-icon-document window-title-basename +syntax keyword zathurarcOption window-title-home-tilde window-title-page window-width +syntax keyword zathurarcOption zoom-center zoom-max zoom-min zoom-step highlight default link zathurarcComment Comment highlight default link zathurarcNumber Number diff --git a/src/alloc.c b/src/alloc.c index 0fa59ad6d6..463a7104e3 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -746,6 +746,8 @@ ga_grow_inner(garray_T *gap, int n) if (n < gap->ga_len / 2) n = gap->ga_len / 2; + if (n > 0 && (size_t)(gap->ga_len + n) > SIZE_MAX / gap->ga_itemsize) + return FAIL; new_len = (size_t)gap->ga_itemsize * (gap->ga_len + n); pp = vim_realloc(gap->ga_data, new_len); if (pp == NULL) diff --git a/src/channel.c b/src/channel.c index 8196239f2c..64c6ee19b3 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1532,6 +1532,12 @@ channel_listen( int val = 1; channel_T *channel; + if (hostname == NULL || *hostname == NUL) + { + ch_error(NULL, "Hostname/address not defined."); + return NULL; + } + #ifdef MSWIN channel_init_winsock(); #endif @@ -1548,47 +1554,42 @@ channel_listen( vim_memset((char *)&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(port_in); - if (hostname != NULL && *hostname != NUL) - { + #ifdef FEAT_IPV6 - struct addrinfo hints; - struct addrinfo *res = NULL; - int err; + struct addrinfo hints; + struct addrinfo *res = NULL; + int err; - CLEAR_FIELD(hints); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0) - { - ch_error(channel, "in getaddrinfo() in channel_listen()"); - PERROR(_(e_gethostbyname_in_channel_listen)); - channel_free(channel); - return NULL; - } - memcpy(&server.sin_addr, - &((struct sockaddr_in *)res->ai_addr)->sin_addr, - sizeof(server.sin_addr)); - freeaddrinfo(res); -#else - if ((host = gethostbyname(hostname)) == NULL) - { - ch_error(channel, "in gethostbyname() in channel_listen()"); - PERROR(_(e_gethostbyname_in_channel_listen)); - channel_free(channel); - return NULL; - } - { - char *p; - - // When using host->h_addr_list[0] directly ubsan warns for it to - // not be aligned. First copy the pointer to avoid that. - memcpy(&p, &host->h_addr_list[0], sizeof(p)); - memcpy((char *)&server.sin_addr, p, host->h_length); - } -#endif + CLEAR_FIELD(hints); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0) + { + ch_error(channel, "in getaddrinfo() in channel_listen()"); + PERROR(_(e_gethostbyname_in_channel_listen)); + channel_free(channel); + return NULL; } - else - server.sin_addr.s_addr = htonl(INADDR_ANY); + memcpy(&server.sin_addr, + &((struct sockaddr_in *)res->ai_addr)->sin_addr, + sizeof(server.sin_addr)); + freeaddrinfo(res); +#else + if ((host = gethostbyname(hostname)) == NULL) + { + ch_error(channel, "in gethostbyname() in channel_listen()"); + PERROR(_(e_gethostbyname_in_channel_listen)); + channel_free(channel); + return NULL; + } + + char *p; + + // When using host->h_addr_list[0] directly ubsan warns for it to + // not be aligned. First copy the pointer to avoid that. + memcpy(&p, &host->h_addr_list[0], sizeof(p)); + memcpy((char *)&server.sin_addr, p, host->h_length); +#endif sd = socket(AF_INET, SOCK_STREAM, 0); if (sd == -1) @@ -1650,7 +1651,7 @@ channel_listen( channel->ch_listen = TRUE; channel->CH_SOCK_FD = (sock_T)sd; channel->ch_nb_close_cb = nb_close_cb; - channel->ch_hostname = (char *)vim_strsave((char_u *)(hostname != NULL ? hostname : "")); + channel->ch_hostname = (char *)vim_strsave((char_u *)hostname); channel->ch_port = port_in; channel->ch_to_be_closed |= (1U << PART_SOCK); @@ -2315,6 +2316,8 @@ channel_consume(channel_T *channel, ch_part_T part, int len) readq_T *node = head->rq_next; char_u *buf = node->rq_buffer; + if (len < 0 || (long_u)len > node->rq_buflen) + return; mch_memmove(buf, buf + len, node->rq_buflen - len); node->rq_buflen -= len; node->rq_buffer[node->rq_buflen] = NUL; @@ -4325,6 +4328,10 @@ channel_read(channel_T *channel, ch_part_T part, char *func) newchannel->CH_SOCK_FD = (sock_T)newfd; newchannel->ch_to_be_closed |= (1U << PART_SOCK); +#ifdef FEAT_GUI + channel_gui_register_one(newchannel, PART_SOCK); +#endif + if (client.ss_family == AF_INET) { #ifdef HAVE_INET_NTOP diff --git a/src/crypt.c b/src/crypt.c index 794594f910..2fade5db9d 100644 --- a/src/crypt.c +++ b/src/crypt.c @@ -342,7 +342,7 @@ sodium_enabled(int verbose) #endif #define CRYPT_MAGIC_LEN 12 // cannot change -static char crypt_magic_head[] = "VimCrypt~"; +static const char crypt_magic_head[] = "VimCrypt~"; /* * Return int value for crypt method name. diff --git a/src/drawline.c b/src/drawline.c index ac52f98873..87fef7061d 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -1213,13 +1213,19 @@ win_line( int save_did_emsg; #endif #ifdef FEAT_PROP_POPUP +# define WIN_LINE_TEXT_PROP_STACK_LEN 32 int did_line = FALSE; // set to TRUE when line text done int text_prop_count; int last_textprop_text_idx = -1; int text_prop_next = 0; // next text property to use + textprop_T text_props_buf[WIN_LINE_TEXT_PROP_STACK_LEN]; + int text_prop_idxs_buf[WIN_LINE_TEXT_PROP_STACK_LEN]; + char_u text_prop_suffix_flags_buf[WIN_LINE_TEXT_PROP_STACK_LEN + 1]; textprop_T *text_props = NULL; int *text_prop_idxs = NULL; + char_u *text_prop_suffix_flags = NULL; int text_props_active = 0; + int text_props_need_sort = FALSE; proptype_T *text_prop_type = NULL; int text_prop_attr = 0; int text_prop_attr_comb = 0; // text_prop_attr combined with @@ -1418,8 +1424,7 @@ win_line( wlv.fromcol = 0; else { - getvvcol(wp, top, (colnr_T *)&wlv.fromcol, - NULL, NULL, 0); + getvvcol(wp, top, &wlv.fromcol, NULL, NULL, 0); if (gchar_pos(top) == NUL) wlv.tocol = wlv.fromcol + 1; } @@ -1437,12 +1442,10 @@ win_line( { pos = *bot; if (*p_sel == 'e') - getvvcol(wp, &pos, (colnr_T *)&wlv.tocol, - NULL, NULL, 0); + getvvcol(wp, &pos, &wlv.tocol, NULL, NULL, 0); else { - getvvcol(wp, &pos, NULL, NULL, - (colnr_T *)&wlv.tocol, 0); + getvvcol(wp, &pos, NULL, NULL, &wlv.tocol, 0); ++wlv.tocol; } } @@ -1481,14 +1484,14 @@ win_line( { if (lnum == curwin->w_cursor.lnum) getvcol(curwin, &(curwin->w_cursor), - (colnr_T *)&wlv.fromcol, NULL, NULL, 0); + &wlv.fromcol, NULL, NULL, 0); else wlv.fromcol = 0; if (lnum == curwin->w_cursor.lnum + search_match_lines) { pos.lnum = lnum; pos.col = search_match_endcol; - getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL, 0); + getvcol(curwin, &pos, &wlv.tocol, NULL, NULL, 0); } else wlv.tocol = MAXCOL; @@ -1697,15 +1700,40 @@ win_line( { // Make a copy of the properties, so that they are properly // aligned. - text_props = ALLOC_MULT(textprop_T, text_prop_count); + if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN) + text_props = text_props_buf; + else + text_props = ALLOC_MULT(textprop_T, text_prop_count); if (text_props != NULL) mch_memmove(text_props, prop_start, text_prop_count * sizeof(textprop_T)); // Allocate an array for the indexes. - text_prop_idxs = ALLOC_MULT(int, text_prop_count); + if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN) + text_prop_idxs = text_prop_idxs_buf; + else + text_prop_idxs = ALLOC_MULT(int, text_prop_count); if (text_prop_idxs == NULL) - VIM_CLEAR(text_props); + { + if (text_props != text_props_buf) + VIM_CLEAR(text_props); + else + text_props = NULL; + } + if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN) + text_prop_suffix_flags = text_prop_suffix_flags_buf; + else + text_prop_suffix_flags = ALLOC_MULT(char_u, text_prop_count + 1); + if (text_prop_suffix_flags == NULL) + { + if (text_prop_idxs != text_prop_idxs_buf) + vim_free(text_prop_idxs); + text_prop_idxs = NULL; + if (text_props != text_props_buf) + VIM_CLEAR(text_props); + else + text_props = NULL; + } if (text_props != NULL) { @@ -1739,6 +1767,20 @@ win_line( else ++wlv.text_prop_above_count; } + + text_prop_suffix_flags[text_prop_count] = 0; + for (int i = text_prop_count - 1; i >= 0; --i) + { + int flags = text_prop_suffix_flags[i + 1]; + + if (text_props[i].tp_col == MAXCOL) + { + flags |= 1; + if (text_props[i].tp_flags & TP_FLAG_ALIGN_BELOW) + flags |= 2; + } + text_prop_suffix_flags[i] = flags; + } } } @@ -1748,8 +1790,12 @@ win_line( wlv.row += wlv.text_prop_above_count; if (wlv.row >= endrow) { - vim_free(text_props); - vim_free(text_prop_idxs); + if (text_props != text_props_buf) + vim_free(text_props); + if (text_prop_idxs != text_prop_idxs_buf) + vim_free(text_prop_idxs); + if (text_prop_suffix_flags != text_prop_suffix_flags_buf) + vim_free(text_prop_suffix_flags); return wlv.row; } wlv.screen_row += wlv.text_prop_above_count; @@ -2125,6 +2171,7 @@ win_line( sizeof(int) * (text_props_active - (pi + 1))); --text_props_active; + text_props_need_sort = TRUE; --pi; # ifdef FEAT_LINEBREAK // not exactly right but should work in most cases @@ -2167,7 +2214,10 @@ win_line( } if (active) + { text_prop_idxs[text_props_active++] = text_prop_next; + text_props_need_sort = TRUE; + } ++text_prop_next; } @@ -2193,10 +2243,14 @@ win_line( text_prop_above = FALSE; text_prop_follows = FALSE; - // Sort the properties on priority and/or starting last. - // Then combine the attributes, highest priority last. - sort_text_props(wp->w_buffer, text_props, - text_prop_idxs, text_props_active); + if (text_props_need_sort) + { + // The active set only changes when a property starts + // or ends, so avoid sorting again for every column. + sort_text_props(wp->w_buffer, text_props, + text_prop_idxs, text_props_active); + text_props_need_sort = FALSE; + } for (pi = 0; pi < text_props_active; ++pi) { @@ -2405,19 +2459,10 @@ win_line( // Or when not wrapping and at the rightmost column. int only_below_follows = !wp->w_p_wrap && wlv.col == wp->w_width - 1; - // TODO: Store "after"/"right"/"below" text properties in order - // in the buffer so only `text_props[text_prop_count - 1]` - // needs to be checked for following "below" virtual text - for (int i = text_prop_next; i < text_prop_count; ++i) - { - if (text_props[i].tp_col == MAXCOL - && (!only_below_follows - || (text_props[i].tp_flags & TP_FLAG_ALIGN_BELOW))) - { - text_prop_follows = TRUE; - break; - } - } + int suffix_flags = text_prop_suffix_flags[text_prop_next]; + + text_prop_follows = (suffix_flags + & (only_below_follows ? 2 : 1)) != 0; } } @@ -4507,8 +4552,12 @@ win_line( } // for every character in the line #ifdef FEAT_PROP_POPUP - vim_free(text_props); - vim_free(text_prop_idxs); + if (text_props != text_props_buf) + vim_free(text_props); + if (text_prop_idxs != text_prop_idxs_buf) + vim_free(text_prop_idxs); + if (text_prop_suffix_flags != text_prop_suffix_flags_buf) + vim_free(text_prop_suffix_flags); vim_free(p_extra_free2); #endif diff --git a/src/errors.h b/src/errors.h index 71bcb2397c..2c04c3c68c 100644 --- a/src/errors.h +++ b/src/errors.h @@ -3742,7 +3742,7 @@ EXTERN char e_no_quickfix_stack[] EXTERN char e_cannot_switch_to_a_closing_buffer[] INIT(= N_("E1546: Cannot switch to a closing buffer")); EXTERN char e_cannot_not_support_redrawtabpanel[] - INIT(= N_("E1547: This version of Vim does support :redrawtabpanel")); + INIT(= N_("E1547: This version of Vim does not support :redrawtabpanel")); #ifdef FEAT_WAYLAND EXTERN char e_wayland_connection_unavailable[] INIT(= N_("E1548: Wayland connection is unavailable")); diff --git a/src/eval.c b/src/eval.c index e8b9cc8303..6f7c9960a2 100644 --- a/src/eval.c +++ b/src/eval.c @@ -7566,7 +7566,13 @@ handle_subscript( *arg = skipwhite(p + 2); else *arg = p + 2; - if (VIM_ISWHITE(**arg)) + if (ret == OK && evaluate && rettv->v_type == VAR_VOID) + { + if (verbose) + emsg(_(e_cannot_use_void_value)); + ret = FAIL; + } + else if (VIM_ISWHITE(**arg)) { emsg(_(e_no_white_space_allowed_before_parenthesis)); ret = FAIL; diff --git a/src/evalfunc.c b/src/evalfunc.c index 7a05f7a13d..d476191a60 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2181,7 +2181,7 @@ static const funcentry_T global_functions[] = {"environ", 0, 0, 0, NULL, ret_dict_string, f_environ}, {"err_teapot", 0, 1, 0, NULL, - ret_number_bool, f_err_teapot}, + ret_void, f_err_teapot}, {"escape", 2, 2, FEARG_1, arg2_string, ret_string, f_escape}, {"eval", 1, 1, FEARG_1, arg1_string, @@ -2747,7 +2747,7 @@ static const funcentry_T global_functions[] = {"remote_expr", 2, 4, FEARG_1, arg24_remote_expr, ret_string, f_remote_expr}, {"remote_foreground", 1, 1, FEARG_1, arg1_string, - ret_string, f_remote_foreground}, + ret_void, f_remote_foreground}, {"remote_peek", 1, 2, FEARG_1, arg2_string, ret_number, f_remote_peek}, {"remote_read", 1, 2, FEARG_1, arg2_string_number, @@ -3081,7 +3081,7 @@ static const funcentry_T global_functions[] = {"test_ignore_error", 1, 1, FEARG_1, arg1_string, ret_void, f_test_ignore_error}, {"test_mswin_event", 2, 2, FEARG_1, arg2_string_dict, - ret_number, f_test_mswin_event}, + ret_bool, f_test_mswin_event}, {"test_null_blob", 0, 0, 0, NULL, ret_blob, f_test_null_blob}, {"test_null_channel", 0, 0, 0, NULL, @@ -3500,6 +3500,8 @@ call_internal_func( return FCERR_OTHER; argvars[argcount].v_type = VAR_UNKNOWN; global_functions[i].f_func(argvars, rettv); + if (in_vim9script() && global_functions[i].f_retfunc == ret_void) + rettv->v_type = VAR_VOID; return FCERR_NONE; } @@ -3510,6 +3512,8 @@ call_internal_func_by_idx( typval_T *rettv) { global_functions[idx].f_func(argvars, rettv); + if (in_vim9script() && global_functions[idx].f_retfunc == ret_void) + rettv->v_type = VAR_VOID; } /* diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 95a1804124..a8aee02c99 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2740,7 +2740,7 @@ ex_errmsg(char *msg, char_u *arg) * The "+" string used in place of an empty command in Ex mode. * This string is used in pointer comparison. */ -static char exmode_plus[] = "+"; +static const char exmode_plus[] = "+"; /* * Handle a range without a command. diff --git a/src/globals.h b/src/globals.h index 81c0fb1d19..8f7417fea7 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1739,17 +1739,17 @@ EXTERN win_T *cmdwin_win INIT(= NULL); // window of cmdline window or NULL EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--")); EXTERN char typename_unknown[] INIT(= N_("unknown")); -EXTERN char typename_int[] INIT(= N_("int")); -EXTERN char typename_longint[] INIT(= N_("long int")); -EXTERN char typename_longlongint[] INIT(= N_("long long int")); -EXTERN char typename_unsignedint[] INIT(= N_("unsigned int")); -EXTERN char typename_unsignedlongint[] INIT(= N_("unsigned long int")); -EXTERN char typename_unsignedlonglongint[] INIT(= N_("unsigned long long int")); +EXTERN char typename_int[] INIT(= "int"); +EXTERN char typename_longint[] INIT(= "long int"); +EXTERN char typename_longlongint[] INIT(= "long long int"); +EXTERN char typename_unsignedint[] INIT(= "unsigned int"); +EXTERN char typename_unsignedlongint[] INIT(= "unsigned long int"); +EXTERN char typename_unsignedlonglongint[] INIT(= "unsigned long long int"); EXTERN char typename_pointer[] INIT(= N_("pointer")); EXTERN char typename_percent[] INIT(= N_("percent")); -EXTERN char typename_char[] INIT(= N_("char")); +EXTERN char typename_char[] INIT(= "char"); EXTERN char typename_string[] INIT(= N_("string")); -EXTERN char typename_float[] INIT(= N_("float")); +EXTERN char typename_float[] INIT(= "float"); /* * When ":global" is used to number of substitutions and changed lines is diff --git a/src/hardcopy.c b/src/hardcopy.c index 5333116049..55d4384182 100644 --- a/src/hardcopy.c +++ b/src/hardcopy.c @@ -1394,7 +1394,7 @@ static int prt_use_courier; static int prt_in_ascii; static int prt_half_width; static char *prt_ascii_encoding; -static char_u prt_hexchar[] = "0123456789abcdef"; +static const char_u prt_hexchar[] = "0123456789abcdef"; static void prt_write_file_raw_len(char_u *buffer, int bytes) diff --git a/src/insexpand.c b/src/insexpand.c index c1be0d98c0..b1cc29b7e5 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -4542,6 +4542,8 @@ fuzzy_longest_match(void) return; } + if ((size_t)compl_num_bests > SIZE_MAX / sizeof(compl_T *)) + return; compl_best_matches = (compl_T **)alloc(compl_num_bests * sizeof(compl_T *)); if (compl_best_matches == NULL) return; diff --git a/src/libvterm/src/parser.c b/src/libvterm/src/parser.c index e167e0cb1a..2ca422f4a2 100644 --- a/src/libvterm/src/parser.c +++ b/src/libvterm/src/parser.c @@ -230,12 +230,16 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) case CSI_ARGS: /* Numerical value of argument */ if(c >= '0' && c <= '9') { - if(vt->parser.v.csi.args[vt->parser.v.csi.argi] == CSI_ARG_MISSING) - vt->parser.v.csi.args[vt->parser.v.csi.argi] = 0; - if(vt->parser.v.csi.args[vt->parser.v.csi.argi] < (CSI_ARG_MISSING - 9) / 10) { - vt->parser.v.csi.args[vt->parser.v.csi.argi] *= 10; - vt->parser.v.csi.args[vt->parser.v.csi.argi] += c - '0'; - } + long arg_max = CSI_ARG_MISSING - 1; + long *arg = &vt->parser.v.csi.args[vt->parser.v.csi.argi]; + int digit = c - '0'; + + if(*arg == CSI_ARG_MISSING) + *arg = 0; + if(*arg > (arg_max - digit) / 10) + *arg = arg_max; + else + *arg = *arg * 10 + digit; break; } if(c == ':') { diff --git a/src/libvterm/src/vterm.c b/src/libvterm/src/vterm.c index dba6377186..a5f5ce3f8a 100644 --- a/src/libvterm/src/vterm.c +++ b/src/libvterm/src/vterm.c @@ -181,18 +181,17 @@ INTERNAL void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len) INTERNAL void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args) { size_t len; -#ifndef VSNPRINTF - // When vsnprintf() is not available (C90) fall back to vsprintf(). - char buffer[1024]; // 1Kbyte is enough for everybody, right? -#endif - #ifdef VSNPRINTF len = VSNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len, format, args); - vterm_push_output_bytes(vt, vt->tmpbuffer, len); #else - len = vsprintf(buffer, format, args); - vterm_push_output_bytes(vt, buffer, len); + // When vsnprintf() is not available (C90) fall back to vsprintf(). + // Use the heap-allocated tmpbuffer (default 4096 bytes) instead of a small + // stack buffer to reduce the risk of overflow. + len = vsprintf(vt->tmpbuffer, format, args); + if (len >= vt->tmpbuffer_len) + len = vt->tmpbuffer_len - 1; #endif + vterm_push_output_bytes(vt, vt->tmpbuffer, len); } INTERNAL void vterm_push_output_sprintf(VTerm *vt, const char *format, ...) diff --git a/src/list.c b/src/list.c index cd12bcb0a0..c9e9d686bd 100644 --- a/src/list.c +++ b/src/list.c @@ -118,6 +118,9 @@ list_alloc_with_items(int count) { list_T *l; + if (count > 0 + && (size_t)count > (SIZE_MAX - sizeof(list_T)) / sizeof(listitem_T)) + return NULL; l = (list_T *)alloc_clear(sizeof(list_T) + count * sizeof(listitem_T)); if (l == NULL) return NULL; diff --git a/src/memline.c b/src/memline.c index 35b1fae230..886f08f973 100644 --- a/src/memline.c +++ b/src/memline.c @@ -69,7 +69,7 @@ typedef struct pointer_entry PTR_EN; // block/line-count pair #define BLOCK0_ID1_C4 's' // block 0 id 1 'cm' 4 #if defined(FEAT_CRYPT) -static int id1_codes[] = { +static const int id1_codes[] = { BLOCK0_ID1_C0, // CRYPT_M_ZIP BLOCK0_ID1_C1, // CRYPT_M_BF BLOCK0_ID1_C2, // CRYPT_M_BF2 diff --git a/src/normal.c b/src/normal.c index 6fbd1e6c2f..06209fe696 100644 --- a/src/normal.c +++ b/src/normal.c @@ -1652,7 +1652,7 @@ clear_showcmd(void) curwin->w_p_sbr = empty_option; #endif getvcols(curwin, &curwin->w_cursor, &VIsual, - &leftcol, &rightcol, 0); + &leftcol, &rightcol, GETVCOL_END_EXCL_LBR); #ifdef FEAT_LINEBREAK p_sbr = saved_sbr; curwin->w_p_sbr = saved_w_sbr; diff --git a/src/ops.c b/src/ops.c index 140cdc8c58..6ea50c912e 100644 --- a/src/ops.c +++ b/src/ops.c @@ -2620,7 +2620,7 @@ charwise_block_prep( startcol = start.col; if (virtual_op) { - getvcol(curwin, &start, &cs, NULL, &ce, false); + getvcol(curwin, &start, &cs, NULL, &ce, 0); if (ce != cs && start.coladd > 0) { // Part of a tab selected -- but don't @@ -2639,7 +2639,7 @@ charwise_block_prep( endcol = end.col; if (virtual_op) { - getvcol(curwin, &end, &cs, NULL, &ce, false); + getvcol(curwin, &end, &cs, NULL, &ce, 0); if (p[endcol] == NUL || (cs + end.coladd < ce // Don't add space for double-wide // char; endcol will be on last byte diff --git a/src/po/de.po b/src/po/de.po index 74e8caeded..a446ba4004 100644 --- a/src/po/de.po +++ b/src/po/de.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 12:15+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2008-05-24 17:26+0200\n" "Last-Translator: Christian Brabandt \n" "Language-Team: German\n" @@ -9427,39 +9427,15 @@ msgstr "E1571: Es muss mindestens ein Callback f msgid "--No lines in buffer--" msgstr "--Keine Zeilen im Buffer--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "Prozent" -msgid "char" -msgstr "char" - msgid "string" msgstr "Zeichenkette" -msgid "float" -msgstr "Float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "Suche erreichte den ANFANG und wurde am ENDE fortgesetzt" diff --git a/src/po/ga.po b/src/po/ga.po index cd1a02970b..73df92c778 100644 --- a/src/po/ga.po +++ b/src/po/ga.po @@ -8923,39 +8923,15 @@ msgstr "E1510: Luach r msgid "--No lines in buffer--" msgstr "--T an maoln folamh--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointeoir" msgid "percent" msgstr "catadn" -msgid "char" -msgstr "char" - msgid "string" msgstr "teaghrn" -msgid "float" -msgstr "snmhphointe" - msgid "search hit TOP, continuing at BOTTOM" msgstr "Buaileadh an BARR le linn an chuardaigh, ag leanint ag an mBUN" diff --git a/src/po/hy.po b/src/po/hy.po index 4392a5650f..88906f76cf 100644 --- a/src/po/hy.po +++ b/src/po/hy.po @@ -70,7 +70,7 @@ msgid "" msgstr "" "Project-Id-Version: vim_9.1_am\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2025-12-20 20:54+0400\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2025-12-21 15:32+0400\n" "Last-Translator: Gagik Hakobyan \n" "Language-Team: Armenian\n" @@ -9296,39 +9296,15 @@ msgstr "E1571: redraud_listener_add-ը պահանջում է առնվազն մե msgid "--No lines in buffer--" msgstr "-- Բուֆերում տողեր չկան --" -msgid "int" -msgstr "ամբողջ" - -msgid "long int" -msgstr "երկար ինտ" - -msgid "long long int" -msgstr "երկար երկար ինտ" - -msgid "unsigned int" -msgstr "անստորագիր միջ" - -msgid "unsigned long int" -msgstr "անստորագիր երկար միջ" - -msgid "unsigned long long int" -msgstr "անստորագիր long long int" - msgid "pointer" msgstr "ցուցիչ" msgid "percent" msgstr "տոկոս" -msgid "char" -msgstr "տառ" - msgid "string" msgstr "տող" -msgid "float" -msgstr "սահող կետով թվանշան" - msgid "search hit TOP, continuing at BOTTOM" msgstr "փնտրումն ավարտվել է, որոնումն սկսվելու է վերջից" diff --git a/src/po/it.po b/src/po/it.po index dd00bb892f..217e85eb37 100644 --- a/src/po/it.po +++ b/src/po/it.po @@ -9328,39 +9328,15 @@ msgstr "E1575: Non posso create delle pipe" msgid "--No lines in buffer--" msgstr "--File vuoto--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "puntatore" msgid "percent" msgstr "percento" -msgid "char" -msgstr "carattere" - msgid "string" msgstr "stringa" -msgid "float" -msgstr "numero a virgola mobile" - #. #. * Some messages that can be shared are included here. #. diff --git a/src/po/ja.euc-jp.po b/src/po/ja.euc-jp.po index 33302f82e0..27c00ae1ea 100644 --- a/src/po/ja.euc-jp.po +++ b/src/po/ja.euc-jp.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim 9.2\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 14:41+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-01-19 23:15+0900\n" "Last-Translator: MURAOKA Taro \n" "Language-Team: Japanese \n" @@ -9115,39 +9115,15 @@ msgstr "" msgid "--No lines in buffer--" msgstr "--Хåե˹Ԥޤ--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "ޤǸΤDzޤ" diff --git a/src/po/ja.po b/src/po/ja.po index 65f7c708e5..c883a01fbb 100644 --- a/src/po/ja.po +++ b/src/po/ja.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim 9.2\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 14:41+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-01-19 23:15+0900\n" "Last-Translator: MURAOKA Taro \n" "Language-Team: Japanese \n" @@ -9123,39 +9123,15 @@ msgstr "" msgid "--No lines in buffer--" msgstr "--バッファに行がありません--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "上まで検索したので下に戻ります" diff --git a/src/po/ja.sjis.po b/src/po/ja.sjis.po index 0a11d2b0fb..c4091d49c7 100644 --- a/src/po/ja.sjis.po +++ b/src/po/ja.sjis.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim 9.2\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 14:41+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-01-19 23:15+0900\n" "Last-Translator: MURAOKA Taro \n" "Language-Team: Japanese \n" @@ -9115,39 +9115,15 @@ msgstr "" msgid "--No lines in buffer--" msgstr "--obt@ɍs܂--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "܂Ō̂ʼnɖ߂܂" diff --git a/src/po/sr.po b/src/po/sr.po index 790ed37435..c8c1537898 100644 --- a/src/po/sr.po +++ b/src/po/sr.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Serbian)\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-02-19 17:55+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-02-20 09:34+0400\n" "Last-Translator: Ivan Pešić \n" "Language-Team: Serbian\n" @@ -9196,39 +9196,15 @@ msgstr "" msgid "--No lines in buffer--" msgstr "--У баферу нема линија--" -msgid "int" -msgstr "целобројни" - -msgid "long int" -msgstr "дуги целобројни" - -msgid "long long int" -msgstr "дуги дуги целобројни" - -msgid "unsigned int" -msgstr "неозначени целобројни" - -msgid "unsigned long int" -msgstr "неозначени дуги целобројни" - -msgid "unsigned long long int" -msgstr "неозначени дуги дуги целобројни" - msgid "pointer" msgstr "показивач" msgid "percent" msgstr "проценат" -msgid "char" -msgstr "карактер" - msgid "string" msgstr "стринг" -msgid "float" -msgstr "покретни" - msgid "search hit TOP, continuing at BOTTOM" msgstr "претрага је достигла ВРХ, наставља се од ДНА" diff --git a/src/po/sv.po b/src/po/sv.po index f61704c7ed..11d00564fd 100644 --- a/src/po/sv.po +++ b/src/po/sv.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim 9.1\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 14:41+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-01-11 14:27+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -9294,39 +9294,15 @@ msgstr "E1571: Måste ange minst ett återanrop för redraw_listener_add" msgid "--No lines in buffer--" msgstr "--Inga rader i buffert--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "osignerad int" - -msgid "unsigned long int" -msgstr "osignerad long int" - -msgid "unsigned long long int" -msgstr "osignerad long long int" - msgid "pointer" msgstr "pekare" msgid "percent" msgstr "procent" -msgid "char" -msgstr "tecken" - msgid "string" msgstr "sträng" -msgid "float" -msgstr "float" - #. #. * Some messages that can be shared are included here. #. diff --git a/src/po/ta.po b/src/po/ta.po index ff5a4e62eb..606779f1bf 100644 --- a/src/po/ta.po +++ b/src/po/ta.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim 9.2\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 14:41+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-02-16 22:09+0530\n" "Last-Translator: தமிழ்நேரம் \n" "Language-Team: தமிழ்நேரம் \n" @@ -9024,39 +9024,15 @@ msgstr "E1571: redraw_listener_add க்கு குறைந்தது ஒ msgid "--No lines in buffer--" msgstr "--பஃபரில் கோடுகள் இல்லை--" -msgid "int" -msgstr "முழு எண்ணாக" - -msgid "long int" -msgstr "நீண்ட எண்ணாக" - -msgid "long long int" -msgstr "நீண்ட நீண்ட எண்ணாக" - -msgid "unsigned int" -msgstr "கையொப்பமிடப்படாத முழு எண்ணாக" - -msgid "unsigned long int" -msgstr "கையொப்பமிடப்படாத நீண்ட எண்ணாக" - -msgid "unsigned long long int" -msgstr "கையொப்பமிடப்படாத நீண்ட நீண்ட எண்ணாக" - msgid "pointer" msgstr "சுட்டி" msgid "percent" msgstr "விழுக்காடு" -msgid "char" -msgstr "கரி" - msgid "string" msgstr "சரம்" -msgid "float" -msgstr "மிதவை" - #. #. * Some messages that can be shared are included here. #. diff --git a/src/po/tr.po b/src/po/tr.po index a26128c073..65d7d03688 100644 --- a/src/po/tr.po +++ b/src/po/tr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim Turkish Localization Project\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-06 14:41+0000\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2026-02-04 20:00+0300\n" "Last-Translator: Emir SARI \n" "Language-Team: Turkish \n" @@ -9134,39 +9134,15 @@ msgstr "E1571: redraw_listener_add için en az bir geri çağrı belirtilmelidir msgid "--No lines in buffer--" msgstr "--Arabellek içinde satır yok--" -msgid "int" -msgstr "tamsayı" - -msgid "long int" -msgstr "uzun tamsayı" - -msgid "long long int" -msgstr "uzun uzun tamsayı" - -msgid "unsigned int" -msgstr "imzalanmamış tamsayı" - -msgid "unsigned long int" -msgstr "imzalanmamış uzun tamsayı" - -msgid "unsigned long long int" -msgstr "imzalanmamış uzun uzun tamsayı" - msgid "pointer" msgstr "işaretçi" msgid "percent" msgstr "yüzde" -msgid "char" -msgstr "karakter" - msgid "string" msgstr "dizi" -msgid "float" -msgstr "kayan noktalı değer" - msgid "search hit TOP, continuing at BOTTOM" msgstr "Arama dosyanın BAŞINI geçti, dosyanın SONUNDAN sürüyor" diff --git a/src/po/uk.cp1251.po b/src/po/uk.cp1251.po index 58796f2ba3..a156093623 100644 --- a/src/po/uk.cp1251.po +++ b/src/po/uk.cp1251.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim Ukrainian\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-05 17:56+0200\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2023-12-24 17:01+0200\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" @@ -9448,39 +9448,15 @@ msgstr "E1571: msgid "--No lines in buffer--" msgstr "-- --" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr " , ʲ" diff --git a/src/po/uk.po b/src/po/uk.po index a1922193c6..fcfea1c830 100644 --- a/src/po/uk.po +++ b/src/po/uk.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim Ukrainian\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-01-05 17:56+0200\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2023-12-24 17:01+0200\n" "Last-Translator: Анатолій Сахнік \n" "Language-Team: Ukrainian\n" @@ -9448,39 +9448,15 @@ msgstr "E1571: Потрібно задати принаймні однин зв msgid "--No lines in buffer--" msgstr "--Жодного рядка--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "Пошук дійшов до ПОЧАТКУ, продовжується з КІНЦЯ" diff --git a/src/po/vim.pot b/src/po/vim.pot index 029a19449e..e57893d24d 100644 --- a/src/po/vim.pot +++ b/src/po/vim.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-03-25 21:51+0000\n" +"POT-Creation-Date: 2026-04-06 13:30+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -8756,7 +8756,7 @@ msgstr "" msgid "E1546: Cannot switch to a closing buffer" msgstr "" -msgid "E1547: This version of Vim does support :redrawtabpanel" +msgid "E1547: This version of Vim does not support :redrawtabpanel" msgstr "" msgid "E1548: Wayland connection is unavailable" @@ -8863,39 +8863,15 @@ msgstr "" msgid "--No lines in buffer--" msgstr "" -msgid "int" -msgstr "" - -msgid "long int" -msgstr "" - -msgid "long long int" -msgstr "" - -msgid "unsigned int" -msgstr "" - -msgid "unsigned long int" -msgstr "" - -msgid "unsigned long long int" -msgstr "" - msgid "pointer" msgstr "" msgid "percent" msgstr "" -msgid "char" -msgstr "" - msgid "string" msgstr "" -msgid "float" -msgstr "" - #. #. * Some messages that can be shared are included here. #. diff --git a/src/po/zh_CN.UTF-8.po b/src/po/zh_CN.UTF-8.po index 0fe7873c89..c00911a2c9 100644 --- a/src/po/zh_CN.UTF-8.po +++ b/src/po/zh_CN.UTF-8.po @@ -18,7 +18,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Simplified Chinese)\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-03-20 20:44+0800\n" +"POT-Creation-Date: 2026-04-05 23:26+0800\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2025-12-28 14:27+0800\n" "Last-Translator: Mao-Yining\n" "Language-Team: Simplified Chinese\n" @@ -55,7 +56,7 @@ msgid "auto-removing autocommand: %s " msgstr "自动删除自动命令: %s " msgid "W19: Deleting augroup that is still in use" -msgstr "W19: 删除依旧在使用中的自动组" +msgstr "W19: 删除仍在使用中的自动命令组" msgid "" "\n" @@ -600,11 +601,11 @@ msgstr "警告: 意外地进入了其它缓冲区 (请检查自动命令)" #, c-format msgid "W20: Required python version 2.x not supported, ignoring file: %s" -msgstr "W20: 不支持需要的 Python 2.x 版本,忽略文件:%s" +msgstr "W20: 所需的 Python 2.x 版本不受支持,忽略文件:%s" #, c-format msgid "W21: Required python version 3.x not supported, ignoring file: %s" -msgstr "W21: 不支持需要的 Python 3.x 版本,忽略文件:%s" +msgstr "W21: 所需的 Python 3.x 版本不受支持,忽略文件:%s" msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "进入 Ex 模式。输入 \"visual\" 回到正常模式。" @@ -743,7 +744,7 @@ msgid "[character special]" msgstr "[字符设备]" msgid "[CR missing]" -msgstr "[缺少 CR]'" +msgstr "[缺少 CR]" msgid "[long lines split]" msgstr "[长行分割]" @@ -824,7 +825,7 @@ msgstr "请参阅 \":help W11\" 以获取更多信息。" #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" -msgstr "W16: 警告: 编辑开始后,文件 \"%s\" 的模式已变动" +msgstr "W16: 警告: 编辑开始后,文件 \"%s\" 的权限模式已变动" msgid "See \":help W16\" for more info." msgstr "请参阅 \":help W16\" 以获取更多信息。" @@ -1137,7 +1138,7 @@ msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection setpgid 失败" msgid "cs_create_connection exec failed" -msgstr "cs_create_connection 执行失败" +msgstr "cs_create_connection exec 失败" msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: fdopen to_fp 失败" @@ -2347,6 +2348,10 @@ msgstr " (已中断)" msgid "Beep!" msgstr "Beep!" +#, c-format +msgid "Executing directly: \"%s\"" +msgstr "直接执行:%s" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "调用 shell 执行: \"%s\"" @@ -3279,7 +3284,7 @@ msgstr "查找 tag 文件 %s" #, c-format msgid "Duplicate field name: %s" -msgstr "重复的字段名:%s" +msgstr "重复的字段名称:%s" msgid "' not known. Available builtin terminals are:" msgstr "' 未知。可用的内建终端有:" @@ -4333,7 +4338,7 @@ msgstr "E127: 函数 %s 正在使用中,不能重新定义" #, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: 函数名必须以大写字母或 \"s:\" 开头: %s" +msgstr "E128: 函数名必须以大写字母或 \"s:\" 开头:%s" msgid "E129: Function name required" msgstr "E129: 需要函数名" @@ -4359,7 +4364,7 @@ msgstr "E136: viminfo: 错误过多,忽略文件的剩余部分" #, c-format msgid "E137: Viminfo file is not writable: %s" -msgstr "E137: Viminfo 文件不可写入: %s" +msgstr "E137: Viminfo 文件不可写入:%s" #, c-format msgid "E138: Can't write viminfo file %s!" @@ -5265,7 +5270,7 @@ msgid "E418: Illegal value: %s" msgstr "E418: 不合法的值: %s" msgid "E418: I'm a teapot" -msgstr "E418: 我是茶壶,不煮咖啡(彩蛋)" +msgstr "E418: 我是茶壶" msgid "E419: FG color unknown" msgstr "E419: 错误的前景颜色" @@ -5572,7 +5577,7 @@ msgid "E503: \"%s\" is not a file or writable device" msgstr "E503: \"%s\" 不是文件或可写的设备" msgid "E503: Coffee is currently not available" -msgstr "E503: 当前无法提供咖啡(彩蛋)" +msgstr "E503: 咖啡当前不可用" msgid "is read-only (cannot override: \"W\" in 'cpoptions')" msgstr "只读 (不能强制执行:'cpoptions' 中包含 \"W\")" @@ -6055,7 +6060,7 @@ msgid "E655: Too many symbolic links (cycle?)" msgstr "E655: 符号连接过多(循环?)" msgid "NetBeans disallows writes of unmodified buffers" -msgstr "NetBeans 不允许未修改的缓冲区写入" +msgstr "NetBeans 不允许写入未修改的缓冲区" msgid "Partial writes disallowed for NetBeans buffers" msgstr "NetBeans 不允许缓冲区部分写入" @@ -8928,8 +8933,8 @@ msgstr "E1545: Quickfix 列表栈不可用" msgid "E1546: Cannot switch to a closing buffer" msgstr "E1546: 不能切换到正在关闭的缓冲区" -msgid "E1547: This version of Vim does support :redrawtabpanel" -msgstr "E1547: 此版本的 Vim 支持 :redrawtabpanel" +msgid "E1547: This version of Vim does not support :redrawtabpanel" +msgstr "E1547: 此版本的 Vim 不支持 :redrawtabpanel" msgid "E1548: Wayland connection is unavailable" msgstr "E1548: Wayland 连接不可用" @@ -9025,42 +9030,21 @@ msgstr "E1573: 无法监听端口" msgid "E1574: gethostbyname(): cannot resolve hostname in channel_listen()" msgstr "E1574: gethostbyname():无法在 channel_listen() 中解析主机名" +msgid "E1575: Cannot create pipes" +msgstr "E1575: 无法建立管道" + msgid "--No lines in buffer--" msgstr "--缓冲区无内容--" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "已查找到文件开头,再从结尾继续查找" @@ -9328,7 +9312,7 @@ msgid "" "You should now append vim.VIM_SPECIAL_PATH to sys.path" msgstr "" "路径设置失败:sys.path 不是列表\n" -"你应该现在添加 vim.VIM_SPECIAL_PATH 到 sys.path" +"你现在应该添加 vim.VIM_SPECIAL_PATH 到 sys.path" msgid "" "Vim macro files (*.vim)\t*.vim\n" diff --git a/src/po/zh_CN.cp936.po b/src/po/zh_CN.cp936.po index d6f1b870c9..9103cde8cc 100644 --- a/src/po/zh_CN.cp936.po +++ b/src/po/zh_CN.cp936.po @@ -18,7 +18,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Simplified Chinese)\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-03-20 20:44+0800\n" +"POT-Creation-Date: 2026-04-05 23:26+0800\n" +"POT-Creation-Date: 2026-03-30 11:05+0900\n" "PO-Revision-Date: 2025-12-28 14:27+0800\n" "Last-Translator: Mao-Yining\n" "Language-Team: Simplified Chinese\n" @@ -55,7 +56,7 @@ msgid "auto-removing autocommand: %s " msgstr "ԶɾԶ %s " msgid "W19: Deleting augroup that is still in use" -msgstr "W19: ɾʹеԶ" +msgstr "W19: ɾʹеԶ" msgid "" "\n" @@ -600,11 +601,11 @@ msgstr " #, c-format msgid "W20: Required python version 2.x not supported, ignoring file: %s" -msgstr "W20: ֧Ҫ Python 2.x 汾ļ%s" +msgstr "W20: Python 2.x 汾֧֣ļ%s" #, c-format msgid "W21: Required python version 3.x not supported, ignoring file: %s" -msgstr "W21: ֧Ҫ Python 3.x 汾ļ%s" +msgstr "W21: Python 3.x 汾֧֣ļ%s" msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr " Ex ģʽ \"visual\" صģʽ" @@ -743,7 +744,7 @@ msgid "[character special]" msgstr "[ַ豸]" msgid "[CR missing]" -msgstr "[ȱ CR]'" +msgstr "[ȱ CR]" msgid "[long lines split]" msgstr "[зָ]" @@ -824,7 +825,7 @@ msgstr " #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" -msgstr "W16: : ༭ʼļ \"%s\" ģʽѱ䶯" +msgstr "W16: : ༭ʼļ \"%s\" Ȩģʽѱ䶯" msgid "See \":help W16\" for more info." msgstr " \":help W16\" ԻȡϢ" @@ -1137,7 +1138,7 @@ msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection setpgid ʧ" msgid "cs_create_connection exec failed" -msgstr "cs_create_connection ִʧ" +msgstr "cs_create_connection exec ʧ" msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: fdopen to_fp ʧ" @@ -2347,6 +2348,10 @@ msgstr " ( msgid "Beep!" msgstr "Beep!" +#, c-format +msgid "Executing directly: \"%s\"" +msgstr "ֱִУ%s" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr " shell ִ: \"%s\"" @@ -3279,7 +3284,7 @@ msgstr " #, c-format msgid "Duplicate field name: %s" -msgstr "ظֶ%s" +msgstr "ظֶƣ%s" msgid "' not known. Available builtin terminals are:" msgstr "' δ֪õڽն:" @@ -4325,7 +4330,7 @@ msgstr "E127: #, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: Դдĸ \"s:\" ͷ: %s" +msgstr "E128: Դдĸ \"s:\" ͷ%s" msgid "E129: Function name required" msgstr "E129: Ҫ" @@ -4351,7 +4356,7 @@ msgstr "E136: viminfo: #, c-format msgid "E137: Viminfo file is not writable: %s" -msgstr "E137: Viminfo ļд: %s" +msgstr "E137: Viminfo ļд룺%s" #, c-format msgid "E138: Can't write viminfo file %s!" @@ -5257,7 +5262,7 @@ msgid "E418: Illegal value: %s" msgstr "E418: Ϸֵ: %s" msgid "E418: I'm a teapot" -msgstr "E418: Dz󿧷ȣʵ" +msgstr "E418: Dz" msgid "E419: FG color unknown" msgstr "E419: ǰɫ" @@ -5564,7 +5569,7 @@ msgid "E503: \"%s\" is not a file or writable device" msgstr "E503: \"%s\" ļд豸" msgid "E503: Coffee is currently not available" -msgstr "E503: ǰ޷ṩȣʵ" +msgstr "E503: ȵǰ" msgid "is read-only (cannot override: \"W\" in 'cpoptions')" msgstr "ֻ (ǿִУ'cpoptions' а \"W\")" @@ -6047,7 +6052,7 @@ msgid "E655: Too many symbolic links (cycle?)" msgstr "E655: ӹ(ѭ)" msgid "NetBeans disallows writes of unmodified buffers" -msgstr "NetBeans δ޸ĵĻд" +msgstr "NetBeans дδ޸ĵĻ" msgid "Partial writes disallowed for NetBeans buffers" msgstr "NetBeans д" @@ -8920,8 +8925,8 @@ msgstr "E1545: Quickfix msgid "E1546: Cannot switch to a closing buffer" msgstr "E1546: лڹرյĻ" -msgid "E1547: This version of Vim does support :redrawtabpanel" -msgstr "E1547: ˰汾 Vim ֧ :redrawtabpanel" +msgid "E1547: This version of Vim does not support :redrawtabpanel" +msgstr "E1547: ˰汾 Vim ֧ :redrawtabpanel" msgid "E1548: Wayland connection is unavailable" msgstr "E1548: Wayland Ӳ" @@ -9017,42 +9022,21 @@ msgstr "E1573: msgid "E1574: gethostbyname(): cannot resolve hostname in channel_listen()" msgstr "E1574: gethostbyname()޷ channel_listen() н" +msgid "E1575: Cannot create pipes" +msgstr "E1575: ޷ܵ" + msgid "--No lines in buffer--" msgstr "----" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "Ѳҵļͷٴӽβ" @@ -9320,7 +9304,7 @@ msgid "" "You should now append vim.VIM_SPECIAL_PATH to sys.path" msgstr "" "·ʧܣsys.path б\n" -"Ӧ vim.VIM_SPECIAL_PATH sys.path" +"Ӧ vim.VIM_SPECIAL_PATH sys.path" msgid "" "Vim macro files (*.vim)\t*.vim\n" diff --git a/src/po/zh_CN.po b/src/po/zh_CN.po index 7f4aa908a4..87c60a4d96 100644 --- a/src/po/zh_CN.po +++ b/src/po/zh_CN.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Simplified Chinese)\n" "Report-Msgid-Bugs-To: vim-dev@vim.org\n" -"POT-Creation-Date: 2026-03-20 20:44+0800\n" +"POT-Creation-Date: 2026-04-05 23:26+0800\n" "PO-Revision-Date: 2025-12-28 14:27+0800\n" "Last-Translator: Mao-Yining\n" "Language-Team: Simplified Chinese\n" @@ -55,7 +55,7 @@ msgid "auto-removing autocommand: %s " msgstr "ԶɾԶ %s " msgid "W19: Deleting augroup that is still in use" -msgstr "W19: ɾʹеԶ" +msgstr "W19: ɾʹеԶ" msgid "" "\n" @@ -600,11 +600,11 @@ msgstr " #, c-format msgid "W20: Required python version 2.x not supported, ignoring file: %s" -msgstr "W20: ֧Ҫ Python 2.x 汾ļ%s" +msgstr "W20: Python 2.x 汾֧֣ļ%s" #, c-format msgid "W21: Required python version 3.x not supported, ignoring file: %s" -msgstr "W21: ֧Ҫ Python 3.x 汾ļ%s" +msgstr "W21: Python 3.x 汾֧֣ļ%s" msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr " Ex ģʽ \"visual\" صģʽ" @@ -743,7 +743,7 @@ msgid "[character special]" msgstr "[ַ豸]" msgid "[CR missing]" -msgstr "[ȱ CR]'" +msgstr "[ȱ CR]" msgid "[long lines split]" msgstr "[зָ]" @@ -824,7 +824,7 @@ msgstr " #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" -msgstr "W16: : ༭ʼļ \"%s\" ģʽѱ䶯" +msgstr "W16: : ༭ʼļ \"%s\" Ȩģʽѱ䶯" msgid "See \":help W16\" for more info." msgstr " \":help W16\" ԻȡϢ" @@ -1137,7 +1137,7 @@ msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection setpgid ʧ" msgid "cs_create_connection exec failed" -msgstr "cs_create_connection ִʧ" +msgstr "cs_create_connection exec ʧ" msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: fdopen to_fp ʧ" @@ -2347,6 +2347,10 @@ msgstr " ( msgid "Beep!" msgstr "Beep!" +#, c-format +msgid "Executing directly: \"%s\"" +msgstr "ֱִУ%s" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr " shell ִ: \"%s\"" @@ -3279,7 +3283,7 @@ msgstr " #, c-format msgid "Duplicate field name: %s" -msgstr "ظֶ%s" +msgstr "ظֶƣ%s" msgid "' not known. Available builtin terminals are:" msgstr "' δ֪õڽն:" @@ -4325,7 +4329,7 @@ msgstr "E127: #, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: Դдĸ \"s:\" ͷ: %s" +msgstr "E128: Դдĸ \"s:\" ͷ%s" msgid "E129: Function name required" msgstr "E129: Ҫ" @@ -4351,7 +4355,7 @@ msgstr "E136: viminfo: #, c-format msgid "E137: Viminfo file is not writable: %s" -msgstr "E137: Viminfo ļд: %s" +msgstr "E137: Viminfo ļд룺%s" #, c-format msgid "E138: Can't write viminfo file %s!" @@ -5257,7 +5261,7 @@ msgid "E418: Illegal value: %s" msgstr "E418: Ϸֵ: %s" msgid "E418: I'm a teapot" -msgstr "E418: Dz󿧷ȣʵ" +msgstr "E418: Dz" msgid "E419: FG color unknown" msgstr "E419: ǰɫ" @@ -5564,7 +5568,7 @@ msgid "E503: \"%s\" is not a file or writable device" msgstr "E503: \"%s\" ļд豸" msgid "E503: Coffee is currently not available" -msgstr "E503: ǰ޷ṩȣʵ" +msgstr "E503: ȵǰ" msgid "is read-only (cannot override: \"W\" in 'cpoptions')" msgstr "ֻ (ǿִУ'cpoptions' а \"W\")" @@ -6047,7 +6051,7 @@ msgid "E655: Too many symbolic links (cycle?)" msgstr "E655: ӹ(ѭ)" msgid "NetBeans disallows writes of unmodified buffers" -msgstr "NetBeans δ޸ĵĻд" +msgstr "NetBeans дδ޸ĵĻ" msgid "Partial writes disallowed for NetBeans buffers" msgstr "NetBeans д" @@ -8920,8 +8924,8 @@ msgstr "E1545: Quickfix msgid "E1546: Cannot switch to a closing buffer" msgstr "E1546: лڹرյĻ" -msgid "E1547: This version of Vim does support :redrawtabpanel" -msgstr "E1547: ˰汾 Vim ֧ :redrawtabpanel" +msgid "E1547: This version of Vim does not support :redrawtabpanel" +msgstr "E1547: ˰汾 Vim ֧ :redrawtabpanel" msgid "E1548: Wayland connection is unavailable" msgstr "E1548: Wayland Ӳ" @@ -9017,42 +9021,21 @@ msgstr "E1573: msgid "E1574: gethostbyname(): cannot resolve hostname in channel_listen()" msgstr "E1574: gethostbyname()޷ channel_listen() н" +msgid "E1575: Cannot create pipes" +msgstr "E1575: ޷ܵ" + msgid "--No lines in buffer--" msgstr "----" -msgid "int" -msgstr "int" - -msgid "long int" -msgstr "long int" - -msgid "long long int" -msgstr "long long int" - -msgid "unsigned int" -msgstr "unsigned int" - -msgid "unsigned long int" -msgstr "unsigned long int" - -msgid "unsigned long long int" -msgstr "unsigned long long int" - msgid "pointer" msgstr "pointer" msgid "percent" msgstr "percent" -msgid "char" -msgstr "char" - msgid "string" msgstr "string" -msgid "float" -msgstr "float" - msgid "search hit TOP, continuing at BOTTOM" msgstr "Ѳҵļͷٴӽβ" @@ -9320,7 +9303,7 @@ msgid "" "You should now append vim.VIM_SPECIAL_PATH to sys.path" msgstr "" "·ʧܣsys.path б\n" -"Ӧ vim.VIM_SPECIAL_PATH sys.path" +"Ӧ vim.VIM_SPECIAL_PATH sys.path" msgid "" "Vim macro files (*.vim)\t*.vim\n" diff --git a/src/popupwin.c b/src/popupwin.c index cbbb7c6e5d..3ab96cb3e5 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -4103,6 +4103,11 @@ popup_update_mask(win_T *wp, int width, int height) return; // cache is still valid vim_free(wp->w_popup_mask_cells); + if (width > 0 && (size_t)height > SIZE_MAX / (size_t)width) + { + wp->w_popup_mask_cells = NULL; + return; + } wp->w_popup_mask_cells = alloc_clear((size_t)width * height); if (wp->w_popup_mask_cells == NULL) return; diff --git a/src/pty.c b/src/pty.c index 55bbf94d54..c615785c7e 100644 --- a/src/pty.c +++ b/src/pty.c @@ -354,15 +354,15 @@ mch_openpty(char **ttyn) #ifndef PTY_DONE # ifdef hpux -static char PtyProto[] = "/dev/ptym/ptyXY"; -static char TtyProto[] = "/dev/pty/ttyXY"; +static const char PtyProto[] = "/dev/ptym/ptyXY"; +static const char TtyProto[] = "/dev/pty/ttyXY"; # else # ifdef __HAIKU__ -static char PtyProto[] = "/dev/pt/XY"; -static char TtyProto[] = "/dev/tt/XY"; +static const char PtyProto[] = "/dev/pt/XY"; +static const char TtyProto[] = "/dev/tt/XY"; # else -static char PtyProto[] = "/dev/ptyXY"; -static char TtyProto[] = "/dev/ttyXY"; +static const char PtyProto[] = "/dev/ptyXY"; +static const char TtyProto[] = "/dev/ttyXY"; # endif # endif diff --git a/src/regexp.c b/src/regexp.c index 6ac74467f9..54fadc899e 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -377,7 +377,7 @@ static int reg_strict; // "[abc" is illegal */ // META[] is used often enough to justify turning it into a table. -static char_u META_flags[] = { +static const char_u META_flags[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // % & ( ) * + . @@ -2908,7 +2908,7 @@ static regengine_T nfa_regengine = static int regexp_engine = 0; #ifdef DEBUG -static char_u regname[][30] = { +static const char_u regname[][30] = { "AUTOMATIC Regexp Engine", "BACKTRACKING Regexp Engine", "NFA Regexp Engine" diff --git a/src/regexp_bt.c b/src/regexp_bt.c index 063510c643..1fa80f5c72 100644 --- a/src/regexp_bt.c +++ b/src/regexp_bt.c @@ -253,7 +253,7 @@ static int one_exactly = FALSE; // only do one char for EXACTLY // When making changes to classchars also change nfa_classcodes. static char_u *classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU"; -static int classcodes[] = { +static const int classcodes[] = { ANY, IDENT, SIDENT, KWORD, SKWORD, FNAME, SFNAME, PRINT, SPRINT, WHITE, NWHITE, DIGIT, NDIGIT, @@ -5525,7 +5525,7 @@ regprop(char_u *op) case MOPEN + 7: case MOPEN + 8: case MOPEN + 9: - buflen += sprintf(buf + buflen, "MOPEN%d", OP(op) - MOPEN); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "MOPEN%d", OP(op) - MOPEN); p = NULL; break; case MCLOSE + 0: @@ -5540,7 +5540,7 @@ regprop(char_u *op) case MCLOSE + 7: case MCLOSE + 8: case MCLOSE + 9: - buflen += sprintf(buf + buflen, "MCLOSE%d", OP(op) - MCLOSE); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "MCLOSE%d", OP(op) - MCLOSE); p = NULL; break; case BACKREF + 1: @@ -5552,7 +5552,7 @@ regprop(char_u *op) case BACKREF + 7: case BACKREF + 8: case BACKREF + 9: - buflen += sprintf(buf + buflen, "BACKREF%d", OP(op) - BACKREF); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "BACKREF%d", OP(op) - BACKREF); p = NULL; break; case NOPEN: @@ -5571,7 +5571,7 @@ regprop(char_u *op) case ZOPEN + 7: case ZOPEN + 8: case ZOPEN + 9: - buflen += sprintf(buf + buflen, "ZOPEN%d", OP(op) - ZOPEN); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "ZOPEN%d", OP(op) - ZOPEN); p = NULL; break; case ZCLOSE + 1: @@ -5583,7 +5583,7 @@ regprop(char_u *op) case ZCLOSE + 7: case ZCLOSE + 8: case ZCLOSE + 9: - buflen += sprintf(buf + buflen, "ZCLOSE%d", OP(op) - ZCLOSE); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "ZCLOSE%d", OP(op) - ZCLOSE); p = NULL; break; case ZREF + 1: @@ -5595,7 +5595,7 @@ regprop(char_u *op) case ZREF + 7: case ZREF + 8: case ZREF + 9: - buflen += sprintf(buf + buflen, "ZREF%d", OP(op) - ZREF); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "ZREF%d", OP(op) - ZREF); p = NULL; break; # endif @@ -5636,7 +5636,7 @@ regprop(char_u *op) case BRACE_COMPLEX + 7: case BRACE_COMPLEX + 8: case BRACE_COMPLEX + 9: - buflen += sprintf(buf + buflen, "BRACE_COMPLEX%d", OP(op) - BRACE_COMPLEX); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "BRACE_COMPLEX%d", OP(op) - BRACE_COMPLEX); p = NULL; break; case MULTIBYTECODE: @@ -5646,12 +5646,12 @@ regprop(char_u *op) p = "NEWL"; break; default: - buflen += sprintf(buf + buflen, "corrupt %d", OP(op)); + buflen += vim_snprintf(buf + buflen, sizeof(buf) - buflen, "corrupt %d", OP(op)); p = NULL; break; } if (p != NULL) - STRCPY(buf + buflen, p); + vim_strncpy((char_u *)buf + buflen, (char_u *)p, sizeof(buf) - buflen - 1); return (char_u *)buf; } #endif // DEBUG diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c index b17d4d3493..610c6bd678 100644 --- a/src/regexp_nfa.c +++ b/src/regexp_nfa.c @@ -233,7 +233,7 @@ enum }; // Keep in sync with classchars. -static int nfa_classcodes[] = { +static const int nfa_classcodes[] = { NFA_ANY, NFA_IDENT, NFA_SIDENT, NFA_KWORD,NFA_SKWORD, NFA_FNAME, NFA_SFNAME, NFA_PRINT, NFA_SPRINT, NFA_WHITE, NFA_NWHITE, NFA_DIGIT, NFA_NDIGIT, diff --git a/src/scriptfile.c b/src/scriptfile.c index 6df5781a73..df90fe7711 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -885,7 +885,7 @@ add_pack_dir_to_rtp(char_u *fname) buf.length = (size_t)copy_option_part(&entry, buf.string, MAXPATHL, ","); // keep track of p_rtp length as we go to make the STRLEN() below have less work to do - p_rtp_len += (*(p_rtp + buf.length) == ',') ? buf.length + 1 : buf.length; + p_rtp_len += (*(cur_entry + buf.length) == ',') ? buf.length + 1 : buf.length; if ((p = (char_u *)strstr((char *)buf.string, "after")) != NULL && p > buf.string diff --git a/src/spell.c b/src/spell.c index 78fd78a78d..01eb57e3a9 100644 --- a/src/spell.c +++ b/src/spell.c @@ -2965,7 +2965,7 @@ ex_spellrepall(exarg_T *eap UNUSED) } size_t repl_from_len = STRLEN(repl_from); size_t repl_to_len = STRLEN(repl_to); - int addlen = (int)(repl_to_len - repl_from_len); + long addlen = (long)repl_to_len - (long)repl_from_len; frompat = alloc(repl_from_len + 7); if (frompat == NULL) @@ -2999,7 +2999,7 @@ ex_spellrepall(exarg_T *eap UNUSED) #if defined(FEAT_PROP_POPUP) if (curbuf->b_has_textprop && addlen != 0) adjust_prop_columns(curwin->w_cursor.lnum, - curwin->w_cursor.col, addlen, APC_SUBSTITUTE); + curwin->w_cursor.col, (int)addlen, APC_SUBSTITUTE); #endif if (curwin->w_cursor.lnum != prev_lnum) diff --git a/src/spellfile.c b/src/spellfile.c index 7c105cf79c..c570920795 100644 --- a/src/spellfile.c +++ b/src/spellfile.c @@ -1589,7 +1589,7 @@ spell_read_tree( len = get4c(fd); if (len < 0) return SP_TRUNCERROR; - if (len >= LONG_MAX / (long)sizeof(int)) + if ((size_t)len > SIZE_MAX / sizeof(int)) // Invalid length, multiply with sizeof(int) would overflow. return SP_FORMERROR; if (len <= 0) diff --git a/src/strings.c b/src/strings.c index b47422c114..82ebdb644d 100644 --- a/src/strings.c +++ b/src/strings.c @@ -626,6 +626,8 @@ vim_strchr(char_u *string, int c) int b; p = string; + if (enc_utf8 && c > 0 && c < 0x80) + return vim_strbyte(string, c); if (enc_utf8 && c >= 0x80) { while (*p != NUL) @@ -3012,22 +3014,22 @@ format_typename( switch (format_typeof(type)) { case TYPE_INT: - return _(typename_int); + return typename_int; case TYPE_LONGINT: - return _(typename_longint); + return typename_longint; case TYPE_LONGLONGINT: - return _(typename_longlongint); + return typename_longlongint; case TYPE_UNSIGNEDINT: - return _(typename_unsignedint); + return typename_unsignedint; case TYPE_UNSIGNEDLONGINT: - return _(typename_unsignedlongint); + return typename_unsignedlongint; case TYPE_UNSIGNEDLONGLONGINT: - return _(typename_unsignedlonglongint); + return typename_unsignedlonglongint; case TYPE_POINTER: return _(typename_pointer); @@ -3036,13 +3038,13 @@ format_typename( return _(typename_percent); case TYPE_CHAR: - return _(typename_char); + return typename_char; case TYPE_STRING: return _(typename_string); case TYPE_FLOAT: - return _(typename_float); + return typename_float; } return _(typename_unknown); diff --git a/src/term.c b/src/term.c index 008916b7df..e72e658338 100644 --- a/src/term.c +++ b/src/term.c @@ -689,7 +689,7 @@ static tcap_entry_T builtin_sync_output[] = { /* * List of DECRQM modes that Vim supports */ -static int dec_modes[] = { +static const int dec_modes[] = { 2026, // Synchronized output #ifdef UNIX 2048 // In-band terminal resize events @@ -7215,6 +7215,13 @@ find_term_bykeys(char_u *src, int *matchlen) int slen, modslen; int thislen; + // Most input bytes cannot start a terminal code. Reuse the same leader + // table as check_termcode() to avoid scanning termcodes[] unnecessarily. + if (need_gather) + gather_termleader(); + if (*src == NUL || vim_strchr(termleader, *src) == NULL) + return -1; + // find longest match // borrows part of check_termcode for (i = 0; i < tc_len; ++i) @@ -7833,11 +7840,11 @@ swap_tcap(void) #if (defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))) || defined(FEAT_TERMINAL) -static int cube_value[] = { +static const int cube_value[] = { 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF }; -static int grey_ramp[] = { +static const int grey_ramp[] = { 0x08, 0x12, 0x1C, 0x26, 0x30, 0x3A, 0x44, 0x4E, 0x58, 0x62, 0x6C, 0x76, 0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE }; diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 5ebbee6d00..de70acf6b6 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -256,6 +256,7 @@ NEW_TESTS = \ test_plugin_termdebug \ test_plugin_tohtml \ test_plugin_tutor \ + test_plugin_vimball \ test_plugin_zip \ test_plus_arg_edit \ test_popup \ @@ -533,6 +534,7 @@ NEW_TESTS_RES = \ test_plugin_termdebug.res \ test_plugin_tohtml.res \ test_plugin_tutor.res \ + test_plugin_vimball.res \ test_plugin_zip.res \ test_plus_arg_edit.res \ test_popup.res \ diff --git a/src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump b/src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump index a1825a9ee2..69bbb16772 100644 --- a/src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump +++ b/src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump @@ -2,5 +2,5 @@ |f+0#0000001#a8a8a8255|o@1> +0#0000000#ffffff0@16||+1&&|~+0#4040ff13&| @52 |x+0#0000000&@19||+1&&|~+0#4040ff13&| @52 |~| @18||+1#0000000&|~+0#4040ff13&| @52 -|<+3#0000000&|a|m|e|]| |[|+|]| |2|,|4| @3|A|l@1| |[+1&&|N|o| |N|a|m|e|]| @26|0|,|0|-|1| @9|A|l@1 -|-+2&&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@45|2|x|2|0| @6 +|~| @18||+1#0000000&|~+0#4040ff13&| @52 +|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@28|2|x|4| @6|2|,|4| @10|A|l@1| diff --git a/src/testdir/samples/evil.zip b/src/testdir/samples/evil.zip index 17cffadf93..8361710b9b 100644 Binary files a/src/testdir/samples/evil.zip and b/src/testdir/samples/evil.zip differ diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index 203ae0428e..6cd55ca9f9 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -2763,10 +2763,17 @@ endfunc let g:server_received_addr = '' let g:server_received_msg = '' +let g:server_received_input = '' + +func s:test_listen_input(ch, msg) + let g:server_received_input = a:msg +endfunc func s:test_listen_accept(ch, addr) let g:server_received_addr = a:addr let g:server_received_msg = ch_readraw(a:ch) + + call ch_setoptions(a:ch, #{mode: "raw", callback: function('s:test_listen_input')}) endfunction func Test_listen() @@ -2782,7 +2789,10 @@ func Test_listen() return endif call ch_sendraw(handle, 'hello') - call WaitFor('"" != g:server_received_msg') + call WaitFor('"hello" == g:server_received_msg') + call ch_sendraw(handle, 'notify') + call WaitFor('"notify" == g:server_received_input') + call ch_close(handle) call ch_close(server) call assert_equal('hello', g:server_received_msg) diff --git a/src/testdir/test_listlbr.vim b/src/testdir/test_listlbr.vim index 7430ec626c..434bef3609 100644 --- a/src/testdir/test_listlbr.vim +++ b/src/testdir/test_listlbr.vim @@ -195,14 +195,28 @@ func Test_linebreak_reset_restore() call StopVimInTerminal(buf) endfunc -func Test_virtual_block() +func Test_visual_block() call s:test_windows('setl sbr=+') call setline(1, [ \ "REMOVE: this not", \ "REMOVE: aaaaaaaaaaaaa", \ ]) + set showcmd showcmdloc=tabline showtabline=2 tabline=%S + if has('gui') + set guioptions-=e + endif exe "norm! 1/^REMOVE:" - exe "norm! 0\jf x" + exe "norm! 0\jf " + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "2x8 ", +\ "REMOVE: this not ", +\ "REMOVE: ", +\ "+aaaaaaaaaaaaa ", +\ ] + call s:compare_lines(expect, lines) + norm! x + set showcmd& showcmdloc& showtabline& tabline& guioptions& $put let lines = s:screen_lines([1, 4], winwidth(0)) let expect = [ @@ -215,7 +229,7 @@ func Test_virtual_block() call s:close_windows() endfunc -func Test_virtual_block_and_vbA() +func Test_visual_block_and_vbA() call s:test_windows() call setline(1, "long line: " . repeat("foobar ", 40) . "TARGET at end") exe "norm! $3B\eAx\" @@ -236,7 +250,7 @@ func Test_virtual_block_and_vbA() call s:close_windows() endfunc -func Test_virtual_char_and_block() +func Test_visual_char_and_block() call s:test_windows() call setline(1, "1111-1111-1111-11-1111-1111-1111") exe "norm! 0f-lv3lc2222\bgj." diff --git a/src/testdir/test_listlbr_utf8.vim b/src/testdir/test_listlbr_utf8.vim index bde1a49580..5bac070b95 100644 --- a/src/testdir/test_listlbr_utf8.vim +++ b/src/testdir/test_listlbr_utf8.vim @@ -412,11 +412,12 @@ func Test_visual_block_hl_with_linebreak() setlocal nolinebreak call setline(1, [repeat('x', 15), repeat('x', 10), repeat('x', 10)]) call prop_type_add('test', {}) - call prop_add(2, 5, #{text: "foo: ",type: "test"}) - call prop_add(3, 5, #{text: "bar: ",type: "test"}) + call prop_add(2, 5, #{text: "foo: ", type: "test"}) + call prop_add(3, 5, #{text: "bar: ", type: "test"}) exe "normal! gg02l\2j2l" endfunc + set laststatus=0 showcmd ruler " FIXME: clipboard=autoselect sometimes changes Visual highlight set clipboard= END diff --git a/src/testdir/test_packadd.vim b/src/testdir/test_packadd.vim index cd7126a9db..6a368762a9 100644 --- a/src/testdir/test_packadd.vim +++ b/src/testdir/test_packadd.vim @@ -26,6 +26,13 @@ func Test_packadd() " plugdir should be inserted before plugdir/after call assert_match('^nosuchdir,' . s:plugdir . ',', &rtp) + " This used to cause heep-buffer-overflow + " All existing entries in 'rtp' have the same length here + let &rtp = 'Xfoodir,Xbardir,Xbazdir' + packadd mytest + " plugdir should be inserted after the existing directories + call assert_match('^Xfoodir,Xbardir,Xbazdir,' .. s:plugdir .. ',', &rtp) + set rtp& let rtp = &rtp filetype on diff --git a/src/testdir/test_plugin_netrw.vim b/src/testdir/test_plugin_netrw.vim index 2e5da13d75..b234670928 100644 --- a/src/testdir/test_plugin_netrw.vim +++ b/src/testdir/test_plugin_netrw.vim @@ -604,4 +604,9 @@ func Test_netrw_FileUrlEdit_pipe_injection() call assert_false(filereadable(fname), 'Command injection via pipe in file URL') endfunc +func Test_netrw_RFC2396() + let fname = 'a%20b' + call assert_equal('a b', netrw#RFC2396(fname)) +endfunc + " vim:ts=8 sts=2 sw=2 et diff --git a/src/testdir/test_plugin_tar.vim b/src/testdir/test_plugin_tar.vim index 8d34ce11a7..d6dbdd7613 100644 --- a/src/testdir/test_plugin_tar.vim +++ b/src/testdir/test_plugin_tar.vim @@ -147,3 +147,57 @@ def g:Test_tar_path_traversal_with_nowrapscan() bw! enddef + +def g:Test_tar_lz4_extract() + CheckExecutable lz4 + + delete('X.txt') + delete('Xarchive.tar') + delete('Xarchive.tar.lz4') + call writefile(['hello'], 'X.txt') + call system('tar -cf Xarchive.tar X.txt') + assert_equal(0, v:shell_error) + + call system('lz4 -z Xarchive.tar Xarchive.tar.lz4') + assert_equal(0, v:shell_error) + + delete('X.txt') + delete('Xarchive.tar') + defer delete('Xarchive.tar.lz4') + + e Xarchive.tar.lz4 + assert_match('X.txt', getline(5)) + :5 + normal x + assert_true(filereadable('X.txt')) + assert_equal(['hello'], readfile('X.txt')) + delete('X.txt') + bw! +enddef + +def g:Test_tlz4_extract() + CheckExecutable lz4 + + delete('X.txt') + delete('Xarchive.tar') + delete('Xarchive.tlz4') + call writefile(['goodbye'], 'X.txt') + call system('tar -cf Xarchive.tar X.txt') + assert_equal(0, v:shell_error) + + call system('lz4 -z Xarchive.tar Xarchive.tlz4') + assert_equal(0, v:shell_error) + + delete('X.txt') + delete('Xarchive.tar') + defer delete('Xarchive.tlz4') + + e Xarchive.tlz4 + assert_match('X.txt', getline(5)) + :5 + normal x + assert_true(filereadable('X.txt')) + assert_equal(['goodbye'], readfile('X.txt')) + delete('X.txt') + bw! +enddef diff --git a/src/testdir/test_plugin_vimball.vim b/src/testdir/test_plugin_vimball.vim new file mode 100644 index 0000000000..2d5b4ba768 --- /dev/null +++ b/src/testdir/test_plugin_vimball.vim @@ -0,0 +1,85 @@ +" Test for the vimball plugin + +let s:testdir = expand("