diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-10-21 11:25:30 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-10-21 11:25:30 +0100 |
commit | 5b2a3d77d320d76f12b1666938a9d58c2a848205 (patch) | |
tree | 435466e4c1e4d0ede36dd3e499e91ffebf0166e4 | |
parent | 63c84731c1802bac36c1d1a82b3ef5960b35b089 (diff) | |
download | vim-git-5b2a3d77d320d76f12b1666938a9d58c2a848205.tar.gz |
patch 9.0.0810: readblob() returns empty when trying to read too muchv9.0.0810
Problem: readblob() returns empty when trying to read too much.
Solution: Return what is available.
-rw-r--r-- | runtime/doc/builtin.txt | 6 | ||||
-rw-r--r-- | src/blob.c | 26 | ||||
-rw-r--r-- | src/testdir/test_blob.vim | 11 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 32 insertions, 13 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 5b383fdfc..5cb0bd950 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6866,8 +6866,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/blob.c b/src/blob.c index a94316c13..311b87e49 100644 --- a/src/blob.c +++ b/src/blob.c @@ -199,24 +199,32 @@ read_blob(FILE *fd, typval_T *rettv, off_T offset, off_T size_arg) 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 > st.st_size - offset +#ifdef S_ISCHR + && !S_ISCHR(st.st_mode) +#endif + )) // size may become negative, checked below size = st.st_size - offset; whence = SEEK_SET; } else { - if (size == -1) + // limit the offset to not go before the start of the file + if (-offset > st.st_size +#ifdef S_ISCHR + && !S_ISCHR(st.st_mode) +#endif + ) + offset = -st.st_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 || ( -#ifdef S_ISCHR - !S_ISCHR(st.st_mode) && -#endif - size > st.st_size)) + if (size <= 0) return OK; if (offset != 0 && vim_fseek(fd, offset, whence) != 0) return OK; diff --git a/src/testdir/test_blob.vim b/src/testdir/test_blob.vim index 47315ab84..4a957aa72 100644 --- a/src/testdir/test_blob.vim +++ b/src/testdir/test_blob.vim @@ -499,10 +499,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 diff --git a/src/version.c b/src/version.c index 94e5d5c95..4017c4720 100644 --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 810, +/**/ 809, /**/ 808, |