[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 03/03: string ports: Add overflow checks and other fixes
From: |
Mark H. Weaver |
Subject: |
[Guile-commits] 03/03: string ports: Add overflow checks and other fixes. |
Date: |
Mon, 02 Nov 2015 02:31:17 +0000 |
mhw pushed a commit to branch stable-2.0
in repository guile.
commit 133ec4c491d9c4f6e9c5c44963e17be662fe420d
Author: Mark H Weaver <address@hidden>
Date: Sun Sep 6 07:42:07 2015 -0400
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.
---
libguile/strports.c | 64 +++++++++++++++++++++++++++++++-------------------
1 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/libguile/strports.c b/libguile/strports.c
index f306019..18f1970 100644
--- a/libguile/strports.c
+++ b/libguile/strports.c
@@ -103,28 +103,33 @@ stfill_buffer (SCM port)
static void
st_resize_port (scm_t_port *pt, scm_t_off new_size)
{
- SCM old_stream = SCM_PACK (pt->stream);
- const signed char *src = SCM_BYTEVECTOR_CONTENTS (old_stream);
- SCM new_stream = scm_c_make_bytevector (new_size);
- signed char *dst = SCM_BYTEVECTOR_CONTENTS (new_stream);
- unsigned long int old_size = SCM_BYTEVECTOR_LENGTH (old_stream);
- unsigned long int min_size = min (old_size, new_size);
+ if (new_size < 0 || new_size > SCM_I_SIZE_MAX)
+ scm_misc_error ("st_resize_port", "new_size overflow", SCM_EOL);
- scm_t_off index = pt->write_pos - pt->write_buf;
+ {
+ SCM old_stream = SCM_PACK (pt->stream);
+ const signed char *src = SCM_BYTEVECTOR_CONTENTS (old_stream);
+ SCM new_stream = scm_c_make_bytevector (new_size);
+ signed char *dst = SCM_BYTEVECTOR_CONTENTS (new_stream);
+ unsigned long int old_size = SCM_BYTEVECTOR_LENGTH (old_stream);
+ unsigned long int min_size = min (old_size, new_size);
- pt->write_buf_size = new_size;
+ scm_t_off index = pt->write_pos - pt->write_buf;
- memcpy (dst, src, min_size);
+ pt->write_buf_size = new_size;
- scm_remember_upto_here_1 (old_stream);
+ memcpy (dst, src, min_size);
- /* reset buffer. */
- {
- pt->stream = SCM_UNPACK (new_stream);
- pt->read_buf = pt->write_buf = (unsigned char *)dst;
- pt->read_pos = pt->write_pos = pt->write_buf + index;
- pt->write_end = pt->write_buf + pt->write_buf_size;
- pt->read_end = pt->read_buf + pt->read_buf_size;
+ scm_remember_upto_here_1 (old_stream);
+
+ /* reset buffer. */
+ {
+ pt->stream = SCM_UNPACK (new_stream);
+ pt->read_buf = pt->write_buf = (unsigned char *)dst;
+ pt->read_pos = pt->write_pos = pt->write_buf + index;
+ pt->write_end = pt->write_buf + pt->write_buf_size;
+ pt->read_end = pt->read_buf + pt->read_buf_size;
+ }
}
}
@@ -176,7 +181,8 @@ st_end_input (SCM port, int offset)
if (pt->read_pos - pt->read_buf < offset)
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;
}
@@ -202,6 +208,8 @@ st_seek (SCM port, scm_t_off offset, int whence)
else
/* all other cases. */
{
+ scm_t_off base = 0;
+
if (pt->rw_active == SCM_PORT_WRITE)
st_flush (port);
@@ -211,18 +219,24 @@ st_seek (SCM port, scm_t_off offset, int whence)
switch (whence)
{
case SEEK_CUR:
- target = pt->read_pos - pt->read_buf + offset;
+ base = pt->read_pos - pt->read_buf;
break;
case SEEK_END:
- target = pt->read_end - pt->read_buf + offset;
+ base = pt->read_end - pt->read_buf;
break;
- default: /* SEEK_SET */
- target = offset;
+ case SEEK_SET:
+ base = 0;
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)
- scm_misc_error ("st_seek", "negative offset", SCM_EOL);
+ scm_misc_error ("st_seek", "negative target", SCM_EOL);
if (target >= pt->write_buf_size)
{
@@ -235,7 +249,9 @@ st_seek (SCM port, scm_t_off offset, int whence)
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);
}
pt->read_pos = pt->write_pos = pt->read_buf + target;