]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.0810: readblob() returns empty when trying to read too much v9.0.0810
authorBram Moolenaar <Bram@vim.org>
Fri, 21 Oct 2022 10:25:30 +0000 (11:25 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 21 Oct 2022 10:25:30 +0000 (11:25 +0100)
Problem:    readblob() returns empty when trying to read too much.
Solution:   Return what is available.

runtime/doc/builtin.txt
src/blob.c
src/testdir/test_blob.vim
src/version.c

index 5b383fdfcfa4751175a5b11293a0865e15cdd14d..5cb0bd95060aa756737c184a84fc6e7c3bfd8a14 100644 (file)
@@ -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()|.
 
 
index a94316c13f56fc5b91a5cbe25eb6ebf7ebb819a6..311b87e49c472a5c51abe4aa04f7b895440fc140 100644 (file)
@@ -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;
index 47315ab84fbfcbac1c8ad5ef024c416d3bb95d29..4a957aa7216811ea0945e441b1d08f970a7d430d 100644 (file)
@@ -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
index 94e5d5c95bbd5494385b99bedd23add36b072d7a..4017c472074f8aaf4f2b0ff44bf6e23237572ae1 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    810,
 /**/
     809,
 /**/