summaryrefslogtreecommitdiff
path: root/libguile/read.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2017-02-08 15:05:03 +0100
committerAndy Wingo <wingo@pobox.com>2017-02-08 15:09:14 +0100
commit09a69dd712536350b4b8feec8cdec3dc49cb71d5 (patch)
treeecf2fd427208fee72efbc0e47ca2da863eee3ba2 /libguile/read.c
parent8a4774dec8368def01af4126e77797468b0ce6de (diff)
downloadguile-09a69dd712536350b4b8feec8cdec3dc49cb71d5.tar.gz
Prevent TOCTTOU bugs in C ports
* libguile/ports-internal.h (scm_port_buffer_can_take): (scm_port_buffer_can_put): Add cur/end output arguments so that when a caller asks the buffer room, it can be relative to a fixed point in the buffer and not whatever point it's at when we go to fill it. (scm_port_buffer_did_take, scm_port_buffer_did_put): Similarly, require that the caller knows where they took/put data in the buffer. Prevents overflow. (scm_port_buffer_take_pointer, scm_port_buffer_put_pointer): Likewise, require that the caller has already checked and knows a position in the buffer and therefore how much data is available. (scm_port_buffer_take, scm_port_buffer_put, scm_port_buffer_putback): Adapt. * libguile/ports.h (scm_fill_input): Add cur/avail output arguments. * libguile/filesys.c: * libguile/poll.c: * libguile/ports.c: * libguile/r6rs-ports.c: * libguile/read.c: * libguile/rw.c: Adapt all callers. Gnarly work!
Diffstat (limited to 'libguile/read.c')
-rw-r--r--libguile/read.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/libguile/read.c b/libguile/read.c
index c7da054b0..5c436e2b2 100644
--- a/libguile/read.c
+++ b/libguile/read.c
@@ -2080,7 +2080,7 @@ scm_i_scan_for_encoding (SCM port)
scm_t_port *pt;
SCM buf;
char header[SCM_ENCODING_SEARCH_SIZE+1];
- size_t bytes_read, encoding_length, i;
+ size_t cur, bytes_read, encoding_length, i;
char *encoding = NULL;
char *pos, *encoding_start;
int in_comment;
@@ -2091,11 +2091,10 @@ scm_i_scan_for_encoding (SCM port)
if (pt->rw_random)
scm_flush (port);
- if (scm_port_buffer_can_take (buf) == 0)
+ if (scm_port_buffer_can_take (buf, &cur) == 0)
{
/* We can use the read buffer, and thus avoid a seek. */
- buf = scm_fill_input (port, 0);
- bytes_read = scm_port_buffer_can_take (buf);
+ buf = scm_fill_input (port, 0, &cur, &bytes_read);
if (bytes_read > SCM_ENCODING_SEARCH_SIZE)
bytes_read = SCM_ENCODING_SEARCH_SIZE;
@@ -2103,7 +2102,7 @@ scm_i_scan_for_encoding (SCM port)
/* An unbuffered port -- don't scan. */
return NULL;
- memcpy (header, scm_port_buffer_take_pointer (buf), bytes_read);
+ memcpy (header, scm_port_buffer_take_pointer (buf, cur), bytes_read);
header[bytes_read] = '\0';
}
else