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.
This commit is contained in:
Dag-Erling Smørgrav 2018-05-06 04:19:26 +02:00
parent 56bd595396
commit a1bf5e87f0
8 changed files with 66 additions and 12 deletions

View file

@ -51,6 +51,9 @@ AC_TYPE_UINT8_T
AC_TYPE_UINTMAX_T
AC_TYPE_UINTPTR_T
AC_CHECK_TYPES([rsize_t], [], [], [[#include <stdint.h>]])
AC_CHECK_DECL([RSIZE_MAX], [], [], [[#include <stdint.h>]])
############################################################################
#
# Headers and functions

View file

@ -24,6 +24,7 @@ cryb_HEADERS += \
endian.h \
memcpy_s.h \
memset_s.h \
rsize.h \
strchrnul.h \
string.h \
strlcat.h \

View file

@ -34,9 +34,13 @@
#include <cryb/to.h>
#endif
#ifndef CRYB_RSIZE_H_INCLUDED
#include <cryb/rsize.h>
#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

View file

@ -34,9 +34,13 @@
#include <cryb/to.h>
#endif
#ifndef CRYB_RSIZE_H_INCLUDED
#include <cryb/rsize.h>
#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

41
include/cryb/rsize.h Normal file
View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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;
};