[libdvdnav-devel] [Git][videolan/libdvdread][master] 4 commits: dvd_input: fix stream seek offset truncation on 32-bit off_t

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Wed Jul 29 13:07:18 UTC 2026



Jean-Baptiste Kempf pushed to branch master at VideoLAN / libdvdread


Commits:
d824fe61 by Kacper Michajłow at 2026-07-29T15:04:24+02:00
dvd_input: fix stream seek offset truncation on 32-bit off_t

The byte offset passed to the pf_seek callback was computed in off_t
arithmetic before being widened to the callback's uint64_t parameter.
On platforms where off_t is 32-bit (Windows) this truncated seeks
beyond 2 GiB. Compute the offset in uint64_t directly.

- - - - -
1c2c33eb by Kacper Michajłow at 2026-07-29T15:04:24+02:00
file_win32: clamp oversized reads, callers must handle partial reads anyway

win32 CRT read() takes uint as input read size and returns int.

- - - - -
fff6d674 by Kacper Michajłow at 2026-07-29T15:04:24+02:00
dvd_input: keep block count as int

No need to use off_t here, and cause type mismatches with seek functions
that takes number of blocks as int anyway.

- - - - -
21cdfe9f by Kacper Michajłow at 2026-07-29T15:04:24+02:00
ifo_read: add explicit cast to suppres warnings

We convert number of bytes to count and we know that this will never be
huge value, safe to store as u16.

- - - - -


3 changed files:

- src/dvd_input.c
- src/file/file_win32.c
- src/ifo_read.c


Changes:

=====================================
src/dvd_input.c
=====================================
@@ -109,7 +109,8 @@ struct dvd_input_s {
   /* */
   void *priv;
   dvd_logger_cb *logcb;
-  off_t ipos;
+  /* Current position as a block index, -1 after a failed read */
+  int ipos;
 
   /* This variable keeps track of the current files stream_type,
    * and in turn determined the decryption method to use */
@@ -314,7 +315,7 @@ static int file_seek(dvd_input_t dev, int blocks)
 
   if (dev->stream_cb) {
     /* Returns 0 on successful completion and -1 on error */
-    pos = dev->stream_cb->pf_seek(dev->priv, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN);
+    pos = dev->stream_cb->pf_seek(dev->priv, blocks * (uint64_t)DVD_VIDEO_LB_LEN);
 
     if (!pos) {
       dev->ipos = blocks;
@@ -324,7 +325,7 @@ static int file_seek(dvd_input_t dev, int blocks)
     pos = dev->fs->file_seek(dev->file, (off64_t)blocks * (off64_t)DVD_VIDEO_LB_LEN, SEEK_SET);
 
     if (pos >= 0) {
-      dev->ipos = pos / DVD_VIDEO_LB_LEN;
+      dev->ipos = (int)(pos / DVD_VIDEO_LB_LEN);
     }
   }
 
@@ -332,7 +333,7 @@ static int file_seek(dvd_input_t dev, int blocks)
     return pos;
   }
 
-  return (int) dev->ipos;
+  return dev->ipos;
 }
 
 /**
@@ -349,7 +350,8 @@ static int file_title(dvd_input_t dev UNUSED, int block UNUSED)
 static int file_read(dvd_input_t dev, void *buffer, int blocks,
                      int flags UNUSED)
 {
-  size_t len, bytes, blocks_read;
+  size_t len, bytes;
+  int blocks_read;
 
   len = (size_t)blocks * DVD_VIDEO_LB_LEN;
   bytes = 0;
@@ -382,12 +384,12 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks,
       if(ret < 0)
         return ret;
 
-      return (int) blocks_read;
+      return blocks_read;
     }
 
     len -= ret;
     bytes += ret;
-    blocks_read = bytes / DVD_VIDEO_LB_LEN;
+    blocks_read = (int)(bytes / DVD_VIDEO_LB_LEN);
   }
 
   dev->ipos += blocks_read;


=====================================
src/file/file_win32.c
=====================================
@@ -18,6 +18,7 @@
  */
 
 #include <io.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -73,7 +74,11 @@ static ssize_t file_read_default(void *file, char *buf, size_t size)
         return 0;
     }
 
-    return read(*(int*)file, buf, size);
+    /* Clamp oversized reads, callers must handle partial reads anyway. */
+    if (size > INT_MAX)
+        size = INT_MAX;
+
+    return read(*(int*)file, buf, (unsigned int)size);
 }
 
 static off64_t file_seek_default(void *file, off64_t offset, int whence)


=====================================
src/ifo_read.c
=====================================
@@ -2395,7 +2395,7 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
   if(tt_srpt->nr_of_srpts>info_length/sizeof(title_info_t)){
     Log1(ifop->ctx, "data mismatch: info_length (%zd)!= nr_of_srpts (%d). Truncating.",
             info_length/sizeof(title_info_t),tt_srpt->nr_of_srpts);
-    tt_srpt->nr_of_srpts=info_length/sizeof(title_info_t);
+    tt_srpt->nr_of_srpts=(uint16_t)(info_length/sizeof(title_info_t));
   }
 
   for(i =  0; i < tt_srpt->nr_of_srpts; i++) {
@@ -2979,7 +2979,7 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
      is to high, they high ones are never referenced though. */
   if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) {
     Log1(ifop->ctx, "C_ADT nr_of_vobs > available info entries");
-    c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t);
+    c_adt->nr_of_vobs = (uint16_t)(info_length / sizeof(cell_adr_t));
   }
 
   c_adt->cell_adr_table = calloc(1, info_length);



View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/42ace18eaf15e1c929ed06fbfd3b40fb409b8c8c...21cdfe9f23079277e0b4858b6ca37abd8d94ec7e

-- 
View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/42ace18eaf15e1c929ed06fbfd3b40fb409b8c8c...21cdfe9f23079277e0b4858b6ca37abd8d94ec7e
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the libdvdnav-devel mailing list