harden the bitfield handling to handle corrupt messages from peers. This is in response to Ryoujin's crash report in the forums (http://forum.transmissionbt.com/viewtopic.php?p=20414#20414)

This commit is contained in:
Charles Kerr
2008-03-02 23:44:34 +00:00
parent 6b1001600b
commit 24e05bf3fb
4 changed files with 59 additions and 21 deletions
+8 -4
View File
@@ -1311,10 +1311,12 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
case BT_HAVE:
tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
dbgmsg( msgs, "got Have: %u", ui32 );
tr_bitfieldAdd( msgs->info->have, ui32 );
if( tr_bitfieldAdd( msgs->info->have, ui32 ) )
fireError( msgs, TR_ERROR_PEER_MESSAGE );
/* If this is a fast-allowed piece for this peer, mark it as normal now */
if( msgs->clientAllowedPieces != NULL && tr_bitfieldHas( msgs->clientAllowedPieces, ui32 ) )
tr_bitfieldRem( msgs->clientAllowedPieces, ui32 );
if( tr_bitfieldRem( msgs->clientAllowedPieces, ui32 ) )
fireError( msgs, TR_ERROR_PEER_MESSAGE );
updatePeerProgress( msgs );
tr_rcTransferred( msgs->torrent->swarmspeed, msgs->torrent->info.pieceSize );
break;
@@ -1365,7 +1367,8 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
dbgmsg( msgs, "Got a BT_SUGGEST" );
tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
if( tr_cpPieceIsComplete( msgs->torrent->completion, ui32 ) )
tr_bitfieldAdd( msgs->clientSuggestedPieces, ui32 );
if( tr_bitfieldAdd( msgs->clientSuggestedPieces, ui32 ) )
fireError( msgs, TR_ERROR_PEER_MESSAGE );
break;
}
@@ -1397,7 +1400,8 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
case BT_ALLOWED_FAST: {
dbgmsg( msgs, "Got a BT_ALLOWED_FAST" );
tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
tr_bitfieldAdd( msgs->clientAllowedPieces, ui32 );
if( tr_bitfieldAdd( msgs->clientAllowedPieces, ui32 ) )
fireError( msgs, TR_ERROR_PEER_MESSAGE );
break;
}
+4 -1
View File
@@ -716,7 +716,10 @@ typedef enum tr_errno
/* tracker errors */
TR_ERROR_TC_ERROR = -300,
TR_ERROR_TC_WARNING
TR_ERROR_TC_WARNING,
/* peer errors */
TR_ERROR_PEER_MESSAGE = -400
}
tr_errno;
+43 -12
View File
@@ -541,6 +541,14 @@ tr_errorString( int code )
case TR_ERROR_IO_OTHER:
return "Generic I/O error";
case TR_ERROR_TC_ERROR:
return "Tracker error";
case TR_ERROR_TC_WARNING:
return "Tracker warning";
case TR_ERROR_PEER_MESSAGE:
return "Peer sent a bad message";
default:
return "Unknown error";
}
@@ -673,49 +681,72 @@ int
tr_bitfieldHas( const tr_bitfield * bitfield, size_t nth )
{
static const uint8_t ands[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
return bitfield!=NULL && (bitfield->bits[nth>>3u] & ands[nth&7u] );
const size_t i = nth >> 3u;
return ( bitfield != NULL )
&& ( bitfield->bits != NULL )
&& ( i < bitfield->len )
&& ( ( bitfield->bits[i] & ands[nth&7u] ) != 0 );
}
void
int
tr_bitfieldAdd( tr_bitfield * bitfield, size_t nth )
{
static const uint8_t ands[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
bitfield->bits[nth>>3u] |= ands[nth&7u];
const size_t i = nth >> 3u;
assert( bitfield != NULL );
assert( bitfield->bits != NULL );
if( i >= bitfield->len )
return -1;
bitfield->bits[i] |= ands[nth&7u];
assert( tr_bitfieldHas( bitfield, nth ) );
return 0;
}
void
int
tr_bitfieldAddRange( tr_bitfield * bitfield,
size_t begin,
size_t end )
{
/* TODO: there are faster ways to do this */
int err = 0;
size_t i;
for( i=begin; i<end; ++i )
tr_bitfieldAdd( bitfield, i );
if(( err = tr_bitfieldAdd( bitfield, i )))
break;
return err;
}
void
int
tr_bitfieldRem( tr_bitfield * bitfield,
size_t nth )
{
static const uint8_t rems[8] = { 127, 191, 223, 239, 247, 251, 253, 254 };
const size_t i = nth >> 3u;
if( bitfield != NULL )
bitfield->bits[nth>>3u] &= rems[nth&7u];
assert( bitfield != NULL );
assert( bitfield->bits != NULL );
if( i >= bitfield->len )
return -1;
bitfield->bits[i] &= rems[nth&7u];
assert( !tr_bitfieldHas( bitfield, nth ) );
return 0;
}
void
int
tr_bitfieldRemRange ( tr_bitfield * b,
size_t begin,
size_t end )
{
/* TODO: there are faster ways to do this */
int err = 0;
size_t i;
for( i=begin; i<end; ++i )
tr_bitfieldRem( b, i );
if(( err = tr_bitfieldRem( b, i )))
break;
return err;
}
tr_bitfield*
+4 -4
View File
@@ -158,10 +158,10 @@ tr_bitfield* tr_bitfieldDup( const tr_bitfield* );
void tr_bitfieldFree( tr_bitfield*);
void tr_bitfieldClear( tr_bitfield* );
void tr_bitfieldAdd( tr_bitfield*, size_t bit );
void tr_bitfieldRem( tr_bitfield*, size_t bit );
void tr_bitfieldAddRange( tr_bitfield *, size_t begin, size_t end );
void tr_bitfieldRemRange ( tr_bitfield*, size_t begin, size_t end );
int tr_bitfieldAdd( tr_bitfield*, size_t bit );
int tr_bitfieldRem( tr_bitfield*, size_t bit );
int tr_bitfieldAddRange( tr_bitfield *, size_t begin, size_t end );
int tr_bitfieldRemRange ( tr_bitfield*, size_t begin, size_t end );
int tr_bitfieldHas( const tr_bitfield*, size_t bit );
int tr_bitfieldIsEmpty( const tr_bitfield* );