[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 03/05: Avoid passing NULL to 'memcpy' and 'memcmp'.
From: |
Mark H. Weaver |
Subject: |
[Guile-commits] 03/05: Avoid passing NULL to 'memcpy' and 'memcmp'. |
Date: |
Tue, 16 Apr 2019 16:57:27 -0400 (EDT) |
mhw pushed a commit to branch stable-2.2
in repository guile.
commit 6b1de860ab2360e8679205aecdc1c837744a4b9c
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 | 9 ++++++++-
libguile/stime.c | 3 ++-
libguile/strings.c | 11 ++++++++---
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c
index 1d41297..e42a48c 100644
--- a/libguile/bytevectors.c
+++ b/libguile/bytevectors.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2015, 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
@@ -662,7 +662,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 af7c1d9..a4d71e8 100644
--- a/libguile/srfi-14.c
+++ b/libguile/srfi-14.c
@@ -1,6 +1,7 @@
/* srfi-14.c --- SRFI-14 procedures for Guile
*
- * Copyright (C) 2001, 2004, 2006, 2007, 2009, 2011 Free Software Foundation,
Inc.
+ * Copyright (C) 2001, 2004, 2006, 2007, 2009, 2011,
+ * 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
@@ -363,6 +364,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 060a496..b681d7e 100644
--- a/libguile/stime.c
+++ b/libguile/stime.c
@@ -340,10 +340,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 5f35617..62ff2e3 100644
--- a/libguile/strings.c
+++ b/libguile/strings.c
@@ -1,5 +1,5 @@
/* Copyright (C) 1995, 1996, 1998, 2000, 2001, 2004, 2006,
- * 2008-2016, 2018 Free Software Foundation, Inc.
+ * 2008-2016, 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
@@ -2283,13 +2283,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);