[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