aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-02-28 19:29:59 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-02-28 19:52:45 +0800
commit7aad75e293e3a01e292308ca2058e35083b83280 (patch)
tree7198c028ad1b012b9b0710d697df0b3ea95fd76d
parent4bd0611d7b07b56fc5a9e121669a313166ba540f (diff)
downloadrneovim-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.txt6
-rw-r--r--src/nvim/eval.c17
-rw-r--r--src/nvim/testdir/test_blob.vim11
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