rpcrt4: Check to make sure there is enough data in the buffer during unmarshalling, so that the code doesn't try to read beyound the end of the buffer.

This commit is contained in:
Rob Shearman 2007-07-16 15:02:38 +01:00 committed by Alexandre Julliard
parent 686c0f094c
commit b44c16cc8d
1 changed files with 67 additions and 35 deletions

View File

@ -21,7 +21,6 @@
* TODO:
* - Non-conformant strings
* - String structs
* - Encapsulated unions
* - Byte count pointers
* - transmit_as/represent as
* - Multi-dimensional arrays
@ -351,6 +350,8 @@ static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
{
ALIGN_POINTER(pStubMsg->Buffer, 4);
if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
RpcRaiseException(RPC_X_BAD_STUB_DATA);
pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
pStubMsg->Buffer += 4;
TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
@ -370,6 +371,8 @@ static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_S
}
ALIGN_POINTER(pStubMsg->Buffer, 4);
if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
RpcRaiseException(RPC_X_BAD_STUB_DATA);
pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
pStubMsg->Buffer += 4;
TRACE("offset is %d\n", pStubMsg->Offset);
@ -571,6 +574,24 @@ static inline ULONG safe_multiply(ULONG a, ULONG b)
return ret;
}
static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
{
if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
(pStubMsg->Buffer + size > pStubMsg->BufferEnd))
RpcRaiseException(RPC_X_BAD_STUB_DATA);
pStubMsg->Buffer += size;
}
/* copies data from the buffer, checking that there is enough data in the buffer
* to do so */
static inline void safe_buffer_copy(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
{
if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
(pStubMsg->Buffer + size > pStubMsg->BufferEnd))
RpcRaiseException(RPC_X_BAD_STUB_DATA);
memcpy(p, pStubMsg->Buffer, size);
pStubMsg->Buffer += size;
}
/*
* NdrConformantString:
@ -735,6 +756,17 @@ unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg
RpcRaiseException(RPC_S_INVALID_BOUND);
return NULL;
}
/* verify the buffer is safe to access */
if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
(pStubMsg->Buffer + bufsize < pStubMsg->BufferEnd))
{
ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
pStubMsg->BufferEnd, pStubMsg->Buffer);
RpcRaiseException(RPC_X_BAD_STUB_DATA);
return NULL;
}
for (i = bufsize - esize; i < bufsize; i++)
if (pStubMsg->Buffer[i] != 0)
{
@ -747,9 +779,7 @@ unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg
if (fMustAlloc || !*ppMemory)
*ppMemory = NdrAllocate(pStubMsg, memsize);
memcpy(*ppMemory, pStubMsg->Buffer, bufsize);
pStubMsg->Buffer += bufsize;
safe_buffer_copy(pStubMsg, *ppMemory, bufsize);
if (*pFormat == RPC_FC_C_CSTRING) {
TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
@ -1539,7 +1569,7 @@ unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
{
ALIGN_POINTER(pStubMsg->Buffer, 4);
Buffer = pStubMsg->Buffer;
pStubMsg->Buffer += 4;
safe_buffer_increment(pStubMsg, 4);
}
else
Buffer = pStubMsg->Buffer;
@ -1894,31 +1924,27 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
case RPC_FC_CHAR:
case RPC_FC_SMALL:
case RPC_FC_USMALL:
memcpy(pMemory, pStubMsg->Buffer, 1);
safe_buffer_copy(pStubMsg, pMemory, 1);
TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
pStubMsg->Buffer += 1;
pMemory += 1;
break;
case RPC_FC_WCHAR:
case RPC_FC_SHORT:
case RPC_FC_USHORT:
memcpy(pMemory, pStubMsg->Buffer, 2);
safe_buffer_copy(pStubMsg, pMemory, 2);
TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
pStubMsg->Buffer += 2;
pMemory += 2;
break;
case RPC_FC_LONG:
case RPC_FC_ULONG:
case RPC_FC_ENUM32:
memcpy(pMemory, pStubMsg->Buffer, 4);
safe_buffer_copy(pStubMsg, pMemory, 4);
TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
pStubMsg->Buffer += 4;
pMemory += 4;
break;
case RPC_FC_HYPER:
memcpy(pMemory, pStubMsg->Buffer, 8);
safe_buffer_copy(pStubMsg, pMemory, 8);
TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
pStubMsg->Buffer += 8;
pMemory += 8;
break;
case RPC_FC_POINTER:
@ -2547,10 +2573,8 @@ unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
ALIGN_POINTER(pStubMsg->Buffer, alignment);
memcpy(*ppMemory, pStubMsg->Buffer, size);
pStubMsg->BufferMark = pStubMsg->Buffer;
pStubMsg->Buffer += size;
safe_buffer_copy(pStubMsg, *ppMemory, size);
EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
@ -2697,8 +2721,7 @@ unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pS
if (!*ppMemory || fMustAlloc)
*ppMemory = NdrAllocate(pStubMsg, memsize);
memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, bufsize);
pStubMsg->Buffer += bufsize;
safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
@ -3436,8 +3459,7 @@ unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMs
/* now copy the data */
pStubMsg->BufferMark = pStubMsg->Buffer;
memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size + bufsize);
pStubMsg->Buffer += pCStructFormat->memory_size + bufsize;
safe_buffer_copy(pStubMsg, *ppMemory, pCStructFormat->memory_size + bufsize);
if (pCStructFormat->type == RPC_FC_CPSTRUCT)
EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
@ -3659,8 +3681,7 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE
/* copy the constant data */
pStubMsg->BufferMark = pStubMsg->Buffer;
memcpy(*ppMemory, pStubMsg->Buffer, pCVStructFormat->memory_size);
pStubMsg->Buffer += pCVStructFormat->memory_size;
safe_buffer_copy(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
@ -3688,9 +3709,7 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE
}
/* copy the array data */
memcpy(*ppMemory + pCVStructFormat->memory_size, pStubMsg->Buffer,
bufsize);
pStubMsg->Buffer += bufsize;
safe_buffer_copy(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
if (cvarray_type == RPC_FC_C_CSTRING)
TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
@ -3999,9 +4018,8 @@ unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
if (fMustAlloc || !*ppMemory)
*ppMemory = NdrAllocate(pStubMsg, total_size);
memcpy(*ppMemory, pStubMsg->Buffer, total_size);
pStubMsg->BufferMark = pStubMsg->Buffer;
pStubMsg->Buffer += total_size;
safe_buffer_copy(pStubMsg, *ppMemory, total_size);
pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
@ -4234,8 +4252,7 @@ unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
if (!*ppMemory || fMustAlloc)
*ppMemory = NdrAllocate(pStubMsg, size);
memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, bufsize);
pStubMsg->Buffer += bufsize;
safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
@ -4567,6 +4584,9 @@ static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
else
pStubMsg->Buffer += 4; /* for pointer ID */
if (saved_buffer + 4 > pStubMsg->BufferEnd)
RpcRaiseException(RPC_X_BAD_STUB_DATA);
PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc);
if (pointer_buffer_mark_set)
{
@ -4900,22 +4920,31 @@ static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
case RPC_FC_CHAR:
case RPC_FC_SMALL:
case RPC_FC_USMALL:
discriminant = *(UCHAR *)pStubMsg->Buffer;
pStubMsg->Buffer += sizeof(UCHAR);
{
UCHAR d;
safe_buffer_copy(pStubMsg, &d, sizeof(d));
discriminant = d;
break;
}
case RPC_FC_WCHAR:
case RPC_FC_SHORT:
case RPC_FC_USHORT:
{
USHORT d;
ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
discriminant = *(USHORT *)pStubMsg->Buffer;
pStubMsg->Buffer += sizeof(USHORT);
safe_buffer_copy(pStubMsg, &d, sizeof(d));
discriminant = d;
break;
}
case RPC_FC_LONG:
case RPC_FC_ULONG:
{
ULONG d;
ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
discriminant = *(ULONG *)pStubMsg->Buffer;
pStubMsg->Buffer += sizeof(ULONG);
safe_buffer_copy(pStubMsg, &d, sizeof(d));
discriminant = d;
break;
}
default:
FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
}
@ -5655,6 +5684,9 @@ void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
ALIGN_POINTER(pStubMsg->Buffer, 4);
if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
RpcRaiseException(RPC_X_BAD_STUB_DATA);
NDRCContextUnmarshall(pContextHandle,
BindHandle,
pStubMsg->Buffer,