mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
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'.
This commit is contained in:
parent
420c2632bb
commit
91ba73b397
8 changed files with 142 additions and 76 deletions
|
@ -84,7 +84,8 @@
|
||||||
c_len = SCM_BYTEVECTOR_LENGTH (bv); \
|
c_len = SCM_BYTEVECTOR_LENGTH (bv); \
|
||||||
c_bv = (_sign char *) SCM_BYTEVECTOR_CONTENTS (bv); \
|
c_bv = (_sign char *) SCM_BYTEVECTOR_CONTENTS (bv); \
|
||||||
\
|
\
|
||||||
if (SCM_UNLIKELY (c_index + ((_len) >> 3UL) - 1 >= c_len)) \
|
if (SCM_UNLIKELY (c_len < c_index \
|
||||||
|
|| (c_len - c_index < (_len) / 8))) \
|
||||||
scm_out_of_range (FUNC_NAME, index);
|
scm_out_of_range (FUNC_NAME, index);
|
||||||
|
|
||||||
#define INTEGER_GETTER_PROLOGUE(_len, _sign) \
|
#define INTEGER_GETTER_PROLOGUE(_len, _sign) \
|
||||||
|
@ -206,12 +207,17 @@ make_bytevector (size_t len, scm_t_array_element_type element_type)
|
||||||
size_t c_len;
|
size_t c_len;
|
||||||
|
|
||||||
if (SCM_UNLIKELY (element_type > SCM_ARRAY_ELEMENT_TYPE_LAST
|
if (SCM_UNLIKELY (element_type > SCM_ARRAY_ELEMENT_TYPE_LAST
|
||||||
|| scm_i_array_element_type_sizes[element_type] < 8
|
|| scm_i_array_element_type_sizes[element_type] < 8))
|
||||||
|| len >= (((size_t) -1)
|
|
||||||
/ (scm_i_array_element_type_sizes[element_type]/8))))
|
|
||||||
/* This would be an internal Guile programming error */
|
/* This would be an internal Guile programming error */
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
|
/* 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 (SCM_UNLIKELY (len >= (((size_t) -(SCM_BYTEVECTOR_HEADER_BYTES + 32))
|
||||||
|
/ (scm_i_array_element_type_sizes[element_type]/8))))
|
||||||
|
scm_num_overflow ("make-bytevector");
|
||||||
|
|
||||||
if (SCM_UNLIKELY (len == 0 && element_type == SCM_ARRAY_ELEMENT_TYPE_VU8
|
if (SCM_UNLIKELY (len == 0 && element_type == SCM_ARRAY_ELEMENT_TYPE_VU8
|
||||||
&& SCM_BYTEVECTOR_P (scm_null_bytevector)))
|
&& SCM_BYTEVECTOR_P (scm_null_bytevector)))
|
||||||
ret = scm_null_bytevector;
|
ret = scm_null_bytevector;
|
||||||
|
@ -252,7 +258,7 @@ make_bytevector_from_buffer (size_t len, void *contents,
|
||||||
size_t c_len;
|
size_t c_len;
|
||||||
|
|
||||||
ret = SCM_PACK_POINTER (scm_gc_malloc (SCM_BYTEVECTOR_HEADER_BYTES,
|
ret = SCM_PACK_POINTER (scm_gc_malloc (SCM_BYTEVECTOR_HEADER_BYTES,
|
||||||
SCM_GC_BYTEVECTOR));
|
SCM_GC_BYTEVECTOR));
|
||||||
|
|
||||||
c_len = len * (scm_i_array_element_type_sizes[element_type] / 8);
|
c_len = len * (scm_i_array_element_type_sizes[element_type] / 8);
|
||||||
|
|
||||||
|
@ -510,7 +516,7 @@ SCM_DEFINE (scm_bytevector_length, "bytevector-length", 1, 0, 0,
|
||||||
"Return the length (in bytes) of @var{bv}.")
|
"Return the length (in bytes) of @var{bv}.")
|
||||||
#define FUNC_NAME s_scm_bytevector_length
|
#define FUNC_NAME s_scm_bytevector_length
|
||||||
{
|
{
|
||||||
return scm_from_uint (scm_c_bytevector_length (bv));
|
return scm_from_size_t (scm_c_bytevector_length (bv));
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
@ -595,9 +601,11 @@ SCM_DEFINE (scm_bytevector_copy_x, "bytevector-copy!", 5, 0, 0,
|
||||||
c_source_len = SCM_BYTEVECTOR_LENGTH (source);
|
c_source_len = SCM_BYTEVECTOR_LENGTH (source);
|
||||||
c_target_len = SCM_BYTEVECTOR_LENGTH (target);
|
c_target_len = SCM_BYTEVECTOR_LENGTH (target);
|
||||||
|
|
||||||
if (SCM_UNLIKELY (c_source_start + c_len > c_source_len))
|
if (SCM_UNLIKELY (c_source_len < c_source_start
|
||||||
|
|| (c_source_len - c_source_start < c_len)))
|
||||||
scm_out_of_range (FUNC_NAME, source_start);
|
scm_out_of_range (FUNC_NAME, source_start);
|
||||||
if (SCM_UNLIKELY (c_target_start + c_len > c_target_len))
|
if (SCM_UNLIKELY (c_target_len < c_target_start
|
||||||
|
|| (c_target_len - c_target_start < c_len)))
|
||||||
scm_out_of_range (FUNC_NAME, target_start);
|
scm_out_of_range (FUNC_NAME, target_start);
|
||||||
|
|
||||||
memmove (c_target + c_target_start,
|
memmove (c_target + c_target_start,
|
||||||
|
@ -915,7 +923,8 @@ bytevector_large_set (char *c_bv, size_t c_size, int signed_p,
|
||||||
size_t. */ \
|
size_t. */ \
|
||||||
if (SCM_UNLIKELY (c_size == 0 || c_size >= (SIZE_MAX >> 3))) \
|
if (SCM_UNLIKELY (c_size == 0 || c_size >= (SIZE_MAX >> 3))) \
|
||||||
scm_out_of_range (FUNC_NAME, size); \
|
scm_out_of_range (FUNC_NAME, size); \
|
||||||
if (SCM_UNLIKELY (c_index + c_size > c_len)) \
|
if (SCM_UNLIKELY (c_len < c_index \
|
||||||
|
|| (c_len - c_index < c_size))) \
|
||||||
scm_out_of_range (FUNC_NAME, index);
|
scm_out_of_range (FUNC_NAME, index);
|
||||||
|
|
||||||
#define GENERIC_INTEGER_GETTER_PROLOGUE(_sign) \
|
#define GENERIC_INTEGER_GETTER_PROLOGUE(_sign) \
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
/* Copyright (C) 1995-2004, 2006-2015, 2017, 2019
|
||||||
* 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
|
* Free Software Foundation, Inc.
|
||||||
* 2014, 2015, 2017 Free Software Foundation, Inc.
|
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -621,6 +620,11 @@ fport_seek (SCM port, scm_t_off offset, int whence)
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
scm_syserror ("fport_seek");
|
scm_syserror ("fport_seek");
|
||||||
|
|
||||||
|
/* Check to make sure the result fits in scm_t_off,
|
||||||
|
which might be smaller than off_t_or_off64_t. */
|
||||||
|
if (result > SCM_T_OFF_MAX)
|
||||||
|
scm_num_overflow ("fport_seek");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (C) 1998,1999,2000,2001, 2006, 2008, 2009, 2011,
|
/* Copyright (C) 1998-2001, 2006, 2008, 2009, 2011-2013, 2019
|
||||||
* 2012, 2013 Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -89,7 +89,7 @@ guardian_print (SCM guardian, SCM port, scm_print_state *pstate SCM_UNUSED)
|
||||||
scm_uintprint ((scm_t_bits) g, 16, port);
|
scm_uintprint ((scm_t_bits) g, 16, port);
|
||||||
|
|
||||||
scm_puts (" (reachable: ", port);
|
scm_puts (" (reachable: ", port);
|
||||||
scm_display (scm_from_uint (g->live), port);
|
scm_display (scm_from_ulong (g->live), port);
|
||||||
scm_puts (" unreachable: ", port);
|
scm_puts (" unreachable: ", port);
|
||||||
scm_display (scm_length (g->zombies), port);
|
scm_display (scm_length (g->zombies), port);
|
||||||
scm_puts (")", port);
|
scm_puts (")", port);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (C) 1995-2001, 2003-2004, 2006-2017
|
/* Copyright (C) 1995-2001, 2003-2004, 2006-2017, 2019
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -2236,7 +2236,8 @@ SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
|
||||||
"@var{port} is not supplied, the current-input-port is used.")
|
"@var{port} is not supplied, the current-input-port is used.")
|
||||||
#define FUNC_NAME s_scm_unread_string
|
#define FUNC_NAME s_scm_unread_string
|
||||||
{
|
{
|
||||||
int n;
|
size_t n;
|
||||||
|
|
||||||
SCM_VALIDATE_STRING (1, str);
|
SCM_VALIDATE_STRING (1, str);
|
||||||
if (SCM_UNBNDP (port))
|
if (SCM_UNBNDP (port))
|
||||||
port = scm_current_input_port ();
|
port = scm_current_input_port ();
|
||||||
|
@ -3734,8 +3735,8 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
|
||||||
{
|
{
|
||||||
scm_t_port *pt = SCM_PORT (fd_port);
|
scm_t_port *pt = SCM_PORT (fd_port);
|
||||||
scm_t_port_type *ptob = SCM_PORT_TYPE (fd_port);
|
scm_t_port_type *ptob = SCM_PORT_TYPE (fd_port);
|
||||||
off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
|
scm_t_off off = scm_to_off_t (offset);
|
||||||
off_t_or_off64_t rv;
|
scm_t_off rv;
|
||||||
|
|
||||||
if (ptob->seek && how == SEEK_CUR && off == 0)
|
if (ptob->seek && how == SEEK_CUR && off == 0)
|
||||||
{
|
{
|
||||||
|
@ -3749,7 +3750,7 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
|
||||||
scm_dynwind_end ();
|
scm_dynwind_end ();
|
||||||
rv -= scm_port_buffer_can_take (pt->read_buf, &tmp);
|
rv -= scm_port_buffer_can_take (pt->read_buf, &tmp);
|
||||||
rv += scm_port_buffer_can_take (pt->write_buf, &tmp);
|
rv += scm_port_buffer_can_take (pt->write_buf, &tmp);
|
||||||
return scm_from_off_t_or_off64_t (rv);
|
return scm_from_off_t (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ptob->seek || !pt->rw_random)
|
if (!ptob->seek || !pt->rw_random)
|
||||||
|
@ -3770,7 +3771,7 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
|
||||||
|
|
||||||
scm_i_clear_pending_eof (fd_port);
|
scm_i_clear_pending_eof (fd_port);
|
||||||
|
|
||||||
return scm_from_off_t_or_off64_t (rv);
|
return scm_from_off_t (rv);
|
||||||
}
|
}
|
||||||
else /* file descriptor?. */
|
else /* file descriptor?. */
|
||||||
{
|
{
|
||||||
|
@ -3855,7 +3856,7 @@ SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
|
||||||
}
|
}
|
||||||
else if (SCM_OPOUTPORTP (object))
|
else if (SCM_OPOUTPORTP (object))
|
||||||
{
|
{
|
||||||
off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
|
scm_t_off c_length = scm_to_off_t (length);
|
||||||
scm_t_port_type *ptob = SCM_PORT_TYPE (object);
|
scm_t_port_type *ptob = SCM_PORT_TYPE (object);
|
||||||
|
|
||||||
if (!ptob->truncate)
|
if (!ptob->truncate)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* Copyright (C) 2009, 2010, 2011, 2013-2015, 2018 Free Software Foundation, Inc.
|
/* Copyright (C) 2009-2011, 2013-2015, 2018, 2019
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <intprops.h>
|
||||||
|
|
||||||
#include "libguile/_scm.h"
|
#include "libguile/_scm.h"
|
||||||
#include "libguile/bytevectors.h"
|
#include "libguile/bytevectors.h"
|
||||||
|
@ -130,21 +132,27 @@ bytevector_input_port_seek (SCM port, scm_t_off offset, int whence)
|
||||||
#define FUNC_NAME "bytevector_input_port_seek"
|
#define FUNC_NAME "bytevector_input_port_seek"
|
||||||
{
|
{
|
||||||
struct bytevector_input_port *stream = (void *) SCM_STREAM (port);
|
struct bytevector_input_port *stream = (void *) SCM_STREAM (port);
|
||||||
|
size_t base;
|
||||||
scm_t_off target;
|
scm_t_off target;
|
||||||
|
|
||||||
if (whence == SEEK_CUR)
|
if (whence == SEEK_CUR)
|
||||||
target = offset + stream->pos;
|
base = stream->pos;
|
||||||
else if (whence == SEEK_SET)
|
else if (whence == SEEK_SET)
|
||||||
target = offset;
|
base = 0;
|
||||||
else if (whence == SEEK_END)
|
else if (whence == SEEK_END)
|
||||||
target = offset + SCM_BYTEVECTOR_LENGTH (stream->bytevector);
|
base = SCM_BYTEVECTOR_LENGTH (stream->bytevector);
|
||||||
else
|
else
|
||||||
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, "invalid `seek' parameter");
|
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, "invalid `seek' parameter");
|
||||||
|
|
||||||
|
if (base > SCM_T_OFF_MAX
|
||||||
|
|| INT_ADD_OVERFLOW ((scm_t_off) base, offset))
|
||||||
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
target = (scm_t_off) base + offset;
|
||||||
|
|
||||||
if (target >= 0 && target <= SCM_BYTEVECTOR_LENGTH (stream->bytevector))
|
if (target >= 0 && target <= SCM_BYTEVECTOR_LENGTH (stream->bytevector))
|
||||||
stream->pos = target;
|
stream->pos = target;
|
||||||
else
|
else
|
||||||
scm_out_of_range (FUNC_NAME, scm_from_long (offset));
|
scm_out_of_range (FUNC_NAME, scm_from_off_t (offset));
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
@ -224,6 +232,9 @@ custom_binary_port_seek (SCM port, scm_t_off offset, int whence)
|
||||||
/* We just want to know the current position. */
|
/* We just want to know the current position. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (INT_ADD_OVERFLOW (offset, c_result))
|
||||||
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
|
||||||
offset += c_result;
|
offset += c_result;
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
}
|
}
|
||||||
|
@ -231,7 +242,7 @@ custom_binary_port_seek (SCM port, scm_t_off offset, int whence)
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
{
|
{
|
||||||
if (SCM_LIKELY (scm_is_true (stream->set_position_x)))
|
if (SCM_LIKELY (scm_is_true (stream->set_position_x)))
|
||||||
result = scm_call_1 (stream->set_position_x, scm_from_int (offset));
|
result = scm_call_1 (stream->set_position_x, scm_from_off_t (offset));
|
||||||
else
|
else
|
||||||
scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
|
scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
|
||||||
"seekable R6RS custom binary port");
|
"seekable R6RS custom binary port");
|
||||||
|
@ -454,7 +465,8 @@ SCM_DEFINE (scm_get_bytevector_n_x, "get-bytevector-n!", 4, 0, 0,
|
||||||
|
|
||||||
c_len = SCM_BYTEVECTOR_LENGTH (bv);
|
c_len = SCM_BYTEVECTOR_LENGTH (bv);
|
||||||
|
|
||||||
if (SCM_UNLIKELY (c_start + c_count > c_len))
|
if (SCM_UNLIKELY (c_len < c_start
|
||||||
|
|| (c_len - c_start < c_count)))
|
||||||
scm_out_of_range (FUNC_NAME, count);
|
scm_out_of_range (FUNC_NAME, count);
|
||||||
|
|
||||||
if (SCM_LIKELY (c_count > 0))
|
if (SCM_LIKELY (c_count > 0))
|
||||||
|
@ -511,7 +523,7 @@ SCM_DEFINE (scm_get_bytevector_all, "get-bytevector-all", 1, 0, 0,
|
||||||
#define FUNC_NAME s_scm_get_bytevector_all
|
#define FUNC_NAME s_scm_get_bytevector_all
|
||||||
{
|
{
|
||||||
SCM result;
|
SCM result;
|
||||||
unsigned c_len, c_count;
|
size_t c_len, c_count;
|
||||||
size_t c_read, c_total;
|
size_t c_read, c_total;
|
||||||
|
|
||||||
SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
|
SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
|
||||||
|
@ -522,10 +534,14 @@ SCM_DEFINE (scm_get_bytevector_all, "get-bytevector-all", 1, 0, 0,
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (c_total + c_read > c_len)
|
if (c_read > c_len - c_total)
|
||||||
{
|
{
|
||||||
/* Grow the bytevector. */
|
/* Grow the bytevector. */
|
||||||
SCM prev = result;
|
SCM prev = result;
|
||||||
|
|
||||||
|
if (INT_ADD_OVERFLOW (c_len, c_len))
|
||||||
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
|
||||||
result = scm_c_make_bytevector (c_len * 2);
|
result = scm_c_make_bytevector (c_len * 2);
|
||||||
memcpy (SCM_BYTEVECTOR_CONTENTS (result),
|
memcpy (SCM_BYTEVECTOR_CONTENTS (result),
|
||||||
SCM_BYTEVECTOR_CONTENTS (prev),
|
SCM_BYTEVECTOR_CONTENTS (prev),
|
||||||
|
@ -593,20 +609,17 @@ SCM_DEFINE (scm_put_bytevector, "put-bytevector", 2, 2, 0,
|
||||||
if (!scm_is_eq (start, SCM_UNDEFINED))
|
if (!scm_is_eq (start, SCM_UNDEFINED))
|
||||||
{
|
{
|
||||||
c_start = scm_to_size_t (start);
|
c_start = scm_to_size_t (start);
|
||||||
|
if (SCM_UNLIKELY (c_start > c_len))
|
||||||
|
scm_out_of_range (FUNC_NAME, start);
|
||||||
|
|
||||||
if (!scm_is_eq (count, SCM_UNDEFINED))
|
if (!scm_is_eq (count, SCM_UNDEFINED))
|
||||||
{
|
{
|
||||||
c_count = scm_to_size_t (count);
|
c_count = scm_to_size_t (count);
|
||||||
if (SCM_UNLIKELY (c_start + c_count > c_len))
|
if (SCM_UNLIKELY (c_count > c_len - c_start))
|
||||||
scm_out_of_range (FUNC_NAME, count);
|
scm_out_of_range (FUNC_NAME, count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
c_count = c_len - c_start;
|
||||||
if (SCM_UNLIKELY (c_start > c_len))
|
|
||||||
scm_out_of_range (FUNC_NAME, start);
|
|
||||||
else
|
|
||||||
c_count = c_len - c_start;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c_start = 0, c_count = c_len;
|
c_start = 0, c_count = c_len;
|
||||||
|
@ -636,20 +649,17 @@ SCM_DEFINE (scm_unget_bytevector, "unget-bytevector", 2, 2, 0,
|
||||||
if (!scm_is_eq (start, SCM_UNDEFINED))
|
if (!scm_is_eq (start, SCM_UNDEFINED))
|
||||||
{
|
{
|
||||||
c_start = scm_to_size_t (start);
|
c_start = scm_to_size_t (start);
|
||||||
|
if (SCM_UNLIKELY (c_start > c_len))
|
||||||
|
scm_out_of_range (FUNC_NAME, start);
|
||||||
|
|
||||||
if (!scm_is_eq (count, SCM_UNDEFINED))
|
if (!scm_is_eq (count, SCM_UNDEFINED))
|
||||||
{
|
{
|
||||||
c_count = scm_to_size_t (count);
|
c_count = scm_to_size_t (count);
|
||||||
if (SCM_UNLIKELY (c_start + c_count > c_len))
|
if (SCM_UNLIKELY (c_count > c_len - c_start))
|
||||||
scm_out_of_range (FUNC_NAME, count);
|
scm_out_of_range (FUNC_NAME, count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
c_count = c_len - c_start;
|
||||||
if (SCM_UNLIKELY (c_start > c_len))
|
|
||||||
scm_out_of_range (FUNC_NAME, start);
|
|
||||||
else
|
|
||||||
c_count = c_len - c_start;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c_start = 0, c_count = c_len;
|
c_start = 0, c_count = c_len;
|
||||||
|
@ -722,17 +732,20 @@ bytevector_output_port_buffer_grow (scm_t_bytevector_output_port_buffer *buf,
|
||||||
char *new_buf;
|
char *new_buf;
|
||||||
size_t new_size;
|
size_t new_size;
|
||||||
|
|
||||||
for (new_size = buf->total_len
|
|
||||||
? buf->total_len : SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER_INITIAL_SIZE;
|
|
||||||
new_size < min_size;
|
|
||||||
new_size *= 2);
|
|
||||||
|
|
||||||
if (buf->buffer)
|
if (buf->buffer)
|
||||||
new_buf = scm_gc_realloc ((void *) buf->buffer, buf->total_len,
|
{
|
||||||
new_size, SCM_GC_BYTEVECTOR_OUTPUT_PORT);
|
if (INT_ADD_OVERFLOW (buf->total_len, buf->total_len))
|
||||||
|
scm_num_overflow ("bytevector_output_port_buffer_grow");
|
||||||
|
new_size = max (min_size, buf->total_len * 2);
|
||||||
|
new_buf = scm_gc_realloc ((void *) buf->buffer, buf->total_len,
|
||||||
|
new_size, SCM_GC_BYTEVECTOR_OUTPUT_PORT);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
new_buf = scm_gc_malloc_pointerless (new_size,
|
{
|
||||||
SCM_GC_BYTEVECTOR_OUTPUT_PORT);
|
new_size = max (min_size, SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER_INITIAL_SIZE);
|
||||||
|
new_buf = scm_gc_malloc_pointerless (new_size,
|
||||||
|
SCM_GC_BYTEVECTOR_OUTPUT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
buf->buffer = new_buf;
|
buf->buffer = new_buf;
|
||||||
buf->total_len = new_size;
|
buf->total_len = new_size;
|
||||||
|
@ -763,13 +776,18 @@ make_bytevector_output_port (void)
|
||||||
/* Write octets from WRITE_BUF to the backing store. */
|
/* Write octets from WRITE_BUF to the backing store. */
|
||||||
static size_t
|
static size_t
|
||||||
bytevector_output_port_write (SCM port, SCM src, size_t start, size_t count)
|
bytevector_output_port_write (SCM port, SCM src, size_t start, size_t count)
|
||||||
|
#define FUNC_NAME "bytevector_output_port_write"
|
||||||
{
|
{
|
||||||
scm_t_bytevector_output_port_buffer *buf;
|
scm_t_bytevector_output_port_buffer *buf;
|
||||||
|
|
||||||
buf = SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER (port);
|
buf = SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER (port);
|
||||||
|
|
||||||
if (buf->pos + count > buf->total_len)
|
if (count > buf->total_len - buf->pos)
|
||||||
bytevector_output_port_buffer_grow (buf, buf->pos + count);
|
{
|
||||||
|
if (INT_ADD_OVERFLOW (buf->pos, count))
|
||||||
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
bytevector_output_port_buffer_grow (buf, buf->pos + count);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (buf->buffer + buf->pos, SCM_BYTEVECTOR_CONTENTS (src) + start, count);
|
memcpy (buf->buffer + buf->pos, SCM_BYTEVECTOR_CONTENTS (src) + start, count);
|
||||||
|
|
||||||
|
@ -778,29 +796,36 @@ bytevector_output_port_write (SCM port, SCM src, size_t start, size_t count)
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
static scm_t_off
|
static scm_t_off
|
||||||
bytevector_output_port_seek (SCM port, scm_t_off offset, int whence)
|
bytevector_output_port_seek (SCM port, scm_t_off offset, int whence)
|
||||||
#define FUNC_NAME "bytevector_output_port_seek"
|
#define FUNC_NAME "bytevector_output_port_seek"
|
||||||
{
|
{
|
||||||
scm_t_bytevector_output_port_buffer *buf;
|
scm_t_bytevector_output_port_buffer *buf;
|
||||||
|
size_t base;
|
||||||
scm_t_off target;
|
scm_t_off target;
|
||||||
|
|
||||||
buf = SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER (port);
|
buf = SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER (port);
|
||||||
|
|
||||||
if (whence == SEEK_CUR)
|
if (whence == SEEK_CUR)
|
||||||
target = offset + buf->pos;
|
base = buf->pos;
|
||||||
else if (whence == SEEK_SET)
|
else if (whence == SEEK_SET)
|
||||||
target = offset;
|
base = 0;
|
||||||
else if (whence == SEEK_END)
|
else if (whence == SEEK_END)
|
||||||
target = offset + buf->len;
|
base = buf->len;
|
||||||
else
|
else
|
||||||
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, "invalid `seek' parameter");
|
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, "invalid `seek' parameter");
|
||||||
|
|
||||||
|
if (base > SCM_T_OFF_MAX
|
||||||
|
|| INT_ADD_OVERFLOW ((scm_t_off) base, offset))
|
||||||
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
target = (scm_t_off) base + offset;
|
||||||
|
|
||||||
if (target >= 0 && target <= buf->len)
|
if (target >= 0 && target <= buf->len)
|
||||||
buf->pos = target;
|
buf->pos = target;
|
||||||
else
|
else
|
||||||
scm_out_of_range (FUNC_NAME, scm_from_long (offset));
|
scm_out_of_range (FUNC_NAME, scm_from_off_t (offset));
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <unistr.h>
|
#include <unistr.h>
|
||||||
#include <uniconv.h>
|
#include <uniconv.h>
|
||||||
#include <c-strcase.h>
|
#include <c-strcase.h>
|
||||||
|
#include <intprops.h>
|
||||||
|
|
||||||
#include "striconveh.h"
|
#include "striconveh.h"
|
||||||
|
|
||||||
|
@ -124,6 +125,12 @@ make_stringbuf (size_t len)
|
||||||
lenhist[1000]++;
|
lenhist[1000]++;
|
||||||
#endif
|
#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,
|
buf = SCM_PACK_POINTER (scm_gc_malloc_pointerless (STRINGBUF_HEADER_BYTES + len + 1,
|
||||||
"string"));
|
"string"));
|
||||||
|
|
||||||
|
@ -150,9 +157,16 @@ make_wide_stringbuf (size_t len)
|
||||||
lenhist[1000]++;
|
lenhist[1000]++;
|
||||||
#endif
|
#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);
|
raw_len = (len + 1) * sizeof (scm_t_wchar);
|
||||||
buf = SCM_PACK_POINTER (scm_gc_malloc_pointerless (STRINGBUF_HEADER_BYTES + raw_len,
|
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_TYPE (buf, STRINGBUF_TAG | STRINGBUF_F_WIDE);
|
||||||
SCM_SET_CELL_WORD_1 (buf, (scm_t_bits) len);
|
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);
|
s = SCM_CAR (l);
|
||||||
SCM_VALIDATE_STRING (SCM_ARGn, s);
|
SCM_VALIDATE_STRING (SCM_ARGn, s);
|
||||||
len = scm_i_string_length (s);
|
len = scm_i_string_length (s);
|
||||||
if (((size_t) -1) - total < len)
|
if (INT_ADD_OVERFLOW (total, len))
|
||||||
scm_num_overflow (s_scm_string_append);
|
scm_num_overflow (FUNC_NAME);
|
||||||
total += len;
|
total += len;
|
||||||
if (!scm_i_is_narrow_string (s))
|
if (!scm_i_is_narrow_string (s))
|
||||||
wide = 1;
|
wide = 1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (C) 1995, 1996, 1998-2003, 2005, 2006, 2009-2014,
|
/* Copyright (C) 1995, 1996, 1998-2003, 2005, 2006, 2009-2014,
|
||||||
* 2016-2018 Free Software Foundation, Inc.
|
* 2016-2019 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <intprops.h>
|
||||||
|
|
||||||
#include "libguile/bytevectors.h"
|
#include "libguile/bytevectors.h"
|
||||||
#include "libguile/eval.h"
|
#include "libguile/eval.h"
|
||||||
|
@ -82,16 +83,21 @@ string_port_read (SCM port, SCM dst, size_t start, size_t count)
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
string_port_write (SCM port, SCM src, size_t start, size_t count)
|
string_port_write (SCM port, SCM src, size_t start, size_t count)
|
||||||
|
#define FUNC_NAME "string_port_write"
|
||||||
{
|
{
|
||||||
struct string_port *stream = (void *) SCM_STREAM (port);
|
struct string_port *stream = (void *) SCM_STREAM (port);
|
||||||
|
size_t old_size = SCM_BYTEVECTOR_LENGTH (stream->bytevector);
|
||||||
|
|
||||||
if (SCM_BYTEVECTOR_LENGTH (stream->bytevector) < stream->pos + count)
|
if (count > old_size - stream->pos)
|
||||||
{
|
{
|
||||||
SCM new_bv;
|
SCM new_bv;
|
||||||
size_t new_size;
|
size_t new_size;
|
||||||
|
|
||||||
new_size = max (SCM_BYTEVECTOR_LENGTH (stream->bytevector) * 2,
|
if (INT_ADD_OVERFLOW (stream->pos, count))
|
||||||
stream->pos + count);
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
|
||||||
|
/* If (old_size * 2) overflows, it's harmless. */
|
||||||
|
new_size = max (old_size * 2, stream->pos + count);
|
||||||
new_bv = scm_c_make_bytevector (new_size);
|
new_bv = scm_c_make_bytevector (new_size);
|
||||||
memcpy (SCM_BYTEVECTOR_CONTENTS (new_bv),
|
memcpy (SCM_BYTEVECTOR_CONTENTS (new_bv),
|
||||||
SCM_BYTEVECTOR_CONTENTS (stream->bytevector),
|
SCM_BYTEVECTOR_CONTENTS (stream->bytevector),
|
||||||
|
@ -108,27 +114,34 @@ string_port_write (SCM port, SCM src, size_t start, size_t count)
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
static scm_t_off
|
static scm_t_off
|
||||||
string_port_seek (SCM port, scm_t_off offset, int whence)
|
string_port_seek (SCM port, scm_t_off offset, int whence)
|
||||||
#define FUNC_NAME "string_port_seek"
|
#define FUNC_NAME "string_port_seek"
|
||||||
{
|
{
|
||||||
struct string_port *stream = (void *) SCM_STREAM (port);
|
struct string_port *stream = (void *) SCM_STREAM (port);
|
||||||
|
size_t base;
|
||||||
scm_t_off target;
|
scm_t_off target;
|
||||||
|
|
||||||
if (whence == SEEK_CUR)
|
if (whence == SEEK_CUR)
|
||||||
target = offset + stream->pos;
|
base = stream->pos;
|
||||||
else if (whence == SEEK_SET)
|
else if (whence == SEEK_SET)
|
||||||
target = offset;
|
base = 0;
|
||||||
else if (whence == SEEK_END)
|
else if (whence == SEEK_END)
|
||||||
target = offset + stream->len;
|
base = stream->len;
|
||||||
else
|
else
|
||||||
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, "invalid `seek' parameter");
|
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, "invalid `seek' parameter");
|
||||||
|
|
||||||
|
if (base > SCM_T_OFF_MAX
|
||||||
|
|| INT_ADD_OVERFLOW ((scm_t_off) base, offset))
|
||||||
|
scm_num_overflow (FUNC_NAME);
|
||||||
|
target = (scm_t_off) base + offset;
|
||||||
|
|
||||||
if (target >= 0 && target <= stream->len)
|
if (target >= 0 && target <= stream->len)
|
||||||
stream->pos = target;
|
stream->pos = target;
|
||||||
else
|
else
|
||||||
scm_out_of_range (FUNC_NAME, scm_from_long (offset));
|
scm_out_of_range (FUNC_NAME, scm_from_off_t (offset));
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
@ -143,7 +156,7 @@ string_port_truncate (SCM port, scm_t_off length)
|
||||||
if (0 <= length && stream->pos <= length && length <= stream->len)
|
if (0 <= length && stream->pos <= length && length <= stream->len)
|
||||||
stream->len = length;
|
stream->len = length;
|
||||||
else
|
else
|
||||||
scm_out_of_range (FUNC_NAME, scm_from_off_t_or_off64_t (length));
|
scm_out_of_range (FUNC_NAME, scm_from_off_t (length));
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2006, 2008, 2009, 2010,
|
/* Copyright (C) 1995, 1996, 1998-2001, 2006, 2008-2012, 2014, 2019
|
||||||
* 2011, 2012, 2014 Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -245,7 +245,7 @@ scm_c_make_vector (size_t k, SCM fill)
|
||||||
#define FUNC_NAME s_scm_make_vector
|
#define FUNC_NAME s_scm_make_vector
|
||||||
{
|
{
|
||||||
SCM vector;
|
SCM vector;
|
||||||
unsigned long int j;
|
size_t j;
|
||||||
|
|
||||||
SCM_ASSERT_RANGE (1, scm_from_size_t (k), k <= VECTOR_MAX_LENGTH);
|
SCM_ASSERT_RANGE (1, scm_from_size_t (k), k <= VECTOR_MAX_LENGTH);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue