From bf624acec12368fd4ebeedd7a9cee65b3800a0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 16 Dec 2015 00:41:26 +0100 Subject: [PATCH 1/6] Tweak memset_s() and its unit tests, mostly renaming variables. --- lib/core/cryb_memset_s.c | 16 +++++++++++----- t/t_memset_s.c | 25 +++++++++++++------------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/core/cryb_memset_s.c b/lib/core/cryb_memset_s.c index 7a1750b..61d2fe2 100644 --- a/lib/core/cryb_memset_s.c +++ b/lib/core/cryb_memset_s.c @@ -32,9 +32,11 @@ #endif #include +#include #include #include +#include #include /* @@ -42,15 +44,19 @@ * is overwritten even if the data will never be read. */ int -cryb_memset_s(void *s, size_t smax, int c, size_t n) +cryb_memset_s(void *d, size_t dsz, int ch, size_t n) { unsigned int i; - 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 > SIZE_MAX || n > SIZE_MAX) + return (ERANGE); +CRYB_RESTORE_COVERAGE + for (i = 0; i < n && i < dsz; ++i) + ((volatile unsigned char *)d)[i] = (unsigned char)ch; + if (n > dsz) return (EOVERFLOW); return (0); } diff --git a/t/t_memset_s.c b/t/t_memset_s.c index 020d5a3..25ff0fa 100644 --- a/t/t_memset_s.c +++ b/t/t_memset_s.c @@ -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)); } From c73fd34d976da6886c812945e698e51497b92d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 16 Dec 2015 00:50:36 +0100 Subject: [PATCH 2/6] Implement a memcpy_s() equivalent. --- configure.ac | 2 +- include/cryb/Makefile.am | 1 + include/cryb/memcpy_s.h | 40 ++++++ lib/core/Makefile.am | 1 + lib/core/cryb_memcpy_s.c | 77 ++++++++++ t/.gitignore | 1 + t/Makefile.am | 5 +- t/t_memcpy_s.c | 304 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 429 insertions(+), 2 deletions(-) create mode 100644 include/cryb/memcpy_s.h create mode 100644 lib/core/cryb_memcpy_s.c create mode 100644 t/t_memcpy_s.c diff --git a/configure.ac b/configure.ac index 39e5174..45022c9 100644 --- a/configure.ac +++ b/configure.ac @@ -118,7 +118,7 @@ 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..4926d27 100644 --- a/include/cryb/Makefile.am +++ b/include/cryb/Makefile.am @@ -22,6 +22,7 @@ cryb_HEADERS += \ ctype.h \ defs.h \ endian.h \ + memcpy_s.h \ memset_s.h \ strchrnul.h \ string.h \ diff --git a/include/cryb/memcpy_s.h b/include/cryb/memcpy_s.h new file mode 100644 index 0000000..6fa6a34 --- /dev/null +++ b/include/cryb/memcpy_s.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2015 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 + +int cryb_memcpy_s(void *, size_t, const void *, size_t); + +#if !HAVE_MEMCPY_S +#undef memcpy_s +#define memcpy_s(arg, ...) cryb_memcpy_s(arg, __VA_ARGS__) +#endif + +#endif diff --git a/lib/core/Makefile.am b/lib/core/Makefile.am index 95ddb28..34dfcec 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 \ diff --git a/lib/core/cryb_memcpy_s.c b/lib/core/cryb_memcpy_s.c new file mode 100644 index 0000000..3ecc7b6 --- /dev/null +++ b/lib/core/cryb_memcpy_s.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2015 Dag-Erling Smørgrav + * 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 +#include + +/* + * Like memcpy(), but checks for overflow and overwrites the destination + * range with zeroes on error. + */ +int +cryb_memcpy_s(void *d, size_t dsz, const void *s, size_t n) +{ + unsigned int i; + + /* unrecoverable errors */ + if (d == NULL) + return (EINVAL); +CRYB_DISABLE_COVERAGE + if (dsz > SIZE_MAX) + return (ERANGE); +CRYB_RESTORE_COVERAGE + /* recoverable errors */ + if (s == NULL || n > dsz || +CRYB_DISABLE_COVERAGE + n > SIZE_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 > SIZE_MAX) + return (ERANGE); +CRYB_RESTORE_COVERAGE + return (EINVAL); + } + for (i = 0; i < dsz && i < n; ++i) + ((volatile unsigned char *)d)[i] = ((unsigned char *)s)[i]; + 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..057d2ff --- /dev/null +++ b/t/t_memcpy_s.c @@ -0,0 +1,304 @@ +/*- + * Copyright (c) 2015 Dag-Erling Smørgrav + * 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]; + size_t dsz; + const char s[T_BUF_LEN]; + size_t len; + const char out[T_BUF_LEN]; + size_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, s_len, d_off, 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], + 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], + t_overlap_cases[i].desc); + return (0); +} + +void +t_cleanup(void) +{ +} From d6e82b474fdcdc6f596acec4aa7debde77c50b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 8 Jan 2016 15:19:13 +0100 Subject: [PATCH 3/6] Add man pages for memset_s(3) and memcpy_s(3) --- lib/core/Makefile.am | 2 + lib/core/cryb_memcpy_s.3 | 117 +++++++++++++++++++++++++++++++++++++++ lib/core/cryb_memset_s.3 | 111 +++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 lib/core/cryb_memcpy_s.3 create mode 100644 lib/core/cryb_memset_s.3 diff --git a/lib/core/Makefile.am b/lib/core/Makefile.am index 34dfcec..03fcf58 100644 --- a/lib/core/Makefile.am +++ b/lib/core/Makefile.am @@ -22,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..5c3fb41 --- /dev/null +++ b/lib/core/cryb_memcpy_s.3 @@ -0,0 +1,117 @@ +.\"- +.\" 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 December 15, 2015 +.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 void * +.Fn cryb_memcpy_s "void *d" "size_t dsz" "const void *s" "size_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 SIZE_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 +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 +and +.Dv RSIZE_MAX +are not defined. +.Sh SEE ALSO +.Xr cryb_memset_s 3 , +.Xr memcpy 3 +.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_memset_s.3 b/lib/core/cryb_memset_s.3 new file mode 100644 index 0000000..d9df865 --- /dev/null +++ b/lib/core/cryb_memset_s.3 @@ -0,0 +1,111 @@ +.\"- +.\" 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 December 15, 2015 +.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 void * +.Fn cryb_memset_s "void *d" "size_t dsz" "int ch" "size_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 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_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 +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 +and +.Dv RSIZE_MAX +are not defined. +.Sh SEE ALSO +.Xr cryb_memcpy_s 3 , +.Xr memset 3 +.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 . From 56bd595396874d6cfdbc4e0d6d4b9b762f5b8c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sun, 6 May 2018 03:45:56 +0200 Subject: [PATCH 4/6] Modernize. --- include/cryb/memcpy_s.h | 10 +++++++++- include/cryb/memset_s.h | 2 +- lib/core/cryb_memcpy_s.c | 4 ++-- lib/core/cryb_memset_s.c | 4 ++-- t/t_memcpy_s.c | 12 +++++++----- t/t_memset_s.c | 2 +- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/cryb/memcpy_s.h b/include/cryb/memcpy_s.h index 6fa6a34..5fd5c25 100644 --- a/include/cryb/memcpy_s.h +++ b/include/cryb/memcpy_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 @@ -30,6 +30,12 @@ #ifndef CRYB_MEMCPY_S_H_INCLUDED #define CRYB_MEMCPY_S_H_INCLUDED +#ifndef CRYB_TO +#include +#endif + +CRYB_BEGIN + int cryb_memcpy_s(void *, size_t, const void *, size_t); #if !HAVE_MEMCPY_S @@ -37,4 +43,6 @@ int cryb_memcpy_s(void *, size_t, const void *, size_t); #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..cf71781 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 diff --git a/lib/core/cryb_memcpy_s.c b/lib/core/cryb_memcpy_s.c index 3ecc7b6..550305a 100644 --- a/lib/core/cryb_memcpy_s.c +++ b/lib/core/cryb_memcpy_s.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Dag-Erling Smørgrav + * Copyright (c) 2015-2018 The University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,6 +72,6 @@ CRYB_RESTORE_COVERAGE return (EINVAL); } for (i = 0; i < dsz && i < n; ++i) - ((volatile unsigned char *)d)[i] = ((unsigned char *)s)[i]; + ((volatile uint8_t *)d)[i] = ((const uint8_t *)s)[i]; return (0); } diff --git a/lib/core/cryb_memset_s.c b/lib/core/cryb_memset_s.c index 61d2fe2..6730007 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 @@ -55,7 +55,7 @@ CRYB_DISABLE_COVERAGE return (ERANGE); CRYB_RESTORE_COVERAGE for (i = 0; i < n && i < dsz; ++i) - ((volatile unsigned char *)d)[i] = (unsigned char)ch; + ((volatile uint8_t *)d)[i] = (uint8_t)ch; if (n > dsz) return (EOVERFLOW); return (0); diff --git a/t/t_memcpy_s.c b/t/t_memcpy_s.c index 057d2ff..76b45be 100644 --- a/t/t_memcpy_s.c +++ b/t/t_memcpy_s.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Dag-Erling Smørgrav + * Copyright (c) 2015-2018 The University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -289,16 +289,18 @@ t_prepare(int argc, char *argv[]) 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], + 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], + t_add_test(t_memcpy_s_overlap, &t_overlap_cases[i], "%s", t_overlap_cases[i].desc); return (0); } -void -t_cleanup(void) +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 25ff0fa..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 From a1bf5e87f025ed012db3cecf0f29a7ae3dc4c027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sun, 6 May 2018 04:19:26 +0200 Subject: [PATCH 5/6] Implement rsize_t / RSIZE_MAX (almost) correctly. The caveat is needed because if you include one of these headers on a system that defines rsize_t without having the correct incantations in your configure.ac, you are going to have a bad time. But there is no good general solution to the problem. --- configure.ac | 3 +++ include/cryb/Makefile.am | 1 + include/cryb/memcpy_s.h | 6 +++++- include/cryb/memset_s.h | 6 +++++- include/cryb/rsize.h | 41 ++++++++++++++++++++++++++++++++++++++++ lib/core/cryb_memcpy_s.c | 8 ++++---- lib/core/cryb_memset_s.c | 4 ++-- t/t_memcpy_s.c | 9 +++++---- 8 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 include/cryb/rsize.h diff --git a/configure.ac b/configure.ac index 45022c9..212e280 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,9 @@ AC_TYPE_UINT8_T AC_TYPE_UINTMAX_T AC_TYPE_UINTPTR_T +AC_CHECK_TYPES([rsize_t], [], [], [[#include ]]) +AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include ]]) + ############################################################################ # # Headers and functions diff --git a/include/cryb/Makefile.am b/include/cryb/Makefile.am index 4926d27..b66ec7c 100644 --- a/include/cryb/Makefile.am +++ b/include/cryb/Makefile.am @@ -24,6 +24,7 @@ cryb_HEADERS += \ endian.h \ memcpy_s.h \ memset_s.h \ + rsize.h \ strchrnul.h \ string.h \ strlcat.h \ diff --git a/include/cryb/memcpy_s.h b/include/cryb/memcpy_s.h index 5fd5c25..45e59cd 100644 --- a/include/cryb/memcpy_s.h +++ b/include/cryb/memcpy_s.h @@ -34,9 +34,13 @@ #include #endif +#ifndef CRYB_RSIZE_H_INCLUDED +#include +#endif + CRYB_BEGIN -int cryb_memcpy_s(void *, size_t, const void *, size_t); +int cryb_memcpy_s(void *, rsize_t, const void *, rsize_t); #if !HAVE_MEMCPY_S #undef memcpy_s diff --git a/include/cryb/memset_s.h b/include/cryb/memset_s.h index cf71781..fad0265 100644 --- a/include/cryb/memset_s.h +++ b/include/cryb/memset_s.h @@ -34,9 +34,13 @@ #include #endif +#ifndef CRYB_RSIZE_H_INCLUDED +#include +#endif + CRYB_BEGIN -int cryb_memset_s(void *, size_t, int, size_t); +int 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/rsize.h new file mode 100644 index 0000000..5d0bf3b --- /dev/null +++ b/include/cryb/rsize.h @@ -0,0 +1,41 @@ +/*- + * 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_RSIZE_H_INCLUDED +#define CRYB_RSIZE_H_INCLUDED + +#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/cryb_memcpy_s.c b/lib/core/cryb_memcpy_s.c index 550305a..cb56637 100644 --- a/lib/core/cryb_memcpy_s.c +++ b/lib/core/cryb_memcpy_s.c @@ -45,7 +45,7 @@ * range with zeroes on error. */ int -cryb_memcpy_s(void *d, size_t dsz, const void *s, size_t n) +cryb_memcpy_s(void *d, rsize_t dsz, const void *s, rsize_t n) { unsigned int i; @@ -53,20 +53,20 @@ cryb_memcpy_s(void *d, size_t dsz, const void *s, size_t n) if (d == NULL) return (EINVAL); CRYB_DISABLE_COVERAGE - if (dsz > SIZE_MAX) + if (dsz > RSIZE_MAX) return (ERANGE); CRYB_RESTORE_COVERAGE /* recoverable errors */ if (s == NULL || n > dsz || CRYB_DISABLE_COVERAGE - n > SIZE_MAX || + 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 > SIZE_MAX) + if (n > RSIZE_MAX) return (ERANGE); CRYB_RESTORE_COVERAGE return (EINVAL); diff --git a/lib/core/cryb_memset_s.c b/lib/core/cryb_memset_s.c index 6730007..b408bf4 100644 --- a/lib/core/cryb_memset_s.c +++ b/lib/core/cryb_memset_s.c @@ -44,14 +44,14 @@ * is overwritten even if the data will never be read. */ int -cryb_memset_s(void *d, size_t dsz, int ch, size_t n) +cryb_memset_s(void *d, rsize_t dsz, int ch, rsize_t n) { unsigned int i; if (d == NULL) return (EINVAL); CRYB_DISABLE_COVERAGE - if (dsz > SIZE_MAX || n > SIZE_MAX) + if (dsz > RSIZE_MAX || n > RSIZE_MAX) return (ERANGE); CRYB_RESTORE_COVERAGE for (i = 0; i < n && i < dsz; ++i) diff --git a/t/t_memcpy_s.c b/t/t_memcpy_s.c index 76b45be..75ad1dd 100644 --- a/t/t_memcpy_s.c +++ b/t/t_memcpy_s.c @@ -44,11 +44,11 @@ struct t_plain_case { const char *desc; const char in[T_BUF_LEN]; - size_t dsz; + rsize_t dsz; const char s[T_BUF_LEN]; - size_t len; + rsize_t len; const char out[T_BUF_LEN]; - size_t outlen; + rsize_t outlen; int ret; }; @@ -115,7 +115,8 @@ t_memcpy_s(char **desc CRYB_UNUSED, void *arg) struct t_overlap_case { const char *desc; const char *in; - size_t s_off, s_len, d_off, d_len; + size_t s_off, d_off; + rsize_t s_len, d_len; const char out[T_BUF_LEN]; int ret; }; 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 6/6] 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);