mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-21 20:20:24 +02:00
string ports: Add overflow checks and other fixes.
* libguile/strports.c (st_resize_port): Check that 'new_size' fits in a size_t. (st_end_input): Improve code clarity. (st_seek): Check for overflow during computation of target position. Check for invalid 'whence' argument. Resize the port when seeking to a position beyond the end of the buffer. Check for overflow during computation of new buffer size when resizing the port.
This commit is contained in:
parent
448eb30e3d
commit
133ec4c491
1 changed files with 43 additions and 27 deletions
|
@ -102,6 +102,10 @@ stfill_buffer (SCM port)
|
||||||
change `read_buf_size'. */
|
change `read_buf_size'. */
|
||||||
static void
|
static void
|
||||||
st_resize_port (scm_t_port *pt, scm_t_off new_size)
|
st_resize_port (scm_t_port *pt, scm_t_off new_size)
|
||||||
|
{
|
||||||
|
if (new_size < 0 || new_size > SCM_I_SIZE_MAX)
|
||||||
|
scm_misc_error ("st_resize_port", "new_size overflow", SCM_EOL);
|
||||||
|
|
||||||
{
|
{
|
||||||
SCM old_stream = SCM_PACK (pt->stream);
|
SCM old_stream = SCM_PACK (pt->stream);
|
||||||
const signed char *src = SCM_BYTEVECTOR_CONTENTS (old_stream);
|
const signed char *src = SCM_BYTEVECTOR_CONTENTS (old_stream);
|
||||||
|
@ -127,6 +131,7 @@ st_resize_port (scm_t_port *pt, scm_t_off new_size)
|
||||||
pt->read_end = pt->read_buf + pt->read_buf_size;
|
pt->read_end = pt->read_buf + pt->read_buf_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure that `write_pos' < `write_end' by enlarging the buffer when
|
/* Ensure that `write_pos' < `write_end' by enlarging the buffer when
|
||||||
necessary. Update `read_buf' to account for written chars. The
|
necessary. Update `read_buf' to account for written chars. The
|
||||||
|
@ -176,7 +181,8 @@ st_end_input (SCM port, int offset)
|
||||||
if (pt->read_pos - pt->read_buf < offset)
|
if (pt->read_pos - pt->read_buf < offset)
|
||||||
scm_misc_error ("st_end_input", "negative position", SCM_EOL);
|
scm_misc_error ("st_end_input", "negative position", SCM_EOL);
|
||||||
|
|
||||||
pt->write_pos = (unsigned char *) (pt->read_pos = pt->read_pos - offset);
|
pt->read_pos -= offset;
|
||||||
|
pt->write_pos = (unsigned char *) pt->read_pos;
|
||||||
pt->rw_active = SCM_PORT_NEITHER;
|
pt->rw_active = SCM_PORT_NEITHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +208,8 @@ st_seek (SCM port, scm_t_off offset, int whence)
|
||||||
else
|
else
|
||||||
/* all other cases. */
|
/* all other cases. */
|
||||||
{
|
{
|
||||||
|
scm_t_off base = 0;
|
||||||
|
|
||||||
if (pt->rw_active == SCM_PORT_WRITE)
|
if (pt->rw_active == SCM_PORT_WRITE)
|
||||||
st_flush (port);
|
st_flush (port);
|
||||||
|
|
||||||
|
@ -211,18 +219,24 @@ st_seek (SCM port, scm_t_off offset, int whence)
|
||||||
switch (whence)
|
switch (whence)
|
||||||
{
|
{
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
target = pt->read_pos - pt->read_buf + offset;
|
base = pt->read_pos - pt->read_buf;
|
||||||
break;
|
break;
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
target = pt->read_end - pt->read_buf + offset;
|
base = pt->read_end - pt->read_buf;
|
||||||
break;
|
break;
|
||||||
default: /* SEEK_SET */
|
case SEEK_SET:
|
||||||
target = offset;
|
base = 0;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
scm_wrong_type_arg_msg ("st_seek", 0, port,
|
||||||
|
"invalid `whence' argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offset > SCM_T_OFF_MAX - base)
|
||||||
|
scm_misc_error ("st_seek", "target would overflow", SCM_EOL);
|
||||||
|
target = base + offset;
|
||||||
if (target < 0)
|
if (target < 0)
|
||||||
scm_misc_error ("st_seek", "negative offset", SCM_EOL);
|
scm_misc_error ("st_seek", "negative target", SCM_EOL);
|
||||||
|
|
||||||
if (target >= pt->write_buf_size)
|
if (target >= pt->write_buf_size)
|
||||||
{
|
{
|
||||||
|
@ -235,7 +249,9 @@ st_seek (SCM port, scm_t_off offset, int whence)
|
||||||
SCM_EOL);
|
SCM_EOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (target == pt->write_buf_size)
|
else if (target > SCM_T_OFF_MAX - target)
|
||||||
|
scm_misc_error ("st_seek", "target * 2 would overflow", SCM_EOL);
|
||||||
|
else
|
||||||
st_resize_port (pt, target * 2);
|
st_resize_port (pt, target * 2);
|
||||||
}
|
}
|
||||||
pt->read_pos = pt->write_pos = pt->read_buf + target;
|
pt->read_pos = pt->write_pos = pt->read_buf + target;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue