Skip to content

Commit c78f551

Browse files
committed
Improve binary file check to better handle PDFs
PDF files can have a very long text header before the first NUL byte The check now reads the first 2KB rather than 128 bytes, and uses the built-in index() function rather than looping which is very fast. That still didn't catch all PDFs, even increasing it to 8000 bytes like git diff didn't catch all PDFs, so also check for %PDF- signature in file. The increased number of bytes to check remains even with the %PDF- signature check because it costs very little (page size is min 4KB), and will potentially catch other binary files with long text headers.
1 parent 77c0bdd commit c78f551

1 file changed

Lines changed: 17 additions & 5 deletions

File tree

‎autoload/fuzzbox/internal/previewer.vim‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ vim9script
33
import autoload './popup.vim'
44
import './filetype.vim'
55

6+
const PDF_SIGNATURE = '%PDF-'
7+
const PDF_SIGNATURE_BLOB = list2blob(str2list(PDF_SIGNATURE))
8+
69
def IsBinary(path: string): bool
710
# NUL byte check for binary files, used to avoid showing preview
811
# Assumes a file encoding that does not allow NUL bytes, so will
@@ -11,18 +14,27 @@ def IsBinary(path: string): bool
1114
if !has('patch-9.0.0810')
1215
# Workaround for earlier versions of Vim with limited readblob()
1316
# Option to read only part of file finalised in patch 9.0.0810
14-
return match(readfile(path, '', 10), '\%x00') != -1
17+
var lines = readfile(path, '', 10)
18+
if !empty(lines) && type(lines[0]) == v:t_string
19+
if lines[0][0 : len(PDF_SIGNATURE) - 1] == PDF_SIGNATURE
20+
return true
21+
endif
22+
endif
23+
return match(lines, '\%x00') != -1
1524
endif
1625
return IsBinaryBlob(path)
1726
enddef
1827

1928
# Note: use of legacy function a workaround for compilation failing when
2029
# readblob() would be called with invalid args on earlier Vim versions
30+
# Check first 2048 bytes as some binary formats have a long text header
31+
# Specific check for PDF file signature because PDF headers can be huge
2132
function IsBinaryBlob(path)
22-
for byte in readblob(a:path, 0, 128)
23-
if byte == 0 | return v:true | endif
24-
endfor
25-
return v:false
33+
let blob = readblob(a:path, 0, 2048)
34+
if blob[0 : len(s:PDF_SIGNATURE) - 1] == s:PDF_SIGNATURE_BLOB
35+
return v:true
36+
endif
37+
return index(blob, 0) != -1
2638
endfunction
2739

2840
def FTDetectModelines(content: list<string>): string

0 commit comments

Comments
 (0)