From 354759a9f20791bb9ab5e0fe5107950968e0ac8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sun, 6 May 2018 18:33:32 +0200 Subject: [PATCH] Further improvements to memcpy_s(), memset_s(), and their man pages. --- configure.ac | 3 +-- include/cryb/Makefile.am | 2 +- include/cryb/memcpy_s.h | 7 ++--- include/cryb/memset_s.h | 6 ++--- include/cryb/{rsize.h => types.h} | 8 ++++-- lib/core/cryb_memcpy_s.3 | 43 ++++++++++++++++++++++--------- lib/core/cryb_memcpy_s.c | 14 ++++++---- lib/core/cryb_memset_s.3 | 41 +++++++++++++++++++++-------- lib/core/cryb_memset_s.c | 13 ++++++---- 9 files changed, 93 insertions(+), 44 deletions(-) rename include/cryb/{rsize.h => types.h} (93%) diff --git a/configure.ac b/configure.ac index 212e280..7464828 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,7 @@ AC_TYPE_UINT8_T AC_TYPE_UINTMAX_T AC_TYPE_UINTPTR_T +AC_CHECK_TYPES([errno_t], [], [], [[#include ]]) AC_CHECK_TYPES([rsize_t], [], [], [[#include ]]) AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include ]]) @@ -119,8 +120,6 @@ AC_CHECK_HEADERS([sys/resource.h]) AC_CHECK_FUNCS([setrlimit]) # C11 features -# XXX our version has an incorrect prototype due to the lack of a test -# for the existence of rsize_t and RSIZE_MAX. AC_CHECK_FUNCS([memcpy_s memset_s]) ############################################################################ diff --git a/include/cryb/Makefile.am b/include/cryb/Makefile.am index b66ec7c..368aee4 100644 --- a/include/cryb/Makefile.am +++ b/include/cryb/Makefile.am @@ -24,12 +24,12 @@ cryb_HEADERS += \ endian.h \ memcpy_s.h \ memset_s.h \ - rsize.h \ strchrnul.h \ string.h \ strlcat.h \ strlcmp.h \ strlcpy.h \ + types.h \ wcschrnul.h \ wcslcat.h \ wcslcmp.h \ diff --git a/include/cryb/memcpy_s.h b/include/cryb/memcpy_s.h index 45e59cd..34ab970 100644 --- a/include/cryb/memcpy_s.h +++ b/include/cryb/memcpy_s.h @@ -34,13 +34,14 @@ #include #endif -#ifndef CRYB_RSIZE_H_INCLUDED -#include +#ifndef CRYB_TYPES_H_INCLUDED +#include #endif CRYB_BEGIN -int cryb_memcpy_s(void *, rsize_t, const void *, rsize_t); +errno_t cryb_memcpy_s(void * restrict, rsize_t, const void * restrict, + rsize_t); #if !HAVE_MEMCPY_S #undef memcpy_s diff --git a/include/cryb/memset_s.h b/include/cryb/memset_s.h index fad0265..a1dc267 100644 --- a/include/cryb/memset_s.h +++ b/include/cryb/memset_s.h @@ -34,13 +34,13 @@ #include #endif -#ifndef CRYB_RSIZE_H_INCLUDED -#include +#ifndef CRYB_TYPES_H_INCLUDED +#include #endif CRYB_BEGIN -int cryb_memset_s(void *, rsize_t, int, rsize_t); +errno_t cryb_memset_s(void *, rsize_t, int, rsize_t); #if !HAVE_MEMSET_S #undef memset_s diff --git a/include/cryb/rsize.h b/include/cryb/types.h similarity index 93% rename from include/cryb/rsize.h rename to include/cryb/types.h index 5d0bf3b..19f28b0 100644 --- a/include/cryb/rsize.h +++ b/include/cryb/types.h @@ -27,8 +27,12 @@ * SUCH DAMAGE. */ -#ifndef CRYB_RSIZE_H_INCLUDED -#define CRYB_RSIZE_H_INCLUDED +#ifndef CRYB_TYPES_H_INCLUDED +#define CRYB_TYPES_H_INCLUDED + +#if !HAVE_ERRNO_T +typedef int errno_t; +#endif #if !HAVE_RSIZE_T typedef size_t rsize_t; diff --git a/lib/core/cryb_memcpy_s.3 b/lib/core/cryb_memcpy_s.3 index 5c3fb41..5000b2d 100644 --- a/lib/core/cryb_memcpy_s.3 +++ b/lib/core/cryb_memcpy_s.3 @@ -1,5 +1,5 @@ .\"- -.\" Copyright (c) 2015 Universitetet i Oslo +.\" Copyright (c) 2015-2018 Universitetet i Oslo .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 15, 2015 +.Dd May 6, 2018 .Dt cryb_memcpy_s 3 .Os .Sh NAME @@ -36,8 +36,8 @@ .Lb libcryb-core .Sh SYNOPSIS .In cryb/memcpy_s.h -.Ft void * -.Fn cryb_memcpy_s "void *d" "size_t dsz" "const void *s" "size_t n" +.Ft errno_t +.Fn cryb_memcpy_s "void * restrict d" "rsize_t dsz" "const void * restrict s" "rsize_t n" .Sh DESCRIPTION The .Nm cryb_memcpy_s @@ -57,7 +57,7 @@ is is greater than .Va dsz or -.Dv SIZE_MAX +.Dv RSIZE_MAX or the source and destination overlap, the buffer pointed to by .Va d is filled with zeroes and an error is returned. @@ -98,17 +98,36 @@ header provides a macro as an alias to .Fn cryb_memcpy_s . .Pp -The argument and return types for -.Nm -differ from those of its C11 equivalent, as it is expected to be used -in environments in which -.Vt rsize_t +Software that includes +.In cryb/memcpy_s.h +should ensure that the +.Dv HAVE_ERRNO_T , +.Dv HAVE_RSIZE_T , +.Dv HAVE_RSIZE_MAX and -.Dv RSIZE_MAX -are not defined. +.Dv HAVE_MEMCPY_S +macros correctly reflect the availability of these features at compile +time. +For projects that use the GNU autotools, this can be achieved by +including the following code in +.Pa configure.ac : +.Bd -literal -offset indent +AC_CHECK_TYPES([errno_t], [], [], [[#include ]]) +AC_CHECK_TYPES([rsize_t], [], [], [[#include ]]) +AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include ]]) +AC_CHECK_FUNCS([memcpy_s]) +.Ed .Sh SEE ALSO .Xr cryb_memset_s 3 , .Xr memcpy 3 +.Sh STANDARDS +The +.Fn cryb_memcpy_s +function is equivalent to the +.Fn memcpy_s +function described in ISO/IEC 9899:2011 +.Pq Dq C11 +section K.3.7.1.1. .Sh AUTHORS The .Fn cryb_memcpy_s diff --git a/lib/core/cryb_memcpy_s.c b/lib/core/cryb_memcpy_s.c index cb56637..159d25d 100644 --- a/lib/core/cryb_memcpy_s.c +++ b/lib/core/cryb_memcpy_s.c @@ -32,7 +32,6 @@ #endif #include -#include #include #include @@ -43,10 +42,15 @@ /* * Like memcpy(), but checks for overflow and overwrites the destination * range with zeroes on error. + * + * ISO/IEC 9899:2011 K.3.7.1.1 */ -int -cryb_memcpy_s(void *d, rsize_t dsz, const void *s, rsize_t n) +errno_t +cryb_memcpy_s(void * restrict d, rsize_t dsz, const void * restrict s, + rsize_t n) { + volatile uint8_t *D; + const uint8_t *S; unsigned int i; /* unrecoverable errors */ @@ -71,7 +75,7 @@ CRYB_DISABLE_COVERAGE CRYB_RESTORE_COVERAGE return (EINVAL); } - for (i = 0; i < dsz && i < n; ++i) - ((volatile uint8_t *)d)[i] = ((const uint8_t *)s)[i]; + for (D = d, S = s, i = 0; i < dsz && i < n; ++i) + D[i] = S[i]; return (0); } diff --git a/lib/core/cryb_memset_s.3 b/lib/core/cryb_memset_s.3 index d9df865..edea09a 100644 --- a/lib/core/cryb_memset_s.3 +++ b/lib/core/cryb_memset_s.3 @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 15, 2015 +.Dd May 6, 2018 .Dt cryb_memset_s 3 .Os .Sh NAME @@ -36,8 +36,8 @@ .Lb libcryb-core .Sh SYNOPSIS .In cryb/memset_s.h -.Ft void * -.Fn cryb_memset_s "void *d" "size_t dsz" "int ch" "size_t n" +.Ft errno_t +.Fn cryb_memset_s "void *d" "rsize_t dsz" "int ch" "rsize_t n" .Sh DESCRIPTION The .Nm cryb_memset_s @@ -74,7 +74,7 @@ Either or both of the and .Va n arguments were greater than -.Dv SIZE_MAX . +.Dv RSIZE_MAX . .It Bq Er EOVERFLOW The .Va n @@ -92,17 +92,36 @@ header provides a macro as an alias to .Fn cryb_memset_s . .Pp -The argument and return types for -.Nm -differ from those of its C11 equivalent, as it is expected to be used -in environments in which -.Vt rsize_t +Software that includes +.In cryb/memset_s.h +should ensure that the +.Dv HAVE_ERRNO_T , +.Dv HAVE_RSIZE_T , +.Dv HAVE_RSIZE_MAX and -.Dv RSIZE_MAX -are not defined. +.Dv HAVE_MEMSET_S +macros correctly reflect the availability of these features at compile +time. +For projects that use the GNU autotools, this can be achieved by +including the following code in +.Pa configure.ac : +.Bd -literal -offset indent +AC_CHECK_TYPES([errno_t], [], [], [[#include ]]) +AC_CHECK_TYPES([rsize_t], [], [], [[#include ]]) +AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include ]]) +AC_CHECK_FUNCS([memset_s]) +.Ed .Sh SEE ALSO .Xr cryb_memcpy_s 3 , .Xr memset 3 +.Sh STANDARDS +The +.Fn cryb_memset_s +function is equivalent to the +.Fn memset_s +function described in ISO/IEC 9899:2011 +.Pq Dq C11 +section K.3.7.4.1. .Sh AUTHORS The .Fn cryb_memset_s diff --git a/lib/core/cryb_memset_s.c b/lib/core/cryb_memset_s.c index b408bf4..21154d2 100644 --- a/lib/core/cryb_memset_s.c +++ b/lib/core/cryb_memset_s.c @@ -32,7 +32,6 @@ #endif #include -#include #include #include @@ -42,11 +41,15 @@ /* * Like memset(), but checks for overflow and guarantees that the buffer * is overwritten even if the data will never be read. + * + * ISO/IEC 9899:2011 K.3.7.4.1 */ -int -cryb_memset_s(void *d, rsize_t dsz, int ch, rsize_t n) +errno_t +cryb_memset_s(void *d, rsize_t dsz, int c, rsize_t n) { + volatile uint8_t *D; unsigned int i; + uint8_t C; if (d == NULL) return (EINVAL); @@ -54,8 +57,8 @@ CRYB_DISABLE_COVERAGE if (dsz > RSIZE_MAX || n > RSIZE_MAX) return (ERANGE); CRYB_RESTORE_COVERAGE - for (i = 0; i < n && i < dsz; ++i) - ((volatile uint8_t *)d)[i] = (uint8_t)ch; + for (D = d, C = (uint8_t)c, i = 0; i < n && i < dsz; ++i) + D[i] = C; if (n > dsz) return (EOVERFLOW); return (0);