[libbluray-devel] [Git][videolan/libbluray][master] 13 commits: bits: check bs_read() bits count

Petri Hintukainen (@hpi) gitlab at videolan.org
Thu Aug 6 15:10:10 UTC 2026



Petri Hintukainen pushed to branch master at VideoLAN / libbluray


Commits:
166ffc08 by Petri Hintukainen at 2026-08-06T17:23:03+03:00
bits: check bs_read() bits count

Return value is uint32_t

- - - - -
fe78b158 by Petri Hintukainen at 2026-08-06T17:23:08+03:00
bits: factorize refill

- - - - -
9adf622c by Petri Hintukainen at 2026-08-06T17:26:05+03:00
bits: check for failed seek/read in refill

- - - - -
ad0c4472 by Petri Hintukainen at 2026-08-06T17:32:05+03:00
Use correct angle.

title->angle may be different from clip->nagle (unchecked or too large).

- - - - -
e47acdb7 by Petri Hintukainen at 2026-08-06T17:34:53+03:00
nav_title_open(): check if angle is in valid range

Same check is in nav_set_angle()

- - - - -
45f95490 by Petri Hintukainen at 2026-08-06T17:43:02+03:00
clpi_lookup_spn(): protect against negative map index

- - - - -
8f311271 by Petri Hintukainen at 2026-08-06T17:43:40+03:00
clpi_access_point(): protect against negative map index

- - - - -
3357d079 by Petri Hintukainen at 2026-08-06T17:48:29+03:00
_fill_mark(): sanitize clip_ref

Reported-by: Dominik Riedweg <domi.riedweg at gmail.com>

- - - - -
d9b92792 by Petri Hintukainen at 2026-08-06T17:50:26+03:00
Cosmetics

- - - - -
28bc30ad by Petri Hintukainen at 2026-08-06T17:52:24+03:00
nav_mark_search(): fix mark range check

- - - - -
8491b2a2 by Petri Hintukainen at 2026-08-06T17:53:02+03:00
nav_chapter_search(): fix chapter range check

- - - - -
9bf4df65 by Petri Hintukainen at 2026-08-06T18:02:55+03:00
_decode_rle(): avoid signed integer overflow

Triggered only with ~ 64kx64k images

- - - - -
70ba7d4b by Petri Hintukainen at 2026-08-06T18:03:53+03:00
_decode_rle(): limit initial allocation size

- - - - -


5 changed files:

- src/libbluray/bdnav/clpi_parse.c
- src/libbluray/bdnav/navigation.c
- src/libbluray/decoders/pg_decode.c
- src/util/bits.c
- src/util/macro.h


Changes:

=====================================
src/libbluray/bdnav/clpi_parse.c
=====================================
@@ -549,6 +549,9 @@ done:
         }
         jj = entry->coarse[ii].ref_ep_fine_id;
     }
+    if (jj < 0) {
+        jj = 0;
+    }
     spn = (entry->coarse[ii].spn_ep & ~0x1FFFF) + entry->fine[jj].spn_ep;
     return spn;
 }
@@ -606,7 +609,9 @@ clpi_access_point(const CLPI_CL *cl, uint32_t pkt, int next, int angle_change, u
         ii++;
         jj = 0;
     } else if (spn != pkt && !next) {
-        jj--;
+        if (jj > 0) {
+            jj--;
+        }
     }
     if (ii == entry->num_ep_coarse) {
         *time = 0;


=====================================
src/libbluray/bdnav/navigation.c
=====================================
@@ -546,14 +546,21 @@ _fill_mark(const NAV_TITLE *title, NAV_MARK *mark, int entry)
 
     mark->mark_type = plm->mark_type;
     mark->clip_ref = plm->play_item_ref;
-    clip = &title->clip_list.clip[mark->clip_ref];
-    if (clip->cl != NULL && mark->clip_ref < title->pl->list_count) {
-        mark->clip_pkt = clpi_lookup_spn(clip->cl, plm->time, 1,
-            title->pl->play_item[mark->clip_ref].clip[title->angle].stc_id);
-    } else {
-        mark->clip_pkt = clip->start_pkt;
+    if (mark->clip_ref >= title->clip_list.count) {
+        BD_DEBUG(DBG_NAV | DBG_CRIT, "_fill_mark(): invalid play_item_ref %d\n", plm->play_item_ref);
+        mark->clip_ref = 0;
+    }
+
+    if (title->clip_list.count) {
+        clip = &title->clip_list.clip[mark->clip_ref];
+        if (clip->cl != NULL && mark->clip_ref < title->pl->list_count) {
+            mark->clip_pkt = clpi_lookup_spn(clip->cl, plm->time, 1,
+                    title->pl->play_item[mark->clip_ref].clip[clip->angle].stc_id);
+        } else {
+            mark->clip_pkt = clip->start_pkt;
+        }
+        mark->title_pkt = clip->title_pkt + mark->clip_pkt - clip->start_pkt;
     }
-    mark->title_pkt = clip->title_pkt + mark->clip_pkt - clip->start_pkt;
     mark->clip_time = plm->time;
 
     // Calculate start of mark relative to beginning of playlist
@@ -743,6 +750,10 @@ NAV_TITLE* nav_title_open(BD_DISC *disc, const char *playlist, unsigned angle)
     strncpy(title->name, playlist, 11);
     title->name[10] = '\0';
     title->angle_count = 0;
+    if (angle > 8) {
+        // invalid angle
+        angle = 0;
+    }
     title->angle = angle;
     title->pl = mpls_get(disc, playlist);
     if (title->pl == NULL) {
@@ -838,7 +849,7 @@ const NAV_CLIP* nav_chapter_search(const NAV_TITLE *title, unsigned chapter,
         return NULL;
     }
 
-    if (chapter > title->chap_list.count) {
+    if (chapter >= title->chap_list.count) {
         clip = &title->clip_list.clip[0];
         *clip_pkt = clip->start_pkt;
         *out_pkt = clip->title_pkt;
@@ -885,7 +896,7 @@ const NAV_CLIP* nav_mark_search(const NAV_TITLE *title, unsigned mark,
         return NULL;
     }
 
-    if (mark > title->mark_list.count) {
+    if (mark >= title->mark_list.count) {
         clip = &title->clip_list.clip[0];
         *clip_pkt = clip->start_pkt;
         *out_pkt = clip->title_pkt;


=====================================
src/libbluray/decoders/pg_decode.c
=====================================
@@ -28,6 +28,7 @@
 #include "util/logging.h"
 #include "util/bits.h"
 
+#include <inttypes.h>
 #include <string.h>
 #include <stdlib.h>
 
@@ -122,13 +123,16 @@ int pg_decode_palette(BITBUFFER *bb, BD_PG_PALETTE *p)
 static int _decode_rle(BITBUFFER *bb, BD_PG_OBJECT *p)
 {
     BD_PG_RLE_ELEM *tmp;
-    int pixels_left = p->width * p->height;
+    int64_t pixels_left = (int64_t)p->width * p->height;
+    int rle_size        = (int)(pixels_left / 4);
     int num_rle     = 0;
-    int rle_size    = p->width * p->height / 4;
 
     if (rle_size < 1)
         rle_size = 1;
 
+    if (rle_size > 65536)
+        rle_size = 65536;
+
     tmp = refcnt_realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM), NULL);
     if (!tmp) {
         BD_DEBUG(DBG_DECODE | DBG_CRIT, "pg_decode_object(): realloc failed\n");
@@ -163,7 +167,7 @@ static int _decode_rle(BITBUFFER *bb, BD_PG_OBJECT *p)
         pixels_left -= len;
 
         if (pixels_left < 0) {
-            BD_DEBUG(DBG_DECODE, "pg_decode_object(): too many pixels (%d)\n", -pixels_left);
+            BD_DEBUG(DBG_DECODE, "pg_decode_object(): too many pixels (%" PRId64 ")\n", -pixels_left);
             return 0;
         }
 
@@ -180,7 +184,7 @@ static int _decode_rle(BITBUFFER *bb, BD_PG_OBJECT *p)
     }
 
     if (pixels_left > 0) {
-        BD_DEBUG(DBG_DECODE, "pg_decode_object(): missing %d pixels\n", pixels_left);
+        BD_DEBUG(DBG_DECODE, "pg_decode_object(): missing %" PRId64 " pixels\n", pixels_left);
         return 0;
     }
 


=====================================
src/util/bits.c
=====================================
@@ -28,6 +28,7 @@
 
 #include "file/file.h"
 #include "util/logging.h"
+#include "util/macro.h"
 
 #include <stdio.h>  // SEEK_*
 
@@ -44,7 +45,7 @@ void bb_init( BITBUFFER *bb, const uint8_t *p_data, size_t i_data )
     bb->i_left  = 8;
 }
 
-static int _bs_read( BITSTREAM *bs)
+static BD_USED int _bs_read( BITSTREAM *bs)
 {
     int result = 0;
     int64_t got;
@@ -62,7 +63,7 @@ static int _bs_read( BITSTREAM *bs)
     return result;
 }
 
-static int _bs_read_at( BITSTREAM *bs, int64_t off )
+static BD_USED int _bs_read_at( BITSTREAM *bs, int64_t off )
 {
     if (file_seek(bs->fp, off, SEEK_SET) < 0) {
         BD_DEBUG(DBG_FILE | DBG_CRIT, "bs_read(): seek failed\n");
@@ -73,6 +74,19 @@ static int _bs_read_at( BITSTREAM *bs, int64_t off )
     return _bs_read(bs);
 }
 
+static void _bs_refill( BITSTREAM *bs )
+{
+    int64_t pos = bs->pos + (bs->bb.p - bs->bb.p_start);
+    int left = bs->bb.i_left;
+
+    if (_bs_read_at(bs, pos) < 0) {
+        /* seek failed: treat as EOF */
+        bs->size = 0;
+        bb_init(&bs->bb, bs->buf, 0);
+    }
+    bs->bb.i_left = left;
+}
+
 int bs_init( BITSTREAM *bs, BD_FILE_H *fp )
 {
     int64_t size = file_size(fp);;
@@ -184,6 +198,11 @@ uint32_t bb_read( BITBUFFER *bb, int i_count )
     int      i_shr;
     uint32_t i_result = 0;
 
+    if (i_count > 32) {
+        BD_ASSERT(i_count <= 32);
+        i_count = 32;
+    }
+
     while( i_count > 0 ) {
 
         if( bb->p >= bb->p_end ) {
@@ -214,16 +233,16 @@ uint32_t bb_read( BITBUFFER *bb, int i_count )
 
 uint32_t bs_read( BITSTREAM *bs, int i_count )
 {
-    int left;
-    int bytes = (i_count + 7) >> 3;
+    int bytes;
+
+    if (i_count > 32) {
+        BD_ASSERT(i_count <= 32);
+        i_count = 32;
+    }
+    bytes = (i_count + 7) >> 3;
 
     if (bs->bb.p + bytes >= bs->bb.p_end) {
-        bs->pos = bs->pos + (bs->bb.p - bs->bb.p_start);
-        left = bs->bb.i_left;
-        file_seek(bs->fp, bs->pos, SEEK_SET);
-        bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
-        bb_init(&bs->bb, bs->buf, bs->size);
-        bs->bb.i_left = left;
+        _bs_refill(bs);
     }
     return bb_read(&bs->bb, i_count);
 }
@@ -241,16 +260,10 @@ void bb_skip( BITBUFFER *bb, size_t i_count )
 
 void bs_skip( BITSTREAM *bs, size_t i_count )
 {
-    int left;
     size_t bytes = (i_count + 7) >> 3;
 
     if (bs->bb.p + bytes >= bs->bb.p_end) {
-        bs->pos = bs->pos + (bs->bb.p - bs->bb.p_start);
-        left = bs->bb.i_left;
-        file_seek(bs->fp, bs->pos, SEEK_SET);
-        bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
-        bb_init(&bs->bb, bs->buf, bs->size);
-        bs->bb.i_left = left;
+        _bs_refill(bs);
     }
     bb_skip(&bs->bb, i_count);
 }


=====================================
src/util/macro.h
=====================================
@@ -33,6 +33,13 @@
 
 #define BD_MAX_SSIZE ((int64_t)(((size_t)-1)>>1))
 
+#define BD_ASSERT(p)                                      \
+  do {                                                    \
+    if (!(p)) {                                           \
+      BD_DEBUG(DBG_CRIT, "assertion failed: '%s'\n", #p); \
+    }                                                     \
+  } while (0)
+
 /*
  * automatic cast from void* (malloc/calloc/realloc)
  */



View it on GitLab: https://code.videolan.org/videolan/libbluray/-/compare/64bcf07f47452fb4724eef3febc40aaf7720d42a...70ba7d4bf7262a7e7fb20f428d17a287e532f62e

-- 
View it on GitLab: https://code.videolan.org/videolan/libbluray/-/compare/64bcf07f47452fb4724eef3febc40aaf7720d42a...70ba7d4bf7262a7e7fb20f428d17a287e532f62e
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 libbluray-devel mailing list