mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2024-11-28 19:14:14 +01:00
Make ZlibInStream more robust against failures
Move the checks around to avoid missing cases where we might access memory that is no longer valid. Also avoid touching the underlying stream implicitly (e.g. via the destructor) as it might also no longer be valid. A malicious server could theoretically use this for remote code execution in the client. Issue found by Pavel Cheremushkin from Kaspersky Lab
This commit is contained in:
parent
ac06594b12
commit
3282836baf
@ -52,16 +52,16 @@ int ZlibInStream::pos()
|
|||||||
return offset + ptr - start;
|
return offset + ptr - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZlibInStream::removeUnderlying()
|
void ZlibInStream::flushUnderlying()
|
||||||
{
|
{
|
||||||
ptr = end = start;
|
ptr = end = start;
|
||||||
if (!underlying) return;
|
|
||||||
|
|
||||||
while (bytesIn > 0) {
|
while (bytesIn > 0) {
|
||||||
decompress(true);
|
decompress(true);
|
||||||
end = start; // throw away any data
|
end = start; // throw away any data
|
||||||
}
|
}
|
||||||
underlying = 0;
|
|
||||||
|
setUnderlying(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZlibInStream::reset()
|
void ZlibInStream::reset()
|
||||||
@ -90,7 +90,7 @@ void ZlibInStream::init()
|
|||||||
void ZlibInStream::deinit()
|
void ZlibInStream::deinit()
|
||||||
{
|
{
|
||||||
assert(zs != NULL);
|
assert(zs != NULL);
|
||||||
removeUnderlying();
|
setUnderlying(NULL, 0);
|
||||||
inflateEnd(zs);
|
inflateEnd(zs);
|
||||||
delete zs;
|
delete zs;
|
||||||
zs = NULL;
|
zs = NULL;
|
||||||
@ -100,8 +100,6 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait)
|
|||||||
{
|
{
|
||||||
if (itemSize > bufSize)
|
if (itemSize > bufSize)
|
||||||
throw Exception("ZlibInStream overrun: max itemSize exceeded");
|
throw Exception("ZlibInStream overrun: max itemSize exceeded");
|
||||||
if (!underlying)
|
|
||||||
throw Exception("ZlibInStream overrun: no underlying stream");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
if (end - ptr != 0)
|
||||||
memmove(start, ptr, end - ptr);
|
memmove(start, ptr, end - ptr);
|
||||||
@ -127,6 +125,9 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait)
|
|||||||
|
|
||||||
bool ZlibInStream::decompress(bool wait)
|
bool ZlibInStream::decompress(bool wait)
|
||||||
{
|
{
|
||||||
|
if (!underlying)
|
||||||
|
throw Exception("ZlibInStream overrun: no underlying stream");
|
||||||
|
|
||||||
zs->next_out = (U8*)end;
|
zs->next_out = (U8*)end;
|
||||||
zs->avail_out = start + bufSize - end;
|
zs->avail_out = start + bufSize - end;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace rdr {
|
|||||||
virtual ~ZlibInStream();
|
virtual ~ZlibInStream();
|
||||||
|
|
||||||
void setUnderlying(InStream* is, int bytesIn);
|
void setUnderlying(InStream* is, int bytesIn);
|
||||||
void removeUnderlying();
|
void flushUnderlying();
|
||||||
int pos();
|
int pos();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
@ -340,7 +340,8 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer,
|
|||||||
|
|
||||||
zis[streamId].readBytes(netbuf, dataSize);
|
zis[streamId].readBytes(netbuf, dataSize);
|
||||||
|
|
||||||
zis[streamId].removeUnderlying();
|
zis[streamId].flushUnderlying();
|
||||||
|
zis[streamId].setUnderlying(NULL, 0);
|
||||||
delete ms;
|
delete ms;
|
||||||
|
|
||||||
bufptr = netbuf;
|
bufptr = netbuf;
|
||||||
|
@ -174,7 +174,8 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zis->removeUnderlying();
|
zis->flushUnderlying();
|
||||||
|
zis->setUnderlying(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ZRLE_DECODE
|
#undef ZRLE_DECODE
|
||||||
|
Loading…
Reference in New Issue
Block a user