1 /*
   2  * Copyright (c) 2017 Juniper Networks.  All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  *
  13  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23  * SUCH DAMAGE.
  24  */
  25 
  26 /*
  27  * Copyright 2018 Nexenta Systems, Inc.
  28  */
  29 
  30 #include "lint.h"
  31 
  32 #include <errno.h>
  33 #include <stddef.h>
  34 #include <stdint.h>
  35 #include <string.h>
  36 
  37 #include "libc.h"
  38 
  39 /* __memset_vp is a volatile pointer to memset() function */
  40 static void *(*const volatile __memset_vp)(void *, int, size_t) = (memset);
  41 
  42 /* ISO/IEC 9899:2011 K.3.7.4.1 */
  43 errno_t
  44 memset_s(void *s, rsize_t smax, int c, rsize_t n)
  45 {
  46         errno_t ret;
  47         rsize_t lim;
  48         unsigned char v;
  49 
  50         ret = EINVAL;
  51         lim = n < smax ? n : smax;
  52         v = (unsigned char)c;
  53         if (s == NULL) {
  54                 __throw_constraint_handler_s("memset_s: s is NULL", ret);
  55         } else if (smax > RSIZE_MAX) {
  56                 __throw_constraint_handler_s("memset_s: smax > RSIZE_MAX",
  57                     ret);
  58         } else {
  59                 /*
  60                  * Both s and smax are valid, fill the memory buffer using
  61                  * memset() called through a volatile pointer to guarantee
  62                  * it will not be optimized away.
  63                  */
  64                 (*__memset_vp)(s, v, lim);
  65 
  66                 if (n > RSIZE_MAX) {
  67                         __throw_constraint_handler_s("memset_s: n > RSIZE_MAX",
  68                             ret);
  69                 } else if (n > smax) {
  70                         __throw_constraint_handler_s("memset_s: n > smax", ret);
  71                 } else {
  72                         ret = 0;
  73                 }
  74         }
  75         return (ret);
  76 }