]> granicus.if.org Git - transmission/commitdiff
#4506 'crash from memory corruption somewhere called from tr_handshakeDone()' --...
authorJordan Lee <jordan@transmissionbt.com>
Wed, 28 Sep 2011 16:07:35 +0000 (16:07 +0000)
committerJordan Lee <jordan@transmissionbt.com>
Wed, 28 Sep 2011 16:07:35 +0000 (16:07 +0000)
libtransmission/bitfield.c

index d09257986ab125db1b3c80590d5efa52396d510d..db1682b9b9756abadd7736e5a687c6fefec7d6eb 100644 (file)
@@ -170,25 +170,27 @@ tr_bitfieldGetRaw( const tr_bitfield * b, size_t * byte_count )
 
     assert( b->bit_count > 0 );
 
-    if( b->alloc_count )
+    if( b->alloc_count ) {
+        assert( b->alloc_count <= n );
         memcpy( bits, b->bits, b->alloc_count );
-    else if( tr_bitfieldHasAll( b ) )
+    } else if( tr_bitfieldHasAll( b ) ) {
         set_all_true( bits, b->bit_count );
+    }
 
     *byte_count = n;
     return bits;
 }
 
 static void
-tr_bitfieldEnsureBitsAlloced( tr_bitfield * b, size_t nth )
+tr_bitfieldEnsureBitsAlloced( tr_bitfield * b, size_t n )
 {
     size_t bytes_needed;
     const bool has_all = tr_bitfieldHasAll( b );
 
     if( has_all )
-        bytes_needed = get_bytes_needed( MAX( nth, b->true_count ) + 1 );
+        bytes_needed = get_bytes_needed( MAX( n, b->true_count ) );
     else
-        bytes_needed = get_bytes_needed( nth + 1 );
+        bytes_needed = get_bytes_needed( n );
 
     if( b->alloc_count < bytes_needed )
     {
@@ -201,6 +203,13 @@ tr_bitfieldEnsureBitsAlloced( tr_bitfield * b, size_t nth )
     }
 }
 
+static void
+tr_bitfieldEnsureNthBitAlloced( tr_bitfield * b, size_t nth )
+{
+    /* count is zero-based, so we need to allocate nth+1 bits before setting the nth */
+    tr_bitfieldEnsureBitsAlloced( b, nth + 1 );
+}
+
 static void
 tr_bitfieldFreeArray( tr_bitfield * b )
 {
@@ -332,7 +341,7 @@ tr_bitfieldAdd( tr_bitfield * b, size_t nth )
 {
     if( !tr_bitfieldHas( b, nth ) )
     {
-        tr_bitfieldEnsureBitsAlloced( b, nth );
+        tr_bitfieldEnsureNthBitAlloced( b, nth );
         b->bits[nth >> 3u] |= ( 0x80 >> ( nth & 7u ) );
         tr_bitfieldIncTrueCount( b, 1 );
     }
@@ -358,7 +367,7 @@ tr_bitfieldAddRange( tr_bitfield * b, size_t begin, size_t end )
     eb = end >> 3;
     em = 0xff << ( 7 - ( end & 7 ) );
 
-    tr_bitfieldEnsureBitsAlloced( b, end );
+    tr_bitfieldEnsureNthBitAlloced( b, end );
     if( sb == eb )
     {
         b->bits[sb] |= ( sm & em );
@@ -381,7 +390,7 @@ tr_bitfieldRem( tr_bitfield * b, size_t nth )
 
     if( !tr_bitfieldHas( b, nth ) )
     {
-        tr_bitfieldEnsureBitsAlloced( b, nth );
+        tr_bitfieldEnsureNthBitAlloced( b, nth );
         b->bits[nth >> 3u] &= ( 0xff7f >> ( nth & 7u ) );
         tr_bitfieldIncTrueCount( b, -1 );
     }
@@ -408,7 +417,7 @@ tr_bitfieldRemRange( tr_bitfield * b, size_t begin, size_t end )
     eb = end >> 3;
     em = ~( 0xff << ( 7 - ( end & 7 ) ) );
 
-    tr_bitfieldEnsureBitsAlloced( b, end );
+    tr_bitfieldEnsureNthBitAlloced( b, end );
     if( sb == eb )
     {
         b->bits[sb] &= ( sm | em );