diff --git a/configure.ac b/configure.ac index 9efe72c..5ecfe58 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,10 @@ 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 ]]) + ############################################################################ # # Headers and functions @@ -116,9 +120,7 @@ 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([memset_s]) +AC_CHECK_FUNCS([memcpy_s memset_s]) ############################################################################ # diff --git a/include/cryb/Makefile.am b/include/cryb/Makefile.am index 40abdb4..368aee4 100644 --- a/include/cryb/Makefile.am +++ b/include/cryb/Makefile.am @@ -22,12 +22,14 @@ cryb_HEADERS += \ ctype.h \ defs.h \ endian.h \ + memcpy_s.h \ memset_s.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 new file mode 100644 index 0000000..34ab970 --- /dev/null +++ b/include/cryb/memcpy_s.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2015-2018 The University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CRYB_MEMCPY_S_H_INCLUDED +#define CRYB_MEMCPY_S_H_INCLUDED + +#ifndef CRYB_TO +#include +#endif + +#ifndef CRYB_TYPES_H_INCLUDED +#include +#endif + +CRYB_BEGIN + +errno_t cryb_memcpy_s(void * restrict, rsize_t, const void * restrict, + rsize_t); + +#if !HAVE_MEMCPY_S +#undef memcpy_s +#define memcpy_s(arg, ...) cryb_memcpy_s(arg, __VA_ARGS__) +#endif + +CRYB_END + +#endif diff --git a/include/cryb/memset_s.h b/include/cryb/memset_s.h index 9e86886..a1dc267 100644 --- a/include/cryb/memset_s.h +++ b/include/cryb/memset_s.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 The University of Oslo + * Copyright (c) 2015-2018 The University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,9 +34,13 @@ #include #endif +#ifndef CRYB_TYPES_H_INCLUDED +#include +#endif + CRYB_BEGIN -int cryb_memset_s(void *, size_t, int, size_t); +errno_t cryb_memset_s(void *, rsize_t, int, rsize_t); #if !HAVE_MEMSET_S #undef memset_s diff --git a/include/cryb/types.h b/include/cryb/types.h new file mode 100644 index 0000000..19f28b0 --- /dev/null +++ b/include/cryb/types.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2018 The University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#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; +#endif + +#if !HAVE_RSIZE_MAX +#define RSIZE_MAX (SIZE_MAX >> 1) +#endif + +#endif diff --git a/lib/core/Makefile.am b/lib/core/Makefile.am index 95ddb28..03fcf58 100644 --- a/lib/core/Makefile.am +++ b/lib/core/Makefile.am @@ -4,6 +4,7 @@ lib_LTLIBRARIES = libcryb-core.la libcryb_core_la_SOURCES = \ cryb_assert.c \ + cryb_memcpy_s.c \ cryb_memset_s.c \ cryb_strchrnul.c \ cryb_string.c \ @@ -21,6 +22,8 @@ libcryb_core_la_SOURCES = \ EXTRA_DIST = cryb_string_impl.c dist_man3_MANS = \ + cryb_memcpy_s.3 \ + cryb_memset_s.3 \ cryb_strlcat.3 \ cryb_strlcpy.3 diff --git a/lib/core/cryb_memcpy_s.3 b/lib/core/cryb_memcpy_s.3 new file mode 100644 index 0000000..5000b2d --- /dev/null +++ b/lib/core/cryb_memcpy_s.3 @@ -0,0 +1,136 @@ +.\"- +.\" Copyright (c) 2015-2018 Universitetet i Oslo +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote +.\" products derived from this software without specific prior written +.\" permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd May 6, 2018 +.Dt cryb_memcpy_s 3 +.Os +.Sh NAME +.Nm cryb_memcpy_s +.Nd safely copy one buffer to another +.Sh LIBRARY +.Lb libcryb-core +.Sh SYNOPSIS +.In cryb/memcpy_s.h +.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 +function copies the first +.Va n +bytes of the buffer pointed to by +.Va s +into the buffer pointed to by +.Va d , +of size +.Va dsz . +If +.Va s +is +.Dv NULL , +.Va n +is greater than +.Va dsz +or +.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. +.Sh RETURN VALUES +The +.Fn cryb_memcpy_s +function returns zero if successful and a non-zero error code if an +error occurred. +.Sh ERRORS +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Va d +argument was +.Dv NULL +or the source and destination ranges were found to overlap. +.It Bq Er ERANGE +Either or both of the +.Va dsz +and +.Va n +arguments were greater than +.Dv SIZE_MAX . +.It Bq Er EOVERFLOW +The +.Va n +argument was greater than the +.Va dsz +argument. +.El +.Sh IMPLEMENTATION NOTES +If the +.Dv HAVE_MEMCPY_S +preprocessor macro is defined to 0 or undefined, the +.In cryb/memcpy_s.h +header provides a +.Fn memcpy_s +macro as an alias to +.Fn cryb_memcpy_s . +.Pp +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 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 +function and this manual page were written for the University of Oslo +by +.An Dag-Erling Sm\(/orgrav Aq Mt d.e.smorgrav@usit.uio.no . diff --git a/lib/core/cryb_memcpy_s.c b/lib/core/cryb_memcpy_s.c new file mode 100644 index 0000000..159d25d --- /dev/null +++ b/lib/core/cryb_memcpy_s.c @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 2015-2018 The University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include + +/* + * Like memcpy(), but checks for overflow and overwrites the destination + * range with zeroes on error. + * + * ISO/IEC 9899:2011 K.3.7.1.1 + */ +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 */ + if (d == NULL) + return (EINVAL); +CRYB_DISABLE_COVERAGE + if (dsz > RSIZE_MAX) + return (ERANGE); +CRYB_RESTORE_COVERAGE + /* recoverable errors */ + if (s == NULL || n > dsz || +CRYB_DISABLE_COVERAGE + n > RSIZE_MAX || +CRYB_RESTORE_COVERAGE + (s >= d && s < d + dsz) || (d >= s && d < s + n)) { + memset_s(d, dsz, 0, dsz); + if (n > dsz) + return (EOVERFLOW); +CRYB_DISABLE_COVERAGE + if (n > RSIZE_MAX) + return (ERANGE); +CRYB_RESTORE_COVERAGE + return (EINVAL); + } + 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 new file mode 100644 index 0000000..edea09a --- /dev/null +++ b/lib/core/cryb_memset_s.3 @@ -0,0 +1,130 @@ +.\"- +.\" Copyright (c) 2015 Universitetet i Oslo +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote +.\" products derived from this software without specific prior written +.\" permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd May 6, 2018 +.Dt cryb_memset_s 3 +.Os +.Sh NAME +.Nm cryb_memset_s +.Nd safely fill a buffer +.Sh LIBRARY +.Lb libcryb-core +.Sh SYNOPSIS +.In cryb/memset_s.h +.Ft errno_t +.Fn cryb_memset_s "void *d" "rsize_t dsz" "int ch" "rsize_t n" +.Sh DESCRIPTION +The +.Nm cryb_memset_s +function overwrites the first +.Va n +bytes of the buffer pointed to by +.Va d , +of size +.Va dsz , +with copies of the least-significant byte of +.Va ch . +If +.Va n +is greater than +.Va dsz , +only +.Va dsz +bytes are overwritten, and an error is returned. +.Sh RETURN VALUES +The +.Nm +function returns zero if successful and a non-zero error code if an +error occurred. +.Sh ERRORS +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Va d +argument was +.Dv NULL . +.It Bq Er ERANGE +Either or both of the +.Va dsz +and +.Va n +arguments were greater than +.Dv RSIZE_MAX . +.It Bq Er EOVERFLOW +The +.Va n +argument was greater than the +.Va dsz +argument. +.El +.Sh IMPLEMENTATION NOTES +If the +.Dv HAVE_MEMSET_S +preprocessor macro is defined to 0 or undefined, the +.In cryb/memset_s.h +header provides a +.Fn memset_s +macro as an alias to +.Fn cryb_memset_s . +.Pp +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 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 +function and this manual page were written for the University of Oslo +by +.An Dag-Erling Sm\(/orgrav Aq Mt d.e.smorgrav@usit.uio.no . diff --git a/lib/core/cryb_memset_s.c b/lib/core/cryb_memset_s.c index 7a1750b..21154d2 100644 --- a/lib/core/cryb_memset_s.c +++ b/lib/core/cryb_memset_s.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 The University of Oslo + * Copyright (c) 2015-2018 The University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,22 +35,31 @@ #include #include +#include #include /* * 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 *s, size_t smax, int c, size_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 (s == NULL) + if (d == NULL) return (EINVAL); - for (i = 0; i < n && i < smax; ++i) - ((volatile unsigned char *)s)[i] = (unsigned char)c; - if (n > smax) +CRYB_DISABLE_COVERAGE + if (dsz > RSIZE_MAX || n > RSIZE_MAX) + return (ERANGE); +CRYB_RESTORE_COVERAGE + for (D = d, C = (uint8_t)c, i = 0; i < n && i < dsz; ++i) + D[i] = C; + if (n > dsz) return (EOVERFLOW); return (0); } diff --git a/t/.gitignore b/t/.gitignore index 9bd7ad9..775a177 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -29,6 +29,7 @@ /t_md4_openssl /t_md5 /t_md5_openssl +/t_memcpy_s /t_memset_s /t_mpi /t_mpi_addsub diff --git a/t/Makefile.am b/t/Makefile.am index 033c672..67c084b 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -94,9 +94,12 @@ TESTS += t_core t_core_LDADD = $(libt) $(libcore) TESTS += t_assert t_assert_LDADD = $(libt) $(libcore) -TESTS += t_ctype t_endian t_memset_s t_strchrnul t_strlcat t_strlcmp t_strlcpy +TESTS += t_ctype t_endian t_memcpy_s t_memset_s t_strchrnul t_strlcat t_strlcmp t_strlcpy +TESTS += t_string t_wstring +EXTRA_DIST += t__string.c t_ctype_LDADD = $(libt) $(libcore) t_endian_LDADD = $(libt) $(libcore) +t_memcpy_s_LDADD = $(libt) $(libcore) t_memset_s_LDADD = $(libt) $(libcore) t_strchrnul_LDADD = $(libt) $(libcore) t_strlcat_LDADD = $(libt) $(libcore) diff --git a/t/t_memcpy_s.c b/t/t_memcpy_s.c new file mode 100644 index 0000000..75ad1dd --- /dev/null +++ b/t/t_memcpy_s.c @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2015-2018 The University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "cryb/impl.h" + +#include +#include +#include +#include + +#undef HAVE_MEMCPY_S +#include +#include +#include + +#define T_BUF_LEN 40 + +struct t_plain_case { + const char *desc; + const char in[T_BUF_LEN]; + rsize_t dsz; + const char s[T_BUF_LEN]; + rsize_t len; + const char out[T_BUF_LEN]; + rsize_t outlen; + int ret; +}; + +/*************************************************************************** + * Plain test cases + */ +static struct t_plain_case t_plain_cases[] = { + { + .desc = "zero", + .in = "squeamish ossifrage", + .dsz = sizeof "squeamish ossifrage" - 1, + .s = "", + .len = 0, + .out = "squeamish ossifrage", + .ret = 0, + }, + { + .desc = "short", + .in = "squeamish ossifrage", + .dsz = sizeof "squeamish ossifrage" - 1, + .s = "the quick", + .len = sizeof "the quick" - 1, + .out = "the quick ossifrage", + .ret = 0, + }, + { + .desc = "exact", + .in = "squeamish ossifrage", + .dsz = sizeof "squeamish ossifrage" - 1, + .s = "the quick brown fox", + .len = sizeof "the quick brown fox" - 1, + .out = "the quick brown fox", + .ret = 0, + }, + { + .desc = "long", + .in = "squeamish ossifrage", + .dsz = sizeof "squeamish ossifrage" - 1, + .s = "the quick brown fox jumps", + .len = sizeof "the quick brown fox jumps" + 1, + .out = "", + .ret = EOVERFLOW, + }, +}; + +static int +t_memcpy_s(char **desc CRYB_UNUSED, void *arg) +{ + struct t_plain_case *t = arg; + char buf[T_BUF_LEN]; + int ret; + + memset(buf, 0, sizeof buf); + strlcpy(buf, t->in, T_BUF_LEN); + ret = memcpy_s(buf, t->dsz, t->s, t->len); + return (t_compare_i(t->ret, ret) & + t_compare_mem(t->out, buf, T_BUF_LEN)); +} + +/*************************************************************************** + * Overlapping test cases + */ + +struct t_overlap_case { + const char *desc; + const char *in; + size_t s_off, d_off; + rsize_t s_len, d_len; + const char out[T_BUF_LEN]; + int ret; +}; + +static struct t_overlap_case t_overlap_cases[] = { + { + /* [<<<<<<<<<< >>>>>>>>>>] */ + .desc = "left, disjoint", + .in = "the magic words are squeamish ossifrage", + .s_off = 0, + .s_len = 15, + .d_off = 16, + .d_len = 23, + .out = "the magic words the magic wordsssifrage", + .ret = 0, + }, + { + /* [<<<<<<<<<<>>>>>>>>>>] */ + .desc = "left, adjoining", + .in = "the magic words are squeamish ossifrage", + .s_off = 0, + .s_len = 16, + .d_off = 16, + .d_len = 23, + .out = "the magic words the magic words sifrage", + .ret = 0, + }, + { + /* [>>>>>>>>>> <<<<<<<<<<] */ + .desc = "right, disjoint", + .in = "the magic words are squeamish ossifrage", + .s_off = 20, + .s_len = 19, + .d_off = 0, + .d_len = 19, + .out = "squeamish ossifrage squeamish ossifrage", + .ret = 0, + }, + { + /* [>>>>>>>>>><<<<<<<<<<] */ + .desc = "right, adjoining", + .in = "the magic words are squeamish ossifrage", + .s_off = 20, + .s_len = 19, + .d_off = 0, + .d_len = 19, + .out = "squeamish ossifrage squeamish ossifrage", + .ret = 0, + }, + { + /* [<<<<<<<>>>>>>>] */ + .desc = "left, overlapping", + .in = "the magic words are squeamish ossifrage", + .s_off = 4, + .s_len = 15, + .d_off = 16, + .d_len = 23, + .out = "the magic words ", + .ret = EINVAL, + }, + { + /* [>>>>>>>>XXXX<<<<<<<<] */ + .desc = "right, overlapping", + .in = "the magic words are squeamish ossifrage", + .s_off = 16, + .s_len = 23, + .d_off = 0, + .d_len = 29, + .out = "\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0" + " ossifrage", + .ret = EINVAL, + }, + { + /* [>>>>>>>>XXXX>>>>>>>>] */ + .desc = "inside", + .in = "the magic words are squeamish ossifrage", + .s_off = 10, + .s_len = 19, + .d_off = 0, + .d_len = 39, + .out = "", + .ret = EINVAL, + }, + { + /* [<<<<<<< sz before overlap is noticed */ + .desc = "outside", + .in = "the magic words are squeamish ossifrage", + .s_off = 0, + .s_len = 39, + .d_off = 10, + .d_len = 19, + .out = "the magic " + "\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0" + " ossifrage", + .ret = EOVERFLOW, + }, + { + /* [XXXXXXXXXXXXXXXXXXXX] */ + .desc = "full overlap", + .in = "the magic words are squeamish ossifrage", + .s_off = 10, + .s_len = 19, + .d_off = 10, + .d_len = 19, + .out = "the magic " + "\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0" + " ossifrage", + .ret = EINVAL, + }, +}; + +static int +t_memcpy_s_overlap(char **desc CRYB_UNUSED, void *arg) +{ + struct t_overlap_case *t = arg; + char buf[T_BUF_LEN]; + int ret; + + strlcpy(buf, t->in, sizeof buf); + ret = memcpy_s(buf + t->d_off, t->d_len, buf + t->s_off, t->s_len); + return (t_compare_i(t->ret, ret) & + t_compare_mem(t->out, buf, T_BUF_LEN)); +} + +/*************************************************************************** + * NULL cases + */ +static int +t_memcpy_s_null_d(char **desc CRYB_UNUSED, void *arg) +{ + char buf[T_BUF_LEN]; + int ret; + + (void)arg; + memset(buf, 'x', sizeof buf); + ret = memcpy_s(NULL, sizeof buf, buf, sizeof buf); + return (t_compare_i(EINVAL, ret)); +} + +static int +t_memcpy_s_null_s(char **desc CRYB_UNUSED, void *arg) +{ + char buf[T_BUF_LEN]; + int ret; + + (void)arg; + memset(buf, 0, sizeof buf); + ret = memcpy_s(buf, sizeof buf, NULL, sizeof buf); + return (t_compare_i(EINVAL, ret) & + t_compare_mem(buf, t_zero, sizeof buf)); +} + + +/*************************************************************************** + * Boilerplate + */ + +int +t_prepare(int argc, char *argv[]) +{ + int i, n; + + (void)argc; + (void)argv; + t_add_test(t_memcpy_s_null_s, NULL, "null source"); + t_add_test(t_memcpy_s_null_d, NULL, "null destination"); + n = sizeof t_plain_cases / sizeof t_plain_cases[0]; + for (i = 0; i < n; ++i) + t_add_test(t_memcpy_s, &t_plain_cases[i], "%s", + t_plain_cases[i].desc); + n = sizeof t_overlap_cases / sizeof t_overlap_cases[0]; + for (i = 0; i < n; ++i) + t_add_test(t_memcpy_s_overlap, &t_overlap_cases[i], "%s", + t_overlap_cases[i].desc); + return (0); +} + +int +main(int argc, char *argv[]) +{ + + t_main(t_prepare, NULL, argc, argv); +} diff --git a/t/t_memset_s.c b/t/t_memset_s.c index 020d5a3..1c935c8 100644 --- a/t/t_memset_s.c +++ b/t/t_memset_s.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 The University of Oslo + * Copyright (c) 2015-2018 The University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,8 +44,8 @@ struct t_case { const char *desc; const char in[T_BUF_LEN]; - size_t smax; - int c; + size_t dsz; + int ch; size_t len; const char out[T_BUF_LEN]; size_t outlen; @@ -59,8 +59,8 @@ static struct t_case t_cases[] = { { .desc = "zero", .in = "squeamish ossifrage", - .smax = sizeof "squeamish ossifrage" - 1, - .c = 'x', + .dsz = sizeof "squeamish ossifrage" - 1, + .ch = 'x', .len = 0, .out = "squeamish ossifrage", .ret = 0, @@ -68,8 +68,8 @@ static struct t_case t_cases[] = { { .desc = "short", .in = "squeamish ossifrage", - .smax = sizeof "squeamish ossifrage" - 1, - .c = 'x', + .dsz = sizeof "squeamish ossifrage" - 1, + .ch = 'x', .len = 9, .out = "xxxxxxxxx ossifrage", .ret = 0, @@ -77,8 +77,8 @@ static struct t_case t_cases[] = { { .desc = "exact", .in = "squeamish ossifrage", - .smax = sizeof "squeamish ossifrage" - 1, - .c = 'x', + .dsz = sizeof "squeamish ossifrage" - 1, + .ch = 'x', .len = sizeof "squeamish ossifrage" - 1, .out = "xxxxxxxxxxxxxxxxxxx", .ret = 0, @@ -86,8 +86,8 @@ static struct t_case t_cases[] = { { .desc = "long", .in = "squeamish ossifrage", - .smax = sizeof "squeamish ossifrage" - 1, - .c = 'x', + .dsz = sizeof "squeamish ossifrage" - 1, + .ch = 'x', .len = sizeof "squeamish ossifrage" + 1, .out = "xxxxxxxxxxxxxxxxxxx", .ret = EOVERFLOW, @@ -104,8 +104,9 @@ t_memset_s(char **desc CRYB_UNUSED, void *arg) char buf[T_BUF_LEN]; int ret; - memcpy(buf, t->in, T_BUF_LEN); - ret = memset_s(buf, t->smax, t->c, t->len); + memset(buf, 0, sizeof buf); + strncpy(buf, t->in, sizeof buf); + ret = memset_s(buf, t->dsz, t->ch, t->len); return (t_compare_i(t->ret, ret) & t_compare_mem(t->out, buf, T_BUF_LEN)); }