diff --git a/libtransmission/peer-msgs.c b/libtransmission/peer-msgs.c index 08d5a1258..8918c438b 100644 --- a/libtransmission/peer-msgs.c +++ b/libtransmission/peer-msgs.c @@ -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; } diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 95a435655..fc5ed0133 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -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; diff --git a/libtransmission/utils.c b/libtransmission/utils.c index 86c386da3..1c183f6ed 100644 --- a/libtransmission/utils.c +++ b/libtransmission/utils.c @@ -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> 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