#872: crash in bitfield code when loading resume files

This commit is contained in:
Charles Kerr 2008-04-13 14:29:11 +00:00
parent f467beedb5
commit c8c84d6bd1
9 changed files with 144 additions and 46 deletions

View File

@ -28,6 +28,7 @@ libtransmission_a_SOURCES = \
ptrarray.c \
publish.c \
ratecontrol.c \
resume.c \
session.c \
stats.c \
torrent.c \
@ -64,6 +65,7 @@ noinst_HEADERS = \
ptrarray.h \
publish.h \
ratecontrol.h \
resume.h \
session.h \
stats.h \
torrent.h \

View File

@ -237,19 +237,20 @@ const tr_bitfield * tr_cpBlockBitfield( const tr_completion * cp )
return cp->blockBitfield;
}
void
tr_errno
tr_cpBlockBitfieldSet( tr_completion * cp, tr_bitfield * bitfield )
{
tr_block_index_t i;
assert( cp != NULL );
assert( bitfield != NULL );
if( !cp || !bitfield || ( bitfield->len != cp->blockBitfield->len ) )
return TR_ERROR_ASSERT;
tr_cpReset( cp );
for( i=0; i < cp->tor->blockCount; ++i )
if( tr_bitfieldHas( bitfield, i ) )
tr_cpBlockAdd( cp, i );
return 0;
}
float

View File

@ -53,7 +53,7 @@ void tr_cpPieceRem( tr_completion *, tr_piece_index_t piece );
/* Blocks */
int tr_cpBlockIsComplete( const tr_completion *, tr_block_index_t block );
void tr_cpBlockAdd( tr_completion *, tr_block_index_t block );
void tr_cpBlockBitfieldSet( tr_completion *, struct tr_bitfield * );
tr_errno tr_cpBlockBitfieldSet( tr_completion *, struct tr_bitfield * );
float tr_cpPercentBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece );
int tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece );

View File

@ -56,6 +56,7 @@
#include "fastresume.h"
#include "peer-mgr.h"
#include "platform.h"
#include "resume.h" /* TR_FR_ bitwise enum */
#include "torrent.h"
#include "utils.h"
@ -115,7 +116,7 @@ enum
#define FR_MTIME_LEN( t ) \
( sizeof(tr_time_t) * (t)->info.fileCount )
#define FR_BLOCK_BITFIELD_LEN( t ) \
( ( (t)->blockCount + 7 ) / 8 )
( ( (t)->blockCount + 7u ) / 8u )
#define FR_PROGRESS_LEN( t ) \
( FR_MTIME_LEN( t ) + FR_BLOCK_BITFIELD_LEN( t ) )
#define FR_SPEED_LEN (2 * (sizeof(uint16_t) + sizeof(uint8_t) ) )
@ -426,9 +427,12 @@ parseProgress( tr_torrent * tor,
memset( &bitfield, 0, sizeof bitfield );
bitfield.len = FR_BLOCK_BITFIELD_LEN( tor );
bitfield.bits = (uint8_t*) walk;
tr_cpBlockBitfieldSet( tor->completion, &bitfield );
ret = TR_FR_PROGRESS;
if( !tr_cpBlockBitfieldSet( tor->completion, &bitfield ) )
ret = TR_FR_PROGRESS;
else {
tr_torrentUncheck( tor );
tr_tordbg( tor, "Torrent needs to be verified" );
}
}
/* the files whose mtimes are wrong,

View File

@ -27,20 +27,6 @@
void tr_fastResumeSave( const tr_torrent * tor );
enum
{
TR_FR_DOWNLOADED = (1<<0),
TR_FR_UPLOADED = (1<<1),
TR_FR_CORRUPT = (1<<2),
TR_FR_PEERS = (1<<3),
TR_FR_PROGRESS = (1<<4),
TR_FR_PRIORITY = (1<<5),
TR_FR_SPEEDLIMIT = (1<<6),
TR_FR_RUN = (1<<7),
TR_FR_DESTINATION = (1<<8),
TR_FR_MAX_PEERS = (1<<9)
};
/**
* Returns a bitwise-or'ed set of the data loaded from fastresume
*/

74
libtransmission/resume.c Normal file
View File

@ -0,0 +1,74 @@
/*
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*
* $Id:$
*/
#include <string.h>
#include <unistd.h> /* unlink */
#include "transmission.h"
#include "fastresume.h"
#include "platform.h" /* tr_getResumeDir */
#include "resume.h"
#include "torrent.h"
#include "utils.h" /* tr_buildPath */
static void
getResumeFilename( char * buf, size_t buflen, const tr_torrent * tor )
{
const char * dir = tr_getResumeDir( tor->handle );
char base[4096];
snprintf( base, sizeof( base ), "%s.%10.10s.resume", tor->info.name, tor->info.hashString );
tr_buildPath( buf, buflen, dir, base, NULL );
fprintf( stderr, "filename is [%s]\n", buf );
}
uint64_t
tr_torrentLoadResume( tr_torrent * tor,
uint64_t fieldsToLoad,
const tr_ctor * ctor )
{
uint64_t fieldsLoaded = 0;
uint8_t * content;
size_t contentLen;
char filename[MAX_PATH_LENGTH];
getResumeFilename( filename, sizeof( filename ), tor );
content = tr_loadFile( filename, &contentLen );
if( content )
{
tr_free( content );
}
else
{
fieldsLoaded = tr_fastResumeLoad( tor, fieldsToLoad, ctor );
}
return fieldsLoaded;
}
void
tr_torrentSaveResume( const tr_torrent * tor )
{
char filename[MAX_PATH_LENGTH];
getResumeFilename( filename, sizeof( filename ), tor );
/* (temporary) */
tr_fastResumeSave( tor );
}
void
tr_torrentRemoveResume( const tr_torrent * tor )
{
char filename[MAX_PATH_LENGTH];
getResumeFilename( filename, sizeof( filename ), tor );
unlink( filename );
tr_fastResumeRemove( tor );
}

41
libtransmission/resume.h Normal file
View File

@ -0,0 +1,41 @@
/*
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*
* $Id:$
*/
#ifndef TR_RESUME_H
#define TR_RESUME_H
enum
{
TR_FR_DOWNLOADED = (1<<0),
TR_FR_UPLOADED = (1<<1),
TR_FR_CORRUPT = (1<<2),
TR_FR_PEERS = (1<<3),
TR_FR_PROGRESS = (1<<4),
TR_FR_PRIORITY = (1<<5),
TR_FR_SPEEDLIMIT = (1<<6),
TR_FR_RUN = (1<<7),
TR_FR_DESTINATION = (1<<8),
TR_FR_MAX_PEERS = (1<<9)
};
/**
* Returns a bitwise-or'ed set of the loaded resume data
*/
uint64_t tr_torrentLoadResume( tr_torrent * tor,
uint64_t fieldsToLoad,
const tr_ctor * ctor );
void tr_torrentSaveResume( const tr_torrent * tor );
void tr_torrentRemoveResume( const tr_torrent * tor );
#endif

View File

@ -29,7 +29,7 @@
#include "bencode.h"
#include "completion.h"
#include "crypto.h" /* for tr_sha1 */
#include "fastresume.h"
#include "resume.h"
#include "fdlimit.h" /* tr_fdFileClose */
#include "metainfo.h"
#include "peer-mgr.h"
@ -353,7 +353,7 @@ torrentRealInit( tr_handle * h,
tor->checkedPieces = tr_bitfieldNew( tor->info.pieceCount );
tr_torrentUncheck( tor );
loaded = tr_fastResumeLoad( tor, ~0, ctor );
loaded = tr_torrentLoadResume( tor, ~0, ctor );
doStart = tor->isRunning;
tor->isRunning = 0;
@ -457,16 +457,6 @@ tr_torrentNew( tr_handle * handle,
return tor;
}
/***
****
***/
static void
saveFastResumeNow( tr_torrent * tor )
{
tr_fastResumeSave( tor );
}
/**
***
**/
@ -476,7 +466,7 @@ tr_torrentSetFolder( tr_torrent * tor, const char * path )
{
tr_free( tor->destination );
tor->destination = tr_strdup( path );
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
}
const char*
@ -824,7 +814,7 @@ tr_torrentRemoveSaved( tr_torrent * tor )
{
tr_metainfoRemoveSaved( tor->handle, tor->info.hashString );
tr_fastResumeRemove( tor );
tr_torrentRemoveResume( tor );
}
/***
@ -921,7 +911,7 @@ checkAndStartImpl( void * vtor )
*tor->errorString = '\0';
tr_torrentResetTransferStats( tor );
tor->cpStatus = tr_cpGetStatus( tor->completion );
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
tor->startDate = tr_date( );
tr_trackerStart( tor->tracker );
tr_peerMgrStartTorrent( tor->handle->peerMgr, tor->info.hash );
@ -942,7 +932,7 @@ tr_torrentStart( tr_torrent * tor )
if( !tor->isRunning )
{
tr_fastResumeLoad( tor, TR_FR_PROGRESS, NULL );
tr_torrentLoadResume( tor, TR_FR_PROGRESS, NULL );
tor->isRunning = 1;
tr_verifyAdd( tor, checkAndStartCB );
}
@ -999,7 +989,7 @@ tr_torrentStop( tr_torrent * tor )
tr_globalLock( tor->handle );
if( !tor->isDeleting )
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
tor->isRunning = 0;
tr_runInEventThread( tor->handle, stopTorrent, tor );
@ -1010,7 +1000,7 @@ static void
closeTorrent( void * vtor )
{
tr_torrent * tor = vtor;
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
tor->isRunning = 0;
stopTorrent( tor );
if( tor->isDeleting )
@ -1112,7 +1102,7 @@ tr_torrentRecheckCompleteness( tr_torrent * tor )
if( recentChange && ( cpStatus == TR_CP_COMPLETE ) )
tr_trackerCompleted( tor->tracker );
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
}
tr_torrentUnlock( tor );
@ -1158,7 +1148,7 @@ tr_torrentSetFilePriorities( tr_torrent * tor,
for( i=0; i<fileCount; ++i )
tr_torrentInitFilePriority( tor, files[i], priority );
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
tr_torrentUnlock( tor );
}
@ -1285,7 +1275,7 @@ tr_torrentSetFileDLs ( tr_torrent * tor,
{
tr_torrentLock( tor );
tr_torrentInitFileDLs( tor, files, fileCount, doDownload );
saveFastResumeNow( tor );
tr_torrentSaveResume( tor );
tr_torrentUnlock( tor );
}

View File

@ -14,7 +14,7 @@
#include "transmission.h"
#include "completion.h"
#include "fastresume.h" /* tr_fastResumeSave() */
#include "resume.h" /* tr_torrentSaveResume() */
#include "inout.h"
#include "list.h"
#include "platform.h"
@ -133,7 +133,7 @@ verifyThreadFunc( void * unused UNUSED )
if( !stopCurrent )
{
tr_fastResumeSave( tor );
tr_torrentSaveResume( tor );
fireCheckDone( tor, currentNode.verify_done_cb );
}
}