Mercurial > vim
view runtime/autoload/gzip.vim @ 34074:1629cc65d78d v9.1.0006
patch 9.1.0006: is*() and to*() function may be unsafe
Commit: https://github.com/vim/vim/commit/184f71cc6868a240dc872ed2852542bbc1d43e28
Author: Keith Thompson <Keith.S.Thompson@gmail.com>
Date: Thu Jan 4 21:19:04 2024 +0100
patch 9.1.0006: is*() and to*() function may be unsafe
Problem: is*() and to*() function may be unsafe
Solution: Add SAFE_* macros and start using those instead
(Keith Thompson)
Use SAFE_() macros for is*() and to*() functions
The standard is*() and to*() functions declared in <ctype.h> have
undefined behavior for negative arguments other than EOF. If plain char
is signed, passing an unchecked value from argv for from user input
to one of these functions has undefined behavior.
Solution: Add SAFE_*() macros that cast the argument to unsigned char.
Most implementations behave sanely for negative arguments, and most
character values in practice are non-negative, but it's still best
to avoid undefined behavior.
The change from #13347 has been omitted, as this has already been
separately fixed in commit ac709e2fc0db6d31abb7da96f743c40956b60c3a
(v9.0.2054)
fixes: #13332
closes: #13347
Signed-off-by: Keith Thompson <Keith.S.Thompson@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 04 Jan 2024 21:30:04 +0100 |
parents | bd3ee5abdd7a |
children |
line wrap: on
line source
" Vim autoload file for editing compressed files. " Maintainer: The Vim Project <https://github.com/vim/vim> " Last Change: 2023 Aug 10 " Former Maintainer: Bram Moolenaar <Bram@vim.org> " These functions are used by the gzip plugin. " Function to check that executing "cmd [-f]" works. " The result is cached in s:have_"cmd" for speed. fun s:check(cmd) let name = substitute(a:cmd, '\(\S*\).*', '\1', '') if !exists("s:have_" . name) " safety check, don't execute anything from the current directory let f = dist#vim#IsSafeExecutable('gzip', name) if !f echoerr "Warning: NOT executing " .. name .. " from current directory!" endif let e = executable(name) if e < 0 let r = system(name . " --version") let e = (r !~ "not found" && r != "") endif exe "let s:have_" . name . "=" . (e && f) endif exe "return s:have_" . name endfun " Set b:gzip_comp_arg to the gzip argument to be used for compression, based on " the flags in the compressed file. " The only compression methods that can be detected are max speed (-1) and max " compression (-9). fun s:set_compression(line) " get the Compression Method let l:cm = char2nr(a:line[2]) " if it's 8 (DEFLATE), we can check for the compression level if l:cm == 8 " get the eXtra FLags let l:xfl = char2nr(a:line[8]) " max compression if l:xfl == 2 let b:gzip_comp_arg = "-9" " min compression elseif l:xfl == 4 let b:gzip_comp_arg = "-1" endif endif endfun " After reading compressed file: Uncompress text in buffer with "cmd" fun gzip#read(cmd) " don't do anything if the cmd is not supported if !s:check(a:cmd) return endif " for gzip check current compression level and set b:gzip_comp_arg. silent! unlet b:gzip_comp_arg if a:cmd[0] == 'g' call s:set_compression(getline(1)) endif " make 'patchmode' empty, we don't want a copy of the written file let pm_save = &pm set pm= " remove 'a' and 'A' from 'cpo' to avoid the alternate file changes let cpo_save = &cpo set cpo-=a cpo-=A " set 'modifiable' let ma_save = &ma setlocal ma " set 'write' let write_save = &write set write " Reset 'foldenable', otherwise line numbers get adjusted. if has("folding") let fen_save = &fen setlocal nofen endif " when filtering the whole buffer, it will become empty let empty = line("'[") == 1 && line("']") == line("$") let tmp = tempname() let tmpe = tmp . "." . expand("<afile>:e") if exists('*fnameescape') let tmp_esc = fnameescape(tmp) let tmpe_esc = fnameescape(tmpe) else let tmp_esc = escape(tmp, ' ') let tmpe_esc = escape(tmpe, ' ') endif " write the just read lines to a temp file "'[,']w tmp.gz" execute "silent '[,']w " . tmpe_esc " uncompress the temp file: call system("gzip -dn tmp.gz") call system(a:cmd . " " . s:escape(tmpe)) if !filereadable(tmp) " uncompress didn't work! Keep the compressed file then. echoerr "Error: Could not read uncompressed file" let ok = 0 else let ok = 1 " delete the compressed lines; remember the line number let l = line("'[") - 1 if exists(":lockmarks") lockmarks '[,']d _ else '[,']d _ endif " read in the uncompressed lines "'[-1r tmp" " Use ++edit if the buffer was empty, keep the 'ff' and 'fenc' options. setlocal nobin if exists(":lockmarks") if empty execute "silent lockmarks " . l . "r ++edit " . tmp_esc else execute "silent lockmarks " . l . "r " . tmp_esc endif else execute "silent " . l . "r " . tmp_esc endif " if buffer became empty, delete trailing blank line if empty silent $delete _ 1 endif " delete the temp file and the used buffers call delete(tmp) silent! exe "bwipe " . tmp_esc silent! exe "bwipe " . tmpe_esc endif " Store the OK flag, so that we can use it when writing. let b:uncompressOk = ok " Restore saved option values. let &pm = pm_save let &cpo = cpo_save let &l:ma = ma_save let &write = write_save if has("folding") let &l:fen = fen_save endif " When uncompressed the whole buffer, do autocommands if ok && empty if exists('*fnameescape') let fname = fnameescape(expand("%:r")) else let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<") endif if &verbose >= 8 execute "doau BufReadPost " . fname else execute "silent! doau BufReadPost " . fname endif endif endfun " After writing compressed file: Compress written file with "cmd" fun gzip#write(cmd) if exists('b:uncompressOk') && !b:uncompressOk echomsg "Not compressing file because uncompress failed; reset b:uncompressOk to compress anyway" " don't do anything if the cmd is not supported elseif s:check(a:cmd) " Rename the file before compressing it. let nm = resolve(expand("<afile>")) let nmt = s:tempname(nm) if rename(nm, nmt) == 0 if exists("b:gzip_comp_arg") call system(a:cmd . " " . b:gzip_comp_arg . " -- " . s:escape(nmt)) else call system(a:cmd . " -- " . s:escape(nmt)) endif call rename(nmt . "." . expand("<afile>:e"), nm) endif endif endfun " Before appending to compressed file: Uncompress file with "cmd" fun gzip#appre(cmd) " don't do anything if the cmd is not supported if s:check(a:cmd) let nm = expand("<afile>") " for gzip check current compression level and set b:gzip_comp_arg. silent! unlet b:gzip_comp_arg if a:cmd[0] == 'g' call s:set_compression(readfile(nm, "b", 1)[0]) endif " Rename to a weird name to avoid the risk of overwriting another file let nmt = expand("<afile>:p:h") . "/X~=@l9q5" let nmte = nmt . "." . expand("<afile>:e") if rename(nm, nmte) == 0 if &patchmode != "" && getfsize(nm . &patchmode) == -1 " Create patchmode file by creating the decompressed file new call system(a:cmd . " -c -- " . s:escape(nmte) . " > " . s:escape(nmt)) call rename(nmte, nm . &patchmode) else call system(a:cmd . " -- " . s:escape(nmte)) endif call rename(nmt, nm) endif endif endfun " find a file name for the file to be compressed. Use "name" without an " extension if possible. Otherwise use a weird name to avoid overwriting an " existing file. fun s:tempname(name) let fn = fnamemodify(a:name, ":r") if !filereadable(fn) && !isdirectory(fn) return fn endif return fnamemodify(a:name, ":p:h") . "/X~=@l9q5" endfun fun s:escape(name) " shellescape() was added by patch 7.0.111 if exists("*shellescape") return shellescape(a:name) endif return "'" . a:name . "'" endfun " vim: set sw=2 :