tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Adding memset_s function

For some time now, I have wanted a function to zero a block of memory, with a guarantee that the compiler will not optimise it away and do nothing.

ISO/IEC 9899:2011 ("C 11") defines a memset_s function for that. It's a lot like memset(3), but it takes an extra argument, does some sanity checks on the arguments, and it's guaranteed not to be optimised away by the compiler.

You can get a free copy of one of the last committee drafts of the C11 standard from <>, but you have to pay for the actual standard.

A patch to add memset_s to NetBSD is here: <> or via HTTP: <>.

In addition to the memset_s function, man page, and tests, it also adds a few things to header files, protected by
"#if (__STDC_WANT_LIB_EXT1__ - 0 == 1) || defined(_NETBSD_SOURCE)"

    * errno.h: define errno_t;
    * stddef.h: define rsize_t;
    * string.h: define errno_t and rsize_t;
    * stdint.h: define RSIZE_MAX;

I have not implemented the set_constraint_handler_s interface from ISO/IEC 9899:2011 section K.3.1.4; my current implementation of memset_s behaves as if the runtime-constraint handler does nothing. I plan to add the constraint handler interface later.

The standard does not specify what errno values should be used, so I just picked some.

The formatted man page for memset_s looks like this:

     memset_s -- copy a value to all bytes of a memory buffer

     Standard C Library (libc, -lc)

     #define __STDC_WANT_LIB_EXT1__ 1

     #include <string.h>

     memset_s(void *s, rsize_t smax, int c, rsize_t n);

     The memset_s() function copies the value c (converted to an
     unsigned char) into each of the first n bytes of the memory buffer
     whose starting address is given by s.

     It is a runtime-constraints violation if s is a null pointer, or
     if either of smax or n is larger than RSIZE_MAX, or if smax is
     smaller than n.  If there is a runtime-constraints violation,
     and if s is not a null pointer, and if smax is not larger than
     RSIZE_MAX, then, before reporting the runtime-constraints
     violation, memset_s() copies smax bytes to the destination.

     In contrast to the memset(3) function, calls to memset_s() will
     never be ``optimised away'' by a compiler.  This property is
     required by the following sentences in section K. of
     ISO/IEC 9899:2011 (``ISO C11''):

           Unlike memset(), any call to the memset_s() function shall
           be evaluated strictly according to the rules of the abstract
           machine as described in (  That is, any call to the
           memset_s() function shall assume that the memory indicated
           by s and n may be accessible in the future and thus must
           contain the values indicated by c.

     The memset_s() function returns zero for success, or a non-zero
     error code if there was a runtime-constraints violation.

     memset_s() returns the following error codes, and also stores the error
     codes in the global errno variable:

     [EINVAL]           The s argument was a null pointer.

     [E2BIG]            One or both of smax or n was larger than RSIZE_MAX.

     [EOVERFLOW]        n was larger than smax.


     The memset_s() function conforms to ISO/IEC 9899:2011 (``ISO C11''),
     except that the set_constraint_handler_s() interface is not supported.

--apb (Alan Barrett)

Home | Main Index | Thread Index | Old Index