guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/08: Improve overflow checks in bytevector, string, an


From: Mark H. Weaver
Subject: [Guile-commits] 01/08: Improve overflow checks in bytevector, string, and I/O operations.
Date: Tue, 18 Jun 2019 02:08:19 -0400 (EDT)

mhw pushed a commit to branch stable-2.2
in repository guile.

commit 91ba73b397fcc2a36ae7e434522a924c7a8887d0
Author: Mark H Weaver <address@hidden>
Date:   Fri Apr 19 00:59:59 2019 -0400

    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'.
---
 libguile/bytevectors.c |  27 ++++++++-----
 libguile/fports.c      |  10 +++--
 libguile/guardians.c   |   6 +--
 libguile/ports.c       |  17 +++++----
 libguile/r6rs-ports.c  | 101 ++++++++++++++++++++++++++++++-------------------
 libguile/strings.c     |  20 ++++++++--
 libguile/strports.c    |  31 ++++++++++-----
 libguile/vectors.c     |   6 +--
 8 files changed, 142 insertions(+), 76 deletions(-)

diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c
index e42a48c..0ac5ea6 100644
--- a/libguile/bytevectors.c
+++ b/libguile/bytevectors.c
@@ -84,7 +84,8 @@
   c_len = SCM_BYTEVECTOR_LENGTH (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);
 
 #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;
 
   if (SCM_UNLIKELY (element_type > SCM_ARRAY_ELEMENT_TYPE_LAST
-                    || scm_i_array_element_type_sizes[element_type] < 8
-                    || len >= (((size_t) -1)
-                               / 
(scm_i_array_element_type_sizes[element_type]/8))))
+                    || scm_i_array_element_type_sizes[element_type] < 8))
     /* This would be an internal Guile programming error */
     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
                    && SCM_BYTEVECTOR_P (scm_null_bytevector)))
     ret = scm_null_bytevector;
@@ -252,7 +258,7 @@ make_bytevector_from_buffer (size_t len, void *contents,
       size_t c_len;
 
       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);
 
@@ -510,7 +516,7 @@ SCM_DEFINE (scm_bytevector_length, "bytevector-length", 1, 
0, 0,
            "Return the length (in bytes) of @var{bv}.")
 #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
 
@@ -595,9 +601,11 @@ SCM_DEFINE (scm_bytevector_copy_x, "bytevector-copy!", 5, 
0, 0,
   c_source_len = SCM_BYTEVECTOR_LENGTH (source);
   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);
-  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);
 
   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.  */                                                       \
   if (SCM_UNLIKELY (c_size == 0 || c_size >= (SIZE_MAX >> 3)))         \
     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);
 
 #define GENERIC_INTEGER_GETTER_PROLOGUE(_sign)          \
diff --git a/libguile/fports.c b/libguile/fports.c
index ee6ac0b..5de08d3 100644
--- a/libguile/fports.c
+++ b/libguile/fports.c
@@ -1,6 +1,5 @@
-/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- *   2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
- *   2014, 2015, 2017 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2004, 2006-2015, 2017, 2019
+ *   Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * 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)
     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;
 }
 
diff --git a/libguile/guardians.c b/libguile/guardians.c
index cd4d9f3..2c63b58 100644
--- a/libguile/guardians.c
+++ b/libguile/guardians.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 1998,1999,2000,2001, 2006, 2008, 2009, 2011,
- *   2012, 2013 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2001, 2006, 2008, 2009, 2011-2013, 2019
+ *   Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * 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_puts (" (reachable: ", port);
-  scm_display (scm_from_uint (g->live), port);
+  scm_display (scm_from_ulong (g->live), port);
   scm_puts (" unreachable: ", port);
   scm_display (scm_length (g->zombies), port);
   scm_puts (")", port);
diff --git a/libguile/ports.c b/libguile/ports.c
index bb25704..900de67 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 1995-2001, 2003-2004, 2006-2017
- * Free Software Foundation, Inc.
+/* Copyright (C) 1995-2001, 2003-2004, 2006-2017, 2019
+ *   Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * 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.")
 #define FUNC_NAME s_scm_unread_string
 {
-  int n;
+  size_t n;
+
   SCM_VALIDATE_STRING (1, str);
   if (SCM_UNBNDP (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_type *ptob = SCM_PORT_TYPE (fd_port);
-      off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
-      off_t_or_off64_t rv;
+      scm_t_off off = scm_to_off_t (offset);
+      scm_t_off rv;
 
       if (ptob->seek && how == SEEK_CUR && off == 0)
         {
@@ -3749,7 +3750,7 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
           scm_dynwind_end ();
           rv -= scm_port_buffer_can_take (pt->read_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)
@@ -3770,7 +3771,7 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
 
       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?.  */
     {
@@ -3855,7 +3856,7 @@ SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
     }
   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);
 
       if (!ptob->truncate)
diff --git a/libguile/r6rs-ports.c b/libguile/r6rs-ports.c
index 16c1480..90387e8 100644
--- a/libguile/r6rs-ports.c
+++ b/libguile/r6rs-ports.c
@@ -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
  * modify it under the terms of the GNU Lesser General Public License
@@ -24,6 +25,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <assert.h>
+#include <intprops.h>
 
 #include "libguile/_scm.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"
 {
   struct bytevector_input_port *stream = (void *) SCM_STREAM (port);
+  size_t base;
   scm_t_off target;
 
   if (whence == SEEK_CUR)
-    target = offset + stream->pos;
+    base = stream->pos;
   else if (whence == SEEK_SET)
-    target = offset;
+    base = 0;
   else if (whence == SEEK_END)
-    target = offset + SCM_BYTEVECTOR_LENGTH (stream->bytevector);
+    base = SCM_BYTEVECTOR_LENGTH (stream->bytevector);
   else
     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))
     stream->pos = target;
   else
-    scm_out_of_range (FUNC_NAME, scm_from_long (offset));
+    scm_out_of_range (FUNC_NAME, scm_from_off_t (offset));
 
   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.  */
          break;
 
+        if (INT_ADD_OVERFLOW (offset, c_result))
+          scm_num_overflow (FUNC_NAME);
+
        offset += c_result;
        /* Fall through.  */
       }
@@ -231,7 +242,7 @@ custom_binary_port_seek (SCM port, scm_t_off offset, int 
whence)
     case SEEK_SET:
       {
        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
          scm_wrong_type_arg_msg (FUNC_NAME, 0, 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);
 
-  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);
 
   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
 {
   SCM result;
-  unsigned c_len, c_count;
+  size_t c_len, c_count;
   size_t c_read, c_total;
 
   SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
@@ -522,10 +534,14 @@ SCM_DEFINE (scm_get_bytevector_all, "get-bytevector-all", 
1, 0, 0,
 
   do
     {
-      if (c_total + c_read > c_len)
+      if (c_read > c_len - c_total)
        {
          /* Grow the bytevector.  */
           SCM prev = result;
+
+          if (INT_ADD_OVERFLOW (c_len, c_len))
+            scm_num_overflow (FUNC_NAME);
+
           result = scm_c_make_bytevector (c_len * 2);
           memcpy (SCM_BYTEVECTOR_CONTENTS (result),
                   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))
     {
       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))
        {
          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);
        }
       else
-       {
-         if (SCM_UNLIKELY (c_start > c_len))
-           scm_out_of_range (FUNC_NAME, start);
-         else
-           c_count = c_len - c_start;
-       }
+        c_count = c_len - c_start;
     }
   else
     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))
     {
       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))
        {
          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);
        }
       else
-       {
-         if (SCM_UNLIKELY (c_start > c_len))
-           scm_out_of_range (FUNC_NAME, start);
-         else
-           c_count = c_len - c_start;
-       }
+        c_count = c_len - c_start;
     }
   else
     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;
   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)
-    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
-    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->total_len = new_size;
@@ -763,13 +776,18 @@ make_bytevector_output_port (void)
 /* Write octets from WRITE_BUF to the backing store.  */
 static size_t
 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;
 
   buf = SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER (port);
 
-  if (buf->pos + count > buf->total_len)
-    bytevector_output_port_buffer_grow (buf, buf->pos + count);
+  if (count > buf->total_len - buf->pos)
+    {
+      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);
 
@@ -778,29 +796,36 @@ bytevector_output_port_write (SCM port, SCM src, size_t 
start, size_t count)
 
   return count;
 }
+#undef FUNC_NAME
 
 static scm_t_off
 bytevector_output_port_seek (SCM port, scm_t_off offset, int whence)
 #define FUNC_NAME "bytevector_output_port_seek"
 {
   scm_t_bytevector_output_port_buffer *buf;
+  size_t base;
   scm_t_off target;
 
   buf = SCM_BYTEVECTOR_OUTPUT_PORT_BUFFER (port);
 
   if (whence == SEEK_CUR)
-    target = offset + buf->pos;
+    base = buf->pos;
   else if (whence == SEEK_SET)
-    target = offset;
+    base = 0;
   else if (whence == SEEK_END)
-    target = offset + buf->len;
+    base = buf->len;
   else
     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)
     buf->pos = target;
   else
-    scm_out_of_range (FUNC_NAME, scm_from_long (offset));
+    scm_out_of_range (FUNC_NAME, scm_from_off_t (offset));
 
   return target;
 }
diff --git a/libguile/strings.c b/libguile/strings.c
index e5c7f87..9497a3f 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;
diff --git a/libguile/strports.c b/libguile/strports.c
index b01282e..876a62a 100644
--- a/libguile/strports.c
+++ b/libguile/strports.c
@@ -1,5 +1,5 @@
 /* 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
  * modify it under the terms of the GNU Lesser General Public License
@@ -28,6 +28,7 @@
 
 #include <stdio.h>
 #include <unistd.h>
+#include <intprops.h>
 
 #include "libguile/bytevectors.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
 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);
+  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;
       size_t new_size;
 
-      new_size = max (SCM_BYTEVECTOR_LENGTH (stream->bytevector) * 2,
-                      stream->pos + count);
+      if (INT_ADD_OVERFLOW (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);
       memcpy (SCM_BYTEVECTOR_CONTENTS (new_bv),
               SCM_BYTEVECTOR_CONTENTS (stream->bytevector),
@@ -108,27 +114,34 @@ string_port_write (SCM port, SCM src, size_t start, 
size_t count)
 
   return count;
 }
+#undef FUNC_NAME
 
 static scm_t_off
 string_port_seek (SCM port, scm_t_off offset, int whence)
 #define FUNC_NAME "string_port_seek"
 {
   struct string_port *stream = (void *) SCM_STREAM (port);
+  size_t base;
   scm_t_off target;
 
   if (whence == SEEK_CUR)
-    target = offset + stream->pos;
+    base = stream->pos;
   else if (whence == SEEK_SET)
-    target = offset;
+    base = 0;
   else if (whence == SEEK_END)
-    target = offset + stream->len;
+    base = stream->len;
   else
     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)
     stream->pos = target;
   else
-    scm_out_of_range (FUNC_NAME, scm_from_long (offset));
+    scm_out_of_range (FUNC_NAME, scm_from_off_t (offset));
 
   return target;
 }
@@ -143,7 +156,7 @@ string_port_truncate (SCM port, scm_t_off length)
   if (0 <= length && stream->pos <= length && length <= stream->len)
     stream->len = length;
   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
 
diff --git a/libguile/vectors.c b/libguile/vectors.c
index 328cf6f..acdda5d 100644
--- a/libguile/vectors.c
+++ b/libguile/vectors.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2006, 2008, 2009, 2010,
- *   2011, 2012, 2014 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1998-2001, 2006, 2008-2012, 2014, 2019
+ *   Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * 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
 {
   SCM vector;
-  unsigned long int j;
+  size_t j;
 
   SCM_ASSERT_RANGE (1, scm_from_size_t (k), k <= VECTOR_MAX_LENGTH);
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]