Author: Andrew Bower <andrew@bower.uk>
Description: Fix reverse reading of incomplete trailing record
Last-Update: 2025-09-22
Bug: https://savannah.gnu.org/bugs/?56282
Bug: https://savannah.gnu.org/bugs/?56285
Bug: https://savannah.gnu.org/bugs/?49930
Bug-Debian: https://bugs.debian.org/715840
Bug-Debian: https://bugs.debian.org/715841
Bug-Debian: https://bugs.debian.org/506701
Forwarded: https://file.savannah.gnu.org/file/fix-reverse-read-incomplete-record.patch?file_id=57676

---
 file_rd.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/file_rd.c b/file_rd.c
index ac2a754..6c2b324 100644
--- a/file_rd.c
+++ b/file_rd.c
@@ -106,13 +106,23 @@ char *file_reader_get_entry(struct file_rd_info *fri)
             {
               off_t offset, max_recs, recs_to_read;
 
-              if ((offset = ftello (fri->fp)) <= 0)
+              if ((offset = ftello (fri->fp)) < 0) {
+                perror("get_entry: error determining file position");
+                offset = 0;
+              }
+
+              max_recs = offset / (off_t) fri->record_size;
+              if (max_recs * (off_t) fri->record_size != offset) {
+                fprintf(stderr, "warning: data beyond last complete record\n");
+                offset = max_recs * (off_t) fri->record_size;
+              }
+
+              if (offset == 0)
                 goto no_more_records;
 
               /* Read as many records as possible, up to
                        FRI->BUFFERED_RECORDS */
 
-              max_recs = offset / (long) fri->record_size;
 
               recs_to_read = ((max_recs < fri->buffered_records)
                               ? max_recs
