[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