Commit b44c16cc authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

rpcrt4: Check to make sure there is enough data in the buffer during…

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.
parent 686c0f09
......@@ -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,
......
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