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.

5b2a3d77d3

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq
2023-02-28 19:29:59 +08:00
parent 4bd0611d7b
commit 7aad75e293
3 changed files with 24 additions and 10 deletions

View File

@@ -6171,8 +6171,10 @@ readblob({fname} [, {offset} [, {size}]]) *readblob()*
readblob('/dev/ttyS0', 0, 10) readblob('/dev/ttyS0', 0, 10)
< When the file can't be opened an error message is given and < When the file can't be opened an error message is given and
the result is an empty |Blob|. the result is an empty |Blob|.
When trying to read bytes beyond the end of the file the When the offset is beyond the end of the file the result is an
result is an empty blob. empty blob.
When trying to read more bytes than are available the result
is truncated.
Also see |readfile()| and |writefile()|. Also see |readfile()| and |writefile()|.

View File

@@ -5879,22 +5879,27 @@ int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg)
int whence; int whence;
off_T size = size_arg; off_T size = size_arg;
const off_T file_size = (off_T)os_fileinfo_size(&file_info);
if (offset >= 0) { 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 may become negative, checked below
size = (off_T)os_fileinfo_size(&file_info) - offset; size = (off_T)os_fileinfo_size(&file_info) - offset;
} }
whence = SEEK_SET; whence = SEEK_SET;
} else { } 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; size = -offset;
} }
whence = SEEK_END; whence = SEEK_END;
} }
// Trying to read bytes that aren't there results in an empty blob, not an if (size <= 0) {
// error.
if (size < 0 || (!S_ISCHR(file_info.stat.st_mode)
&& size > (off_T)os_fileinfo_size(&file_info))) {
return OK; return OK;
} }
if (offset != 0 && vim_fseek(fd, offset, whence) != 0) { if (offset != 0 && vim_fseek(fd, offset, whence) != 0) {

View File

@@ -450,10 +450,17 @@ func Test_blob_read_write()
VAR br6 = readblob('Xblob', -3, 2) VAR br6 = readblob('Xblob', -3, 2)
call assert_equal(b[-3 : -2], br6) call assert_equal(b[-3 : -2], br6)
#" reading past end of file, empty result
VAR br1e = readblob('Xblob', 10000) VAR br1e = readblob('Xblob', 10000)
call assert_equal(0z, br1e) 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') call delete('Xblob')
END END