diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-02-28 19:29:59 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-02-28 19:52:45 +0800 |
commit | 7aad75e293e3a01e292308ca2058e35083b83280 (patch) | |
tree | 7198c028ad1b012b9b0710d697df0b3ea95fd76d | |
parent | 4bd0611d7b07b56fc5a9e121669a313166ba540f (diff) | |
download | rneovim-7aad75e293e3a01e292308ca2058e35083b83280.tar.gz rneovim-7aad75e293e3a01e292308ca2058e35083b83280.tar.bz2 rneovim-7aad75e293e3a01e292308ca2058e35083b83280.zip |
vim-patch:9.0.0810: readblob() returns empty when trying to read too much
Problem: readblob() returns empty when trying to read too much.
Solution: Return what is available.
https://github.com/vim/vim/commit/5b2a3d77d320d76f12b1666938a9d58c2a848205
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | runtime/doc/builtin.txt | 6 | ||||
-rw-r--r-- | src/nvim/eval.c | 17 | ||||
-rw-r--r-- | src/nvim/testdir/test_blob.vim | 11 |
3 files changed, 24 insertions, 10 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index eab415f495..568b73ddfa 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6171,8 +6171,10 @@ readblob({fname} [, {offset} [, {size}]]) *readblob()* readblob('/dev/ttyS0', 0, 10) < When the file can't be opened an error message is given and the result is an empty |Blob|. - When trying to read bytes beyond the end of the file the - result is an empty blob. + When the offset is beyond the end of the file the result is an + empty blob. + When trying to read more bytes than are available the result + is truncated. Also see |readfile()| and |writefile()|. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 92fd8a8de3..b81384266c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5879,22 +5879,27 @@ int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg) int whence; off_T size = size_arg; + const off_T file_size = (off_T)os_fileinfo_size(&file_info); if (offset >= 0) { - if (size == -1) { + // The size defaults to the whole file. If a size is given it is + // limited to not go past the end of the file. + if (size == -1 || (size > file_size - offset && !S_ISCHR(file_info.stat.st_mode))) { // size may become negative, checked below size = (off_T)os_fileinfo_size(&file_info) - offset; } whence = SEEK_SET; } else { - if (size == -1) { + // limit the offset to not go before the start of the file + if (-offset > file_size && !S_ISCHR(file_info.stat.st_mode)) { + offset = -file_size; + } + // Size defaults to reading until the end of the file. + if (size == -1 || size > -offset) { size = -offset; } whence = SEEK_END; } - // Trying to read bytes that aren't there results in an empty blob, not an - // error. - if (size < 0 || (!S_ISCHR(file_info.stat.st_mode) - && size > (off_T)os_fileinfo_size(&file_info))) { + if (size <= 0) { return OK; } if (offset != 0 && vim_fseek(fd, offset, whence) != 0) { diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 5fc232119c..b01d9309fa 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -450,10 +450,17 @@ func Test_blob_read_write() VAR br6 = readblob('Xblob', -3, 2) call assert_equal(b[-3 : -2], br6) + #" reading past end of file, empty result VAR br1e = readblob('Xblob', 10000) call assert_equal(0z, br1e) - VAR br2e = readblob('Xblob', -10000) - call assert_equal(0z, br2e) + + #" reading too much, result is truncated + VAR blong = readblob('Xblob', -1000) + call assert_equal(b, blong) + LET blong = readblob('Xblob', -10, 8) + call assert_equal(b, blong) + LET blong = readblob('Xblob', 0, 10) + call assert_equal(b, blong) call delete('Xblob') END |