Further improvements to memcpy_s(), memset_s(), and their man pages.

This commit is contained in:
Dag-Erling Smørgrav 2018-05-06 18:33:32 +02:00
parent a1bf5e87f0
commit 354759a9f2
9 changed files with 93 additions and 44 deletions

View file

@ -51,6 +51,7 @@ AC_TYPE_UINT8_T
AC_TYPE_UINTMAX_T AC_TYPE_UINTMAX_T
AC_TYPE_UINTPTR_T AC_TYPE_UINTPTR_T
AC_CHECK_TYPES([errno_t], [], [], [[#include <errno.h>]])
AC_CHECK_TYPES([rsize_t], [], [], [[#include <stdint.h>]]) AC_CHECK_TYPES([rsize_t], [], [], [[#include <stdint.h>]])
AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include <stdint.h>]]) AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include <stdint.h>]])
@ -119,8 +120,6 @@ AC_CHECK_HEADERS([sys/resource.h])
AC_CHECK_FUNCS([setrlimit]) AC_CHECK_FUNCS([setrlimit])
# C11 features # 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]) AC_CHECK_FUNCS([memcpy_s memset_s])
############################################################################ ############################################################################

View file

@ -24,12 +24,12 @@ cryb_HEADERS += \
endian.h \ endian.h \
memcpy_s.h \ memcpy_s.h \
memset_s.h \ memset_s.h \
rsize.h \
strchrnul.h \ strchrnul.h \
string.h \ string.h \
strlcat.h \ strlcat.h \
strlcmp.h \ strlcmp.h \
strlcpy.h \ strlcpy.h \
types.h \
wcschrnul.h \ wcschrnul.h \
wcslcat.h \ wcslcat.h \
wcslcmp.h \ wcslcmp.h \

View file

@ -34,13 +34,14 @@
#include <cryb/to.h> #include <cryb/to.h>
#endif #endif
#ifndef CRYB_RSIZE_H_INCLUDED #ifndef CRYB_TYPES_H_INCLUDED
#include <cryb/rsize.h> #include <cryb/types.h>
#endif #endif
CRYB_BEGIN 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 #if !HAVE_MEMCPY_S
#undef memcpy_s #undef memcpy_s

View file

@ -34,13 +34,13 @@
#include <cryb/to.h> #include <cryb/to.h>
#endif #endif
#ifndef CRYB_RSIZE_H_INCLUDED #ifndef CRYB_TYPES_H_INCLUDED
#include <cryb/rsize.h> #include <cryb/types.h>
#endif #endif
CRYB_BEGIN 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 #if !HAVE_MEMSET_S
#undef memset_s #undef memset_s

View file

@ -27,8 +27,12 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#ifndef CRYB_RSIZE_H_INCLUDED #ifndef CRYB_TYPES_H_INCLUDED
#define CRYB_RSIZE_H_INCLUDED #define CRYB_TYPES_H_INCLUDED
#if !HAVE_ERRNO_T
typedef int errno_t;
#endif
#if !HAVE_RSIZE_T #if !HAVE_RSIZE_T
typedef size_t rsize_t; typedef size_t rsize_t;

View file

@ -1,5 +1,5 @@
.\"- .\"-
.\" Copyright (c) 2015 Universitetet i Oslo .\" Copyright (c) 2015-2018 Universitetet i Oslo
.\" All rights reserved. .\" All rights reserved.
.\" .\"
.\" Redistribution and use in source and binary forms, with or without .\" 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 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd December 15, 2015 .Dd May 6, 2018
.Dt cryb_memcpy_s 3 .Dt cryb_memcpy_s 3
.Os .Os
.Sh NAME .Sh NAME
@ -36,8 +36,8 @@
.Lb libcryb-core .Lb libcryb-core
.Sh SYNOPSIS .Sh SYNOPSIS
.In cryb/memcpy_s.h .In cryb/memcpy_s.h
.Ft void * .Ft errno_t
.Fn cryb_memcpy_s "void *d" "size_t dsz" "const void *s" "size_t n" .Fn cryb_memcpy_s "void * restrict d" "rsize_t dsz" "const void * restrict s" "rsize_t n"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm cryb_memcpy_s .Nm cryb_memcpy_s
@ -57,7 +57,7 @@ is
is greater than is greater than
.Va dsz .Va dsz
or or
.Dv SIZE_MAX .Dv RSIZE_MAX
or the source and destination overlap, the buffer pointed to by or the source and destination overlap, the buffer pointed to by
.Va d .Va d
is filled with zeroes and an error is returned. is filled with zeroes and an error is returned.
@ -98,17 +98,36 @@ header provides a
macro as an alias to macro as an alias to
.Fn cryb_memcpy_s . .Fn cryb_memcpy_s .
.Pp .Pp
The argument and return types for Software that includes
.Nm .In cryb/memcpy_s.h
differ from those of its C11 equivalent, as it is expected to be used should ensure that the
in environments in which .Dv HAVE_ERRNO_T ,
.Vt rsize_t .Dv HAVE_RSIZE_T ,
.Dv HAVE_RSIZE_MAX
and and
.Dv RSIZE_MAX .Dv HAVE_MEMCPY_S
are not defined. 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 <errno.h>]])
AC_CHECK_TYPES([rsize_t], [], [], [[#include <stdint.h>]])
AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include <stdint.h>]])
AC_CHECK_FUNCS([memcpy_s])
.Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr cryb_memset_s 3 , .Xr cryb_memset_s 3 ,
.Xr memcpy 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 .Sh AUTHORS
The The
.Fn cryb_memcpy_s .Fn cryb_memcpy_s

View file

@ -32,7 +32,6 @@
#endif #endif
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -43,10 +42,15 @@
/* /*
* Like memcpy(), but checks for overflow and overwrites the destination * Like memcpy(), but checks for overflow and overwrites the destination
* range with zeroes on error. * range with zeroes on error.
*
* ISO/IEC 9899:2011 K.3.7.1.1
*/ */
int errno_t
cryb_memcpy_s(void *d, rsize_t dsz, const void *s, rsize_t n) 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; unsigned int i;
/* unrecoverable errors */ /* unrecoverable errors */
@ -71,7 +75,7 @@ CRYB_DISABLE_COVERAGE
CRYB_RESTORE_COVERAGE CRYB_RESTORE_COVERAGE
return (EINVAL); return (EINVAL);
} }
for (i = 0; i < dsz && i < n; ++i) for (D = d, S = s, i = 0; i < dsz && i < n; ++i)
((volatile uint8_t *)d)[i] = ((const uint8_t *)s)[i]; D[i] = S[i];
return (0); return (0);
} }

View file

@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd December 15, 2015 .Dd May 6, 2018
.Dt cryb_memset_s 3 .Dt cryb_memset_s 3
.Os .Os
.Sh NAME .Sh NAME
@ -36,8 +36,8 @@
.Lb libcryb-core .Lb libcryb-core
.Sh SYNOPSIS .Sh SYNOPSIS
.In cryb/memset_s.h .In cryb/memset_s.h
.Ft void * .Ft errno_t
.Fn cryb_memset_s "void *d" "size_t dsz" "int ch" "size_t n" .Fn cryb_memset_s "void *d" "rsize_t dsz" "int ch" "rsize_t n"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm cryb_memset_s .Nm cryb_memset_s
@ -74,7 +74,7 @@ Either or both of the
and and
.Va n .Va n
arguments were greater than arguments were greater than
.Dv SIZE_MAX . .Dv RSIZE_MAX .
.It Bq Er EOVERFLOW .It Bq Er EOVERFLOW
The The
.Va n .Va n
@ -92,17 +92,36 @@ header provides a
macro as an alias to macro as an alias to
.Fn cryb_memset_s . .Fn cryb_memset_s .
.Pp .Pp
The argument and return types for Software that includes
.Nm .In cryb/memset_s.h
differ from those of its C11 equivalent, as it is expected to be used should ensure that the
in environments in which .Dv HAVE_ERRNO_T ,
.Vt rsize_t .Dv HAVE_RSIZE_T ,
.Dv HAVE_RSIZE_MAX
and and
.Dv RSIZE_MAX .Dv HAVE_MEMSET_S
are not defined. 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 <errno.h>]])
AC_CHECK_TYPES([rsize_t], [], [], [[#include <stdint.h>]])
AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include <stdint.h>]])
AC_CHECK_FUNCS([memset_s])
.Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr cryb_memcpy_s 3 , .Xr cryb_memcpy_s 3 ,
.Xr memset 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 .Sh AUTHORS
The The
.Fn cryb_memset_s .Fn cryb_memset_s

View file

@ -32,7 +32,6 @@
#endif #endif
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -42,11 +41,15 @@
/* /*
* Like memset(), but checks for overflow and guarantees that the buffer * Like memset(), but checks for overflow and guarantees that the buffer
* is overwritten even if the data will never be read. * is overwritten even if the data will never be read.
*
* ISO/IEC 9899:2011 K.3.7.4.1
*/ */
int errno_t
cryb_memset_s(void *d, rsize_t dsz, int ch, rsize_t n) cryb_memset_s(void *d, rsize_t dsz, int c, rsize_t n)
{ {
volatile uint8_t *D;
unsigned int i; unsigned int i;
uint8_t C;
if (d == NULL) if (d == NULL)
return (EINVAL); return (EINVAL);
@ -54,8 +57,8 @@ CRYB_DISABLE_COVERAGE
if (dsz > RSIZE_MAX || n > RSIZE_MAX) if (dsz > RSIZE_MAX || n > RSIZE_MAX)
return (ERANGE); return (ERANGE);
CRYB_RESTORE_COVERAGE CRYB_RESTORE_COVERAGE
for (i = 0; i < n && i < dsz; ++i) for (D = d, C = (uint8_t)c, i = 0; i < n && i < dsz; ++i)
((volatile uint8_t *)d)[i] = (uint8_t)ch; D[i] = C;
if (n > dsz) if (n > dsz)
return (EOVERFLOW); return (EOVERFLOW);
return (0); return (0);