Skip to content

Commit

Permalink
Make CommonAbstractStore check page cursor bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisvest committed Apr 7, 2016
1 parent 7743afe commit f5aefc6
Show file tree
Hide file tree
Showing 3 changed files with 387 additions and 7 deletions.
Expand Up @@ -204,6 +204,12 @@ protected void initialiseNewStoreFile( PagedFile file ) throws IOException
createHeaderRecord( pageCursor );
}
while ( pageCursor.shouldRetry() );
if ( pageCursor.checkAndClearBoundsFlag() )
{
throw new UnderlyingStorageException(
"Out of page bounds when writing header; page size too small: " +
pageCache.pageSize() + " bytes.");
}
}
}
}
Expand All @@ -216,6 +222,27 @@ protected void initialiseNewStoreFile( PagedFile file ) throws IOException
idGeneratorFactory.create( idFileName, getNumberOfReservedLowIds(), true );
}

protected void checkForOutOfBounds( PageCursor pageCursor, long recordId )
{
if ( pageCursor.checkAndClearBoundsFlag() )
{
throwOutOfBoundsException( recordId );
}
}

private void throwOutOfBoundsException( long recordId )
{
RECORD record = newRecord();
record.setId( recordId );
long pageId = pageIdForRecord( recordId );
int offset = offsetForId( recordId );
throw new UnderlyingStorageException(
"Access to record " + record + " went out of bounds of the page. The record size is " +
recordSize + " bytes, and the access was at offset " + offset + " bytes into page " +
pageId + ", and the pages have a capacity of " + storeFile.pageSize() + " bytes. " +
"The mapped store file in question is " + storageFileName.getAbsolutePath() );
}

protected void createHeaderRecord( PageCursor cursor ) throws IOException
{
int offset = cursor.getOffset();
Expand Down Expand Up @@ -263,6 +290,12 @@ private void extractHeaderRecord() throws IOException
readHeaderAndInitializeRecordFormat( pageCursor );
}
while ( pageCursor.shouldRetry() );
if ( pageCursor.checkAndClearBoundsFlag() )
{
throw new UnderlyingStorageException(
"Out of page bounds when reading header; page size too small: " +
pageCache.pageSize() + " bytes.");
}
}
}
}
Expand Down Expand Up @@ -293,8 +326,8 @@ public int getRecordsPerPage()
public byte[] getRawRecordData( long id ) throws IOException
{
byte[] data = new byte[recordSize];
long pageId = RecordPageLocationCalculator.pageIdForRecord( id, storeFile.pageSize(), recordSize );
int offset = RecordPageLocationCalculator.offsetForId( id, storeFile.pageSize(), recordSize );
long pageId = pageIdForRecord( id );
int offset = offsetForId( id );
try ( PageCursor pageCursor = storeFile.io( pageId, PagedFile.PF_SHARED_READ_LOCK ) )
{
if ( pageCursor.next() )
Expand All @@ -305,6 +338,7 @@ public byte[] getRawRecordData( long id ) throws IOException
pageCursor.getBytes( data );
}
while ( pageCursor.shouldRetry() );
checkForOutOfBounds( pageCursor, id );
}
}
return data;
Expand Down Expand Up @@ -365,6 +399,7 @@ public boolean isInUse( long id )
recordIsInUse = isInUse( cursor );
}
while ( cursor.shouldRetry() );
checkForOutOfBounds( cursor, id );
}
return recordIsInUse;
}
Expand Down Expand Up @@ -396,7 +431,7 @@ final void rebuildIdGenerator()
openIdGenerator();

long defraggedCount = 0;
boolean fastRebuild = doFastIdGeneratorRebuild();
boolean fastRebuild = isOnlyFastIdGeneratorRebuildEnabled( configuration );

try
{
Expand Down Expand Up @@ -426,6 +461,11 @@ final void rebuildIdGenerator()
}
}

protected boolean isOnlyFastIdGeneratorRebuildEnabled( Config config )
{
return config.get( Configuration.rebuild_idgenerators_fast );
}

private long rebuildIdGeneratorSlow( PageCursor cursor, int recordsPerPage, int blockSize,
long foundHighId )
throws IOException
Expand Down Expand Up @@ -469,6 +509,7 @@ else if ( isRecordReserved( cursor ) )
}
}
while ( cursor.shouldRetry() );
checkIdScanCursorBounds( cursor );

for ( int i = 0; i < defragged; i++ )
{
Expand All @@ -480,9 +521,14 @@ else if ( isRecordReserved( cursor ) )
return defragCount;
}

protected boolean doFastIdGeneratorRebuild()
private void checkIdScanCursorBounds( PageCursor cursor )
{
return configuration.get( Configuration.rebuild_idgenerators_fast );
if ( cursor.checkAndClearBoundsFlag() )
{
throw new UnderlyingStorageException(
"Out of bounds access on page " + cursor.getCurrentPageId() + " detected while scanning the " +
storageFileName + " file for deleted records" );
}
}

/**
Expand Down Expand Up @@ -653,11 +699,14 @@ protected long scanForHighId()
long nextPageId = storeFile.getLastPageId();
int recordsPerPage = getRecordsPerPage();
int recordSize = getRecordSize();
long highestId = getNumberOfReservedLowIds();
while ( nextPageId >= 0 && cursor.next( nextPageId ) )
{
nextPageId--;
boolean found;
do
{
found = false;
int currentRecord = recordsPerPage;
while ( currentRecord-- > 0 )
{
Expand All @@ -671,12 +720,19 @@ protected long scanForHighId()
if ( !justLegacyStoreTrailer )
{
// We've found the highest id in use
return recordId + 1 /*+1 since we return the high id*/;
found = true;
highestId = recordId + 1; /*+1 since we return the high id*/;
break;
}
}
}
}
while ( cursor.shouldRetry() );
checkIdScanCursorBounds( cursor );
if ( found )
{
return highestId;
}
}

return getNumberOfReservedLowIds();
Expand Down Expand Up @@ -986,6 +1042,7 @@ public RECORD getRecord( long id, RECORD record, RecordLoad mode )
recordFormat.read( record, cursor, mode, recordSize, storeFile );
}
while ( cursor.shouldRetry() );
checkForOutOfBounds( cursor, id );
verifyAfterReading( record, mode );
}
else
Expand Down Expand Up @@ -1018,6 +1075,7 @@ public void updateRecord( RECORD record )
recordFormat.write( record, cursor, recordSize, storeFile );
}
while ( cursor.shouldRetry() );
checkForOutOfBounds( cursor, id ); // We don't free ids if something weird goes wrong
if ( !record.inUse() )
{
freeId( id );
Expand Down Expand Up @@ -1112,6 +1170,7 @@ public boolean next()
recordFormat.read( record, pageCursor, mode, recordSize, storeFile );
}
while ( pageCursor.shouldRetry() );
checkForOutOfBounds( pageCursor, currentId );
verifyAfterReading( record, mode );
}
else
Expand Down
Expand Up @@ -76,7 +76,7 @@ public DynamicStringStore getNameStore()
}

@Override
protected boolean doFastIdGeneratorRebuild()
protected boolean isOnlyFastIdGeneratorRebuildEnabled( Config config )
{
return false;
}
Expand Down

0 comments on commit f5aefc6

Please sign in to comment.