guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 44/55: Avoid passing NULL to 'memcpy' and 'memcmp'.


From: Andy Wingo
Subject: [Guile-commits] 44/55: Avoid passing NULL to 'memcpy' and 'memcmp'.
Date: Thu, 23 May 2019 11:52:43 -0400 (EDT)

wingo pushed a commit to branch master
in repository guile.

commit 980d8265c2dc35d6e02e540c9041cbf0975dfede
Author: Mark H Weaver <address@hidden>
Date:   Mon Apr 1 22:11:35 2019 -0400

    Avoid passing NULL to 'memcpy' and 'memcmp'.
    
    Reported by Jeffrey Walton <address@hidden> in
    <https://lists.gnu.org/archive/html/guile-devel/2019-03/msg00001.html>.
    
    Note that C11 section 7.1.4 (Use of library functions) states that:
    "unless explicitly stated otherwise in the detailed descriptions [of
    library functions] that follow: If an argument to a function has an
    invalid value (such as ... a null pointer ...) ..., the behavior is
    undefined."  Note that 'strxfrm' is an example of a standard C function
    that explicitly states otherwise, allowing NULL to be passed in the
    first argument if the size argument is zero, but no similar allowance is
    specified for 'memcpy' or 'memcmp'.
    
    * libguile/bytevectors.c (scm_uniform_array_to_bytevector): Call memcpy
    only if 'byte_len' is non-zero.
    * libguile/srfi-14.c (charsets_equal): Call memcmp only if the number of
    ranges is non-zero.
    * libguile/stime.c (setzone): Pass 1-character buffer to
    'scm_to_locale_stringbuf', instead of NULL.
    * libguile/strings.c (scm_to_locale_stringbuf): Call memcpy only if the
    number of bytes to copy is non-zero.
---
 libguile/bytevectors.c |  8 ++++++--
 libguile/srfi-14.c     | 10 +++++++---
 libguile/stime.c       |  3 ++-
 libguile/strings.c     | 11 ++++++++---
 4 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c
index 6e3c950..b4dc2ea 100644
--- a/libguile/bytevectors.c
+++ b/libguile/bytevectors.c
@@ -1,4 +1,4 @@
-/* Copyright 2009-2015,2018
+/* Copyright 2009-2015,2018-2019
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -671,7 +671,11 @@ SCM_DEFINE (scm_uniform_array_to_bytevector, 
"uniform-array->bytevector",
     SCM_MISC_ERROR ("uniform elements larger than 8 bits must fill whole 
bytes", SCM_EOL);
 
   ret = make_bytevector (byte_len, SCM_ARRAY_ELEMENT_TYPE_VU8);
-  memcpy (SCM_BYTEVECTOR_CONTENTS (ret), elts, byte_len);
+  if (byte_len != 0)
+    /* Empty arrays may have elements == NULL.  We must avoid passing
+       NULL to memcpy, even if the length is zero, to avoid undefined
+       behavior. */
+    memcpy (SCM_BYTEVECTOR_CONTENTS (ret), elts, byte_len);
 
   scm_array_handle_release (&h);
 
diff --git a/libguile/srfi-14.c b/libguile/srfi-14.c
index 42ee85d..bbddb05 100644
--- a/libguile/srfi-14.c
+++ b/libguile/srfi-14.c
@@ -1,6 +1,4 @@
-/* srfi-14.c --- SRFI-14 procedures for Guile
-
-   Copyright 2001,2004,2006-2007,2009,2011,2018
+/* Copyright 2001,2004,2006-2007,2009,2011,2018-2019
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -377,6 +375,12 @@ charsets_equal (scm_t_char_set *a, scm_t_char_set *b)
   if (a->len != b->len)
     return 0;
 
+  /* Empty charsets may have ranges == NULL.  We must avoid passing
+     NULL to memcmp, even if the length is zero, to avoid undefined
+     behavior. */
+  if (a->len == 0)
+    return 1;
+
   if (memcmp (a->ranges, b->ranges, sizeof (scm_t_char_range) * a->len) != 0)
     return 0;
 
diff --git a/libguile/stime.c b/libguile/stime.c
index 2b9651c..6c17eb9 100644
--- a/libguile/stime.c
+++ b/libguile/stime.c
@@ -342,10 +342,11 @@ setzone (SCM zone, int pos, const char *subr)
   if (!SCM_UNBNDP (zone))
     {
       static char *tmpenv[2];
+      char dummy_buf[1];
       char *buf;
       size_t zone_len;
       
-      zone_len = scm_to_locale_stringbuf (zone, NULL, 0);
+      zone_len = scm_to_locale_stringbuf (zone, dummy_buf, 0);
       buf = scm_malloc (zone_len + sizeof (tzvar) + 1);
       strcpy (buf, tzvar);
       buf[sizeof(tzvar)-1] = '=';
diff --git a/libguile/strings.c b/libguile/strings.c
index a0a1555..b366f5b 100644
--- a/libguile/strings.c
+++ b/libguile/strings.c
@@ -1,4 +1,4 @@
-/* Copyright 1995-1996,1998,2000-2001,2004,2006,2008-2016,2018
+/* Copyright 1995-1996,1998,2000-2001,2004,2006,2008-2016,2018-2019
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -2288,13 +2288,18 @@ scm_to_stringn (SCM str, size_t *lenp, const char 
*encoding,
 size_t
 scm_to_locale_stringbuf (SCM str, char *buf, size_t max_len)
 {
-  size_t len;
+  size_t len, copy_len;
   char *result = NULL;
   if (!scm_is_string (str))
     scm_wrong_type_arg_msg (NULL, 0, str, "string");
   result = scm_to_locale_stringn (str, &len);
 
-  memcpy (buf, result, (len > max_len) ? max_len : len);
+  copy_len = (len > max_len) ? max_len : len;
+  if (copy_len != 0)
+    /* Some users of 'scm_to_locale_stringbuf' may pass NULL for buf
+       when max_len is zero, and yet we must avoid passing NULL to
+       memcpy to avoid undefined behavior. */
+    memcpy (buf, result, copy_len);
   free (result);
 
   scm_remember_upto_here_1 (str);



reply via email to

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