diff options
author | Mark H Weaver <mhw@netris.org> | 2019-04-19 00:59:59 -0400 |
---|---|---|
committer | Mark H Weaver <mhw@netris.org> | 2019-06-18 02:05:20 -0400 |
commit | 91ba73b397fcc2a36ae7e434522a924c7a8887d0 (patch) | |
tree | 375d88ff803fa5bed9c6ffbfb10e51d41f5ebea8 /libguile/strings.c | |
parent | 420c2632bb1f48e492a035c1d216f209734f45e6 (diff) | |
download | guile-91ba73b397fcc2a36ae7e434522a924c7a8887d0.tar.gz |
Improve overflow checks in bytevector, string, and I/O operations.
* libguile/bytevectors.c (INTEGER_ACCESSOR_PROLOGUE)
(scm_bytevector_copy_x, bytevector_large_set): Rewrite checks to reliably
detect overflows.
(make_bytevector): Constrain the bytevector length to avoid later
overflows during allocation.
(make_bytevector_from_buffer): Fix indentation.
(scm_bytevector_length): Use 'scm_from_size_t' to convert a 'size_t',
not 'scm_from_uint'.
* libguile/fports.c (fport_seek): Check for overflow before the implicit
conversion of the return value.
* libguile/guardians.c (guardian_print): Use 'scm_from_ulong' to convert
an 'unsigned long', not 'scm_from_uint'.
* libguile/ports.c (scm_unread_string): Change a variable to type 'size_t'.
(scm_seek, scm_truncate_file): Use 'scm_t_off' instead of
'off_t_or_off64_t' to avoid implicit type conversions that could
overflow, because 'ptob->seek' and 'ptob->truncate' use 'scm_t_off'.
* libguile/r6rs-ports.c (bytevector_input_port_seek)
(custom_binary_port_seek, bytevector_output_port_seek): Rewrite offset
calculations to reliably detect overflows. Use 'scm_from_off_t' to
convert a 'scm_t_off', not 'scm_from_long' nor 'scm_from_int'.
(scm_get_bytevector_n_x, scm_get_bytevector_all, scm_unget_bytevector)
(bytevector_output_port_write): Rewrite checks to reliably detect
overflows. Use 'size_t' where appropriate.
(bytevector_output_port_buffer_grow): Rewrite size calculations to
reliably detect overflows. Minor change in the calculation of the new
size: now it is max(min_size, 2*current_size), whereas previously it
would multiply current_size by the smallest power of 2 needed to surpass
min_size.
* libguile/strings.c (make_stringbuf): Constrain the stringbuf length to
avoid later overflows during allocation.
(scm_string_append): Change overflow check to use INT_ADD_OVERFLOW.
* libguile/strports.c (string_port_write): Rewrite size calculations to
reliably detect overflows.
(string_port_seek): Rewrite offset calculations to reliably detect
overflows. Use 'scm_from_off_t' to convert a 'scm_t_off', not
'scm_from_long'.
(string_port_truncate): Use 'scm_from_off_t' to convert a 'scm_t_off',
not 'scm_from_off_t_or_off64_t'.
* libguile/vectors.c (scm_c_make_vector): Change a variable to type
'size_t'.
Diffstat (limited to 'libguile/strings.c')
-rw-r--r-- | libguile/strings.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/libguile/strings.c b/libguile/strings.c index e5c7f87d6..9497a3fe1 100644 --- a/libguile/strings.c +++ b/libguile/strings.c @@ -31,6 +31,7 @@ #include <unistr.h> #include <uniconv.h> #include <c-strcase.h> +#include <intprops.h> #include "striconveh.h" @@ -124,6 +125,12 @@ make_stringbuf (size_t len) lenhist[1000]++; #endif + /* Make sure that the total allocation size will not overflow size_t, + with ~30 extra bytes to spare to avoid an overflow within the + allocator. */ + if (INT_ADD_OVERFLOW (len, STRINGBUF_HEADER_BYTES + 32)) + scm_num_overflow ("make_stringbuf"); + buf = SCM_PACK_POINTER (scm_gc_malloc_pointerless (STRINGBUF_HEADER_BYTES + len + 1, "string")); @@ -150,9 +157,16 @@ make_wide_stringbuf (size_t len) lenhist[1000]++; #endif + /* Make sure that the total allocation size will not overflow size_t, + with ~30 extra bytes to spare to avoid an overflow within the + allocator. */ + if (len > (((size_t) -(STRINGBUF_HEADER_BYTES + 32 + sizeof (scm_t_wchar))) + / sizeof (scm_t_wchar))) + scm_num_overflow ("make_wide_stringbuf"); + raw_len = (len + 1) * sizeof (scm_t_wchar); buf = SCM_PACK_POINTER (scm_gc_malloc_pointerless (STRINGBUF_HEADER_BYTES + raw_len, - "string")); + "string")); SCM_SET_CELL_TYPE (buf, STRINGBUF_TAG | STRINGBUF_F_WIDE); SCM_SET_CELL_WORD_1 (buf, (scm_t_bits) len); @@ -1388,8 +1402,8 @@ SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1, s = SCM_CAR (l); SCM_VALIDATE_STRING (SCM_ARGn, s); len = scm_i_string_length (s); - if (((size_t) -1) - total < len) - scm_num_overflow (s_scm_string_append); + if (INT_ADD_OVERFLOW (total, len)) + scm_num_overflow (FUNC_NAME); total += len; if (!scm_i_is_narrow_string (s)) wide = 1; |