Commit 97e514bf authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

decomp: fix heap overflow and cleanup (fixes #12052)

(cherry picked from commit aed1b6da46d484f18dbb36dbb5e62c4d4f9ec070)
parent ae2e2e4d
...@@ -183,16 +183,19 @@ static int Peek (stream_t *, const uint8_t **, unsigned int); ...@@ -183,16 +183,19 @@ static int Peek (stream_t *, const uint8_t **, unsigned int);
*/ */
static int Read (stream_t *stream, void *buf, unsigned int buflen) static int Read (stream_t *stream, void *buf, unsigned int buflen)
{ {
stream_sys_t *p_sys = stream->p_sys; stream_sys_t *sys = stream->p_sys;
block_t *peeked; unsigned ret = 0;
ssize_t length;
if (buf == NULL) /* caller skips data, get big enough peek buffer */ if (buf == NULL) /* caller skips data, get big enough peek buffer */
buflen = Peek (stream, &(const uint8_t *){ NULL }, buflen); buflen = Peek (stream, &(const uint8_t *){ NULL }, buflen);
if ((peeked = p_sys->peeked) != NULL) block_t *peeked = sys->peeked;
if (peeked != NULL)
{ /* dequeue peeked data */ { /* dequeue peeked data */
length = (buflen > peeked->i_buffer) ? peeked->i_buffer : buflen; size_t length = peeked->i_buffer;
if (length > buflen)
length = buflen;
if (buf != NULL) if (buf != NULL)
{ {
memcpy (buf, peeked->p_buffer, length); memcpy (buf, peeked->p_buffer, length);
...@@ -201,24 +204,25 @@ static int Read (stream_t *stream, void *buf, unsigned int buflen) ...@@ -201,24 +204,25 @@ static int Read (stream_t *stream, void *buf, unsigned int buflen)
buflen -= length; buflen -= length;
peeked->p_buffer += length; peeked->p_buffer += length;
peeked->i_buffer -= length; peeked->i_buffer -= length;
if (peeked->i_buffer == 0) if (peeked->i_buffer == 0)
{ {
block_Release (peeked); block_Release (peeked);
p_sys->peeked = NULL; sys->peeked = NULL;
} }
p_sys->offset += length;
if (buflen > 0) sys->offset += length;
length += Read (stream, ((char *)buf) + length, buflen - length); ret += length;
return length;
} }
assert ((buf != NULL) || (buflen == 0)); assert ((buf != NULL) || (buflen == 0));
length = net_Read (stream, p_sys->read_fd, NULL, buf, buflen, false); ssize_t val = net_Read (stream, sys->read_fd, NULL, buf, buflen, false);
if (length < 0) if (val > 0)
return 0; {
p_sys->offset += length; sys->offset += val;
return length; ret += val;
}
return ret;
} }
/** /**
...@@ -226,23 +230,32 @@ static int Read (stream_t *stream, void *buf, unsigned int buflen) ...@@ -226,23 +230,32 @@ static int Read (stream_t *stream, void *buf, unsigned int buflen)
*/ */
static int Peek (stream_t *stream, const uint8_t **pbuf, unsigned int len) static int Peek (stream_t *stream, const uint8_t **pbuf, unsigned int len)
{ {
stream_sys_t *p_sys = stream->p_sys; stream_sys_t *sys = stream->p_sys;
block_t *peeked = p_sys->peeked; block_t *peeked = sys->peeked;
size_t curlen = 0; size_t curlen;
int fd = p_sys->read_fd;
if (peeked == NULL) if (peeked != NULL)
{
curlen = peeked->i_buffer;
if (curlen < len)
peeked = block_Realloc (peeked, 0, len);
}
else
{
curlen = 0;
peeked = block_Alloc (len); peeked = block_Alloc (len);
else if ((curlen = peeked->i_buffer) < len) }
peeked = block_Realloc (peeked, 0, len);
if ((p_sys->peeked = peeked) == NULL) sys->peeked = peeked;
if (unlikely(peeked == NULL))
return 0; return 0;
while (curlen < len) while (curlen < len)
{ {
ssize_t val = net_Read (stream, fd, NULL, peeked->p_buffer + curlen, ssize_t val;
len - curlen, false);
val = net_Read (stream, sys->read_fd, NULL,
peeked->p_buffer + curlen, len - curlen, false);
if (val <= 0) if (val <= 0)
break; break;
curlen += val; curlen += val;
......
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