Commit dbf123ba authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

ole32: Fix reads past the end of streams.

parent 4ad114cf
...@@ -3584,6 +3584,9 @@ HRESULT StorageImpl_ReadRawDirEntry(StorageImpl *This, ULONG index, BYTE *buffer ...@@ -3584,6 +3584,9 @@ HRESULT StorageImpl_ReadRawDirEntry(StorageImpl *This, ULONG index, BYTE *buffer
buffer, buffer,
&bytesRead); &bytesRead);
if (bytesRead != RAW_DIRENTRY_SIZE)
return STG_E_READFAULT;
return hr; return hr;
} }
...@@ -3929,6 +3932,11 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks( ...@@ -3929,6 +3932,11 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
offset.u.LowPart += cbRead; offset.u.LowPart += cbRead;
} }
else
{
resRead = STG_E_READFAULT;
break;
}
} while (cbTotalRead.QuadPart < size.QuadPart); } while (cbTotalRead.QuadPart < size.QuadPart);
HeapFree(GetProcessHeap(),0,buffer); HeapFree(GetProcessHeap(),0,buffer);
...@@ -4027,6 +4035,11 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks( ...@@ -4027,6 +4035,11 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
offset.u.LowPart += cbRead; offset.u.LowPart += cbRead;
} }
else
{
resRead = STG_E_READFAULT;
break;
}
}while(cbTotalRead.QuadPart < size.QuadPart); }while(cbTotalRead.QuadPart < size.QuadPart);
HeapFree(GetProcessHeap(), 0, buffer); HeapFree(GetProcessHeap(), 0, buffer);
...@@ -5810,6 +5823,7 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This, ...@@ -5810,6 +5823,7 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
ULONG bytesToReadInBuffer; ULONG bytesToReadInBuffer;
ULONG blockIndex; ULONG blockIndex;
BYTE* bufferWalker; BYTE* bufferWalker;
ULARGE_INTEGER stream_size;
TRACE("(%p)-> %i %p %i %p\n",This, offset.u.LowPart, buffer, size, bytesRead); TRACE("(%p)-> %i %p %i %p\n",This, offset.u.LowPart, buffer, size, bytesRead);
...@@ -5818,13 +5832,17 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This, ...@@ -5818,13 +5832,17 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
*/ */
blockIndex = BlockChainStream_GetSectorOfOffset(This, blockNoInSequence); blockIndex = BlockChainStream_GetSectorOfOffset(This, blockNoInSequence);
if (blockIndex == BLOCK_END_OF_CHAIN) *bytesRead = 0;
return STG_E_DOCFILECORRUPT; /* We failed to find the starting block */
stream_size = BlockChainStream_GetSize(This);
if (stream_size.QuadPart > offset.QuadPart)
size = min(stream_size.QuadPart - offset.QuadPart, size);
else
return S_OK;
/* /*
* Start reading the buffer. * Start reading the buffer.
*/ */
*bytesRead = 0;
bufferWalker = buffer; bufferWalker = buffer;
while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
...@@ -5862,7 +5880,7 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This, ...@@ -5862,7 +5880,7 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
break; break;
} }
return (size == 0) ? S_OK : STG_E_READFAULT; return S_OK;
} }
/****************************************************************************** /******************************************************************************
...@@ -6295,6 +6313,9 @@ static HRESULT SmallBlockChainStream_GetNextBlockInChain( ...@@ -6295,6 +6313,9 @@ static HRESULT SmallBlockChainStream_GetNextBlockInChain(
&buffer, &buffer,
&bytesRead); &bytesRead);
if (SUCCEEDED(res) && bytesRead != sizeof(DWORD))
res = STG_E_READFAULT;
if (SUCCEEDED(res)) if (SUCCEEDED(res))
{ {
StorageUtl_ReadDWord((BYTE *)&buffer, 0, nextBlockInChain); StorageUtl_ReadDWord((BYTE *)&buffer, 0, nextBlockInChain);
...@@ -6386,7 +6407,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock( ...@@ -6386,7 +6407,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock(
/* /*
* If we run out of space for the small block depot, enlarge it * If we run out of space for the small block depot, enlarge it
*/ */
if (SUCCEEDED(res)) if (SUCCEEDED(res) && bytesRead == sizeof(DWORD))
{ {
StorageUtl_ReadDWord((BYTE *)&buffer, 0, &nextBlockIndex); StorageUtl_ReadDWord((BYTE *)&buffer, 0, &nextBlockIndex);
...@@ -6482,12 +6503,21 @@ HRESULT SmallBlockChainStream_ReadAt( ...@@ -6482,12 +6503,21 @@ HRESULT SmallBlockChainStream_ReadAt(
ULONG blockIndex; ULONG blockIndex;
ULONG bytesReadFromBigBlockFile; ULONG bytesReadFromBigBlockFile;
BYTE* bufferWalker; BYTE* bufferWalker;
ULARGE_INTEGER stream_size;
/* /*
* This should never happen on a small block file. * This should never happen on a small block file.
*/ */
assert(offset.u.HighPart==0); assert(offset.u.HighPart==0);
*bytesRead = 0;
stream_size = SmallBlockChainStream_GetSize(This);
if (stream_size.QuadPart > offset.QuadPart)
size = min(stream_size.QuadPart - offset.QuadPart, size);
else
return S_OK;
/* /*
* Find the first block in the stream that contains part of the buffer. * Find the first block in the stream that contains part of the buffer.
*/ */
...@@ -6504,7 +6534,6 @@ HRESULT SmallBlockChainStream_ReadAt( ...@@ -6504,7 +6534,6 @@ HRESULT SmallBlockChainStream_ReadAt(
/* /*
* Start reading the buffer. * Start reading the buffer.
*/ */
*bytesRead = 0;
bufferWalker = buffer; bufferWalker = buffer;
while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
...@@ -6538,6 +6567,9 @@ HRESULT SmallBlockChainStream_ReadAt( ...@@ -6538,6 +6567,9 @@ HRESULT SmallBlockChainStream_ReadAt(
if (FAILED(rc)) if (FAILED(rc))
return rc; return rc;
if (!bytesReadFromBigBlockFile)
return STG_E_DOCFILECORRUPT;
/* /*
* Step to the next big block. * Step to the next big block.
*/ */
...@@ -6551,7 +6583,7 @@ HRESULT SmallBlockChainStream_ReadAt( ...@@ -6551,7 +6583,7 @@ HRESULT SmallBlockChainStream_ReadAt(
offsetInBlock = (offsetInBlock + bytesReadFromBigBlockFile) % This->parentStorage->smallBlockSize; offsetInBlock = (offsetInBlock + bytesReadFromBigBlockFile) % This->parentStorage->smallBlockSize;
} }
return (size == 0) ? S_OK : STG_E_READFAULT; return S_OK;
} }
/****************************************************************************** /******************************************************************************
......
...@@ -315,6 +315,55 @@ static void test_storage_stream(void) ...@@ -315,6 +315,55 @@ static void test_storage_stream(void)
r = IStream_Commit(stm, STGC_DEFAULT ); r = IStream_Commit(stm, STGC_DEFAULT );
ok(r==S_OK, "failed to commit stream\n"); ok(r==S_OK, "failed to commit stream\n");
/* Read past the end of the stream. */
pos.QuadPart = 3;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 3, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to read\n");
ok(count == 3, "read bytes past end of stream\n");
pos.QuadPart = 10;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 10, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to read\n");
ok(count == 0, "read bytes past end of stream\n");
pos.QuadPart = 10000;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 10000, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to read\n");
ok(count == 0, "read bytes past end of stream\n");
/* Convert to a big block stream, and read past the end. */
p.QuadPart = 5000;
r = IStream_SetSize(stm,p);
ok(r==S_OK, "failed to set pos\n");
pos.QuadPart = 4997;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 4997, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to read\n");
ok(count == 3, "read bytes past end of stream\n");
pos.QuadPart = 5001;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 5001, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to read\n");
ok(count == 0, "read bytes past end of stream\n");
pos.QuadPart = 10000;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 10000, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to read\n");
ok(count == 0, "read bytes past end of stream\n");
/* seek round a bit, reset the stream size */ /* seek round a bit, reset the stream size */
pos.QuadPart = 0; pos.QuadPart = 0;
r = IStream_Seek(stm, pos, 3, &p ); r = IStream_Seek(stm, pos, 3, &p );
...@@ -329,6 +378,16 @@ static void test_storage_stream(void) ...@@ -329,6 +378,16 @@ static void test_storage_stream(void)
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n"); ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 10, "at wrong place\n"); ok(p.QuadPart == 10, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to set pos\n");
ok(count == 0, "read bytes from empty stream\n");
pos.QuadPart = 10000;
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
ok(r==S_OK, "failed to seek stream\n");
ok(p.QuadPart == 10000, "at wrong place\n");
r = IStream_Read(stm, buffer, sizeof buffer, &count );
ok(r==S_OK, "failed to set pos\n");
ok(count == 0, "read bytes from empty stream\n");
pos.QuadPart = 0; pos.QuadPart = 0;
r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p ); r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
ok(r==S_OK, "failed to seek stream\n"); ok(r==S_OK, "failed to seek stream\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment