Bug: fread_mobile function has several problems
Danger: Critical - The most severe problem leads to crashes during pfile loads
Found by: Remcon
Fixed by: Remcon/Samson
---
save.c, fread_mobile
Replace the entire function with this new one:
CHAR_DATA *fread_mobile( FILE * fp )
{
CHAR_DATA *mob = NULL;
const char *word;
bool fMatch;
int inroom = 0;
ROOM_INDEX_DATA *pRoomIndex = NULL;
word = ( feof( fp ) ? "EndMobile" : fread_word( fp ) );
if( word[0] == '\0' )
{
bug( "%s: EOF encountered reading file!", __FUNCTION__ );
word = "EndMobile";
}
if( !strcmp( word, "Vnum" ) )
{
int vnum;
vnum = fread_number( fp );
mob = create_mobile( get_mob_index( vnum ) );
if( !mob )
{
for( ;; )
{
word = ( feof( fp ) ? "EndMobile" : fread_word( fp ) );
if( word[0] == '\0' )
{
bug( "%s: EOF encountered reading file!", __FUNCTION__ );
word = "EndMobile";
}
/*
* So we don't get so many bug messages when something messes up
* * --Shaddai
*/
if( !strcmp( word, "EndMobile" ) )
break;
}
bug( "%s: No index data for vnum %d", __FUNCTION__, vnum );
return NULL;
}
}
else
{
for( ;; )
{
word = ( feof( fp ) ? "EndMobile" : fread_word( fp ) );
if( word[0] == '\0' )
{
bug( "%s: EOF encountered reading file!", __FUNCTION__ );
word = "EndMobile";
}
/*
* So we don't get so many bug messages when something messes up
* * --Shaddai
*/
if( !strcmp( word, "EndMobile" ) )
break;
}
bug( "%s: Vnum not found", __FUNCTION__ );
return NULL;
}
for( ;; )
{
word = ( feof( fp ) ? "EndMobile" : fread_word( fp ) );
if( word[0] == '\0' )
{
bug( "%s: EOF encountered reading file!", __FUNCTION__ );
word = "EndMobile";
}
fMatch = FALSE;
switch ( UPPER( word[0] ) )
{
case '*':
fMatch = TRUE;
fread_to_eol( fp );
break;
case '#':
if( !strcmp( word, "#OBJECT" ) )
fread_obj( mob, fp, OS_CARRY );
break;
case 'D':
KEY( "Description", mob->description, fread_string( fp ) );
break;
case 'E':
if( !strcmp( word, "EndMobile" ) )
{
if( inroom == 0 )
inroom = ROOM_VNUM_TEMPLE;
pRoomIndex = get_room_index( inroom );
if( !pRoomIndex )
pRoomIndex = get_room_index( ROOM_VNUM_TEMPLE );
char_to_room( mob, pRoomIndex );
return mob;
}
break;
case 'F':
KEY( "Flags", mob->act, fread_bitvector( fp ) );
break;
case 'L':
KEY( "Long", mob->long_descr, fread_string( fp ) );
break;
case 'N':
KEY( "Name", mob->name, fread_string( fp ) );
break;
case 'P':
KEY( "Position", mob->position, fread_number( fp ) );
break;
case 'R':
KEY( "Room", inroom, fread_number( fp ) );
break;
case 'S':
KEY( "Short", mob->short_descr, fread_string( fp ) );
break;
}
if( !fMatch )
{
bug( "%s: no match: %s", __FUNCTION__, word );
fread_to_eol( fp );
}
}
}
This fix covers several spots where this function could run into trouble. Most of them deal with reading past the end of file, which has been shown to not be very reliable and will often result in infinite looping. The remaing problem being that if a vnum is not found, the code will attempt to extract a NULL mob, which can lead to a crash.