[vlc-commits] vlc_bits: add bs_error for truncated reads
Francois Cartegnie
git at videolan.org
Fri Jul 24 11:23:14 CEST 2020
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Jul 23 16:24:47 2020 +0200| [e4946a5b6cf24e7440a280bc443868ee679754be] | committer: Francois Cartegnie
vlc_bits: add bs_error for truncated reads
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e4946a5b6cf24e7440a280bc443868ee679754be
---
include/vlc_bits.h | 40 +++++++++++++++++++++++++++++++++++-----
test/src/misc/bits.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/include/vlc_bits.h b/include/vlc_bits.h
index deeca69cb3..f22b97c410 100644
--- a/include/vlc_bits.h
+++ b/include/vlc_bits.h
@@ -49,6 +49,7 @@ typedef struct bs_s
uint8_t i_left; /* i_count number of available bits */
bool b_read_only;
+ bool b_error;
bs_byte_callbacks_t cb;
void *p_priv;
@@ -95,6 +96,7 @@ static inline void bs_init_custom( bs_t *s, const void *p_data, size_t i_data,
s->p_end = s->p_start + i_data;
s->i_left = 0;
s->b_read_only = true;
+ s->b_error = false;
s->p_priv = priv;
s->cb = *cb;
}
@@ -128,6 +130,11 @@ static inline int bs_refill( bs_t *s )
return s->i_left > 0 ? 0 : 1;
}
+static inline bool bs_error( const bs_t *s )
+{
+ return s->b_error;
+}
+
static inline bool bs_eof( bs_t *s )
{
return bs_refill( s ) != 0;
@@ -149,17 +156,29 @@ static inline void bs_skip( bs_t *s, size_t i_count )
return;
if( bs_refill( s ) )
+ {
+ s->b_error = true;
return;
+ }
if( i_count > s->i_left )
{
i_count -= s->i_left;
s->i_left = 0;
- if( i_count / 8 )
- s->cb.pf_byte_forward( s, i_count / 8 );
+ size_t bytes = i_count / 8;
+ if( bytes && s->cb.pf_byte_forward( s, bytes ) != bytes )
+ {
+ s->b_error = true;
+ return;
+ }
i_count = i_count % 8;
- if( i_count > 0 && !bs_refill( s ) )
- s->i_left = 8 - i_count;
+ if( i_count > 0 )
+ {
+ if( !bs_refill( s ) )
+ s->i_left = 8 - i_count;
+ else
+ s->b_error = true;
+ }
}
else s->i_left -= i_count;
}
@@ -178,7 +197,10 @@ static inline uint32_t bs_read( bs_t *s, uint8_t i_count )
while( i_count > 0 )
{
if( bs_refill( s ) )
+ {
+ s->b_error = true;
break;
+ }
if( s->i_left > i_count )
{
@@ -214,7 +236,10 @@ static inline uint32_t bs_read( bs_t *s, uint8_t i_count )
static inline uint32_t bs_read1( bs_t *s )
{
if( bs_refill( s ) )
+ {
+ s->b_error = true;
return 0;
+ }
s->i_left--;
return ( *s->p >> s->i_left )&0x01;
}
@@ -227,7 +252,10 @@ static inline void bs_write( bs_t *s, uint8_t i_count, uint32_t i_bits )
while( i_count > 0 )
{
if( bs_refill( s ) )
+ {
+ s->b_error = true;
break;
+ }
i_count--;
@@ -268,7 +296,9 @@ static inline uint_fast32_t bs_read_ue( bs_t * bs )
{
unsigned i = 0;
- while( bs_read1( bs ) == 0 && bs->p < bs->p_end && i < 31 )
+ while( !bs->b_error &&
+ bs_read1( bs ) == 0 &&
+ bs->p < bs->p_end && i < 31 )
i++;
return (1U << i) - 1 + bs_read( bs, i );
diff --git a/test/src/misc/bits.c b/test/src/misc/bits.c
index df4e5c4923..f593a4dcca 100644
--- a/test/src/misc/bits.c
+++ b/test/src/misc/bits.c
@@ -60,29 +60,41 @@ static int run_tests( const struct testset *p_testsets,
bs_init( &bs, NULL, 0 );
test_assert( bs_remain(&bs), 0 );
test_assert( bs_pos(&bs), 0 );
+ test_assert( bs_eof(&bs), true );
+ test_assert( bs_error(&bs), false );
bs_init( &bs, p_testsets[TESTSET0].data, 0 );
test_assert( bs_remain(&bs), 0 );
test_assert( bs_pos(&bs), 0 );
+ bs_skip( &bs, 3 );
+ test_assert( bs_error(&bs), true );
bs_init( &bs, p_testsets[TESTSET0].data,
p_testsets[TESTSET0].count );
test_assert( bs_remain(&bs), 8 );
test_assert( bs_pos(&bs), 0 );
+ test_assert( bs_eof(&bs), false );
+ test_assert( bs_error(&bs), false );
bs_skip( &bs, 3 );
test_assert( bs_remain(&bs), 5 );
+ test_assert( bs_error(&bs), false );
test_assert( bs_pos(&bs), 3 );
bs_init( &bs, p_testsets[TESTSET1].data,
p_testsets[TESTSET1].count );
test_assert( bs_remain(&bs), 16 );
+ test_assert( bs_error(&bs), false );
bs_write( &bs, 1, 0 );
test_assert( bs_remain(&bs), 16 );
+ test_assert( bs_error(&bs), false );
+ test_assert( bs_eof(&bs), false );
bs_read1( &bs );
test_assert( bs_remain(&bs), 15 );
+ test_assert( bs_error(&bs), false );
+ test_assert( bs_eof(&bs), false );
test_assert( bs_pos(&bs), 1 );
bs_read( &bs, 7 );
@@ -92,10 +104,12 @@ static int run_tests( const struct testset *p_testsets,
bs_read1( &bs );
test_assert( bs_remain(&bs), 7 );
test_assert( bs_pos(&bs), 9 );
+ test_assert( bs_error(&bs), false );
bs_align( &bs );
test_assert( bs_remain(&bs), 0 );
test_assert( bs_pos(&bs), 16 );
+ test_assert( bs_error(&bs), false );
bs_init( &bs, p_testsets[TESTSET1].data,
p_testsets[TESTSET1].count );
@@ -106,9 +120,11 @@ static int run_tests( const struct testset *p_testsets,
p_testsets[TESTSET_EXPGOLOMB].count );
test_assert( bs_read_ue(&bs), 0x09 );
test_assert( bs_remain(&bs), 9 );
+ test_assert( bs_error(&bs), false );
test_assert( bs_read1(&bs), 1 );
test_assert( bs_read_se(&bs), 2 );
test_assert( bs_remain(&bs), 3 );
+ test_assert( bs_error(&bs), false );
test_assert( bs_read_se(&bs), -1 );
test_assert( bs_eof(&bs), !0 );
@@ -119,6 +135,7 @@ static int run_tests( const struct testset *p_testsets,
test_assert( bs_read( &bs, 4 ), 0x0E );
test_assert( bs_read( &bs, 8 ), 0xEF );
test_assert( bs_remain( &bs ), 4 );
+ test_assert( bs_error(&bs), false );
bs_init( &bs, p_testsets[TESTSET2].data,
p_testsets[TESTSET2].count );
@@ -132,6 +149,8 @@ static int run_tests( const struct testset *p_testsets,
test_assert( bs_read( &bs, 4 ), 0x0D );
test_assert( bs_read( &bs, 8 ), 0xEE );
test_assert( bs_remain( &bs ), 8 );
+ test_assert( bs_error(&bs), false );
+ test_assert( bs_eof(&bs), false );
/* */
bs_init( &bs, p_testsets[TESTSET2].data,
@@ -140,8 +159,10 @@ static int run_tests( const struct testset *p_testsets,
{
test_assert(bs_aligned( &bs ), !!(i%8 == 0));
test_assert(bs_remain( &bs ), 6*8 - i);
+ test_assert( bs_eof(&bs), false );
test_assert(bs_pos( &bs ), i);
bs_read( &bs, 1 );
+ test_assert( bs_error(&bs), false );
}
test_assert(bs_eof( &bs ), 1);
@@ -161,9 +182,11 @@ static int run_tests( const struct testset *p_testsets,
{
test_assert(bs_aligned( &bs ), !!(i%8 == 0));
test_assert(bs_remain( &bs ), 5*8 - i);
+ test_assert( bs_eof(&bs), false );
test_assert(bs_pos( &bs ), i);
bs_write(&bs, j % 4, (i % 2) ? 0xFF >> (8 - (j % 4)) : 0 );
i += j % 4;
+ test_assert( bs_error(&bs), i > 5*8 );
}
test_assert(bs_eof( &bs ), 1);
test_assert(!memcmp(buf, bufok, 5), true);
@@ -184,19 +207,31 @@ static int run_tests( const struct testset *p_testsets,
bs_init( &bs, p_testsets[TESTSET1].data, p_testsets[TESTSET1].count );
bs_read( &bs, 42 );
test_assert(bs_remain( &bs ), 0);
+ test_assert( bs_error(&bs), true );
+ test_assert( bs_eof(&bs), true );
test_assert(bs_pos( &bs ), 16);
bs_init( &bs, p_testsets[TESTSET1].data, p_testsets[TESTSET1].count );
bs_skip( &bs, 42 );
test_assert(bs_remain( &bs ), 0);
+ bs_skip( &bs, 2 );
+ test_assert( bs_error(&bs), false );
+ test_assert( bs_eof(&bs), false );
+ bs_skip( &bs, 40 );
+ test_assert( bs_error(&bs), true );
+ test_assert( bs_eof(&bs), true );
test_assert(bs_pos( &bs ), 16);
bs_init( &bs, p_testsets[TESTSET1].data, p_testsets[TESTSET1].count );
bs_skip( &bs, 8 );
test_assert(bs_remain( &bs ), 8);
+ test_assert( bs_error(&bs), false );
test_assert(bs_pos( &bs ), 8);
test_assert(bs_read( &bs, 8 + 2 ), 0x55 << 2);
test_assert(bs_remain( &bs ), 0);
+ test_assert(bs_read( &bs, 8 + 2 ), 0x55 << 2); /* truncated read */
+ test_assert( bs_error(&bs), true );
+ test_assert( bs_eof(&bs), true );
test_assert(bs_pos( &bs ), 16);
return 0;
@@ -205,6 +240,9 @@ static int run_tests( const struct testset *p_testsets,
static size_t bs_skipeven_bytes_forward( bs_t *s, size_t i_count )
{
+ if( s->p_start == NULL || (s->p_start + 1) > s->p_end )
+ return 0;
+
if( s->p == NULL )
{
s->p = s->p_start;
More information about the vlc-commits
mailing list