host/inmsafecapis/unix/safecapismajor.h (363 lines of code) (raw):
#ifndef __SAFE_C_APIS_MAJOR_H__
#define __SAFE_C_APIS_MAJOR_H__
#ifdef __INM_KERNEL_DRIVERS__
#ifdef INM_LINUX
#include <linux/stddef.h>
#include <linux/types.h>
#else
#include <sys/types.h>
#include <inttypes.h>
#endif
#else
#include <inttypes.h>
#include <stdio.h>
#include <wchar.h>
#include <stdarg.h>
#endif /* __INM_KERNEL_DRIVERS__ */
/* Error Values */
#define INM_ERR_SUCCESS 0 /* Success */
#define INM_ERR_INVALID 1 /* Invalid Argument */
#define INM_ERR_OVERLAP 2 /* Overlap */
#define INM_ERR_UNTERM 3 /* Unterminated */
#define INM_ERR_NOSPC 4 /* No Space */
/*
* RHEL 5 gcc compiler does not support inline functions with variable args.
* As such, same function is copied as non inline variant in driver code as
* a workaround. Any bug fixes here should be made there as well.
*/
#if !(defined(RHEL_MAJOR) && (RHEL_MAJOR == 5) && __INM_KERNEL_DRIVERS__)
/* Make sure compiler does printf style format checking */
static inline int sprintf_s(char *buf, size_t bufsz, const char *fmt, ...) __attribute__ ((format(printf, 3, 4)));
static inline int
sprintf_s(char *buf, size_t bufsz, const char *fmt, ...)
{
int retval = -1;
va_list args;
if( buf && bufsz > 0 && fmt ) {
va_start(args, fmt);
retval = vsnprintf(buf, bufsz, fmt, args);
/* If buffer not adequate, return error */
if( retval >= bufsz )
retval = -1;
va_end(args);
}
if( retval == -1 ) {
/* Do we need to set errno?
errno = EINVAL;
*/
if( buf && bufsz )
*buf = '\0';
}
return retval;
}
static inline int
vsnprintf_s(char *buf, size_t bufsz, const char *fmt, va_list args)
{
int retval = -1;
if( buf && bufsz > 0 && fmt ) {
retval = vsnprintf(buf, bufsz, fmt, args);
/* If buffer not adequate, return error */
if( retval >= bufsz )
retval = -1;
}
if( retval == -1 ) {
/* Do we need to set errno?
errno = EINVAL;
*/
if( buf && bufsz )
*buf = '\0';
}
return retval;
}
#endif
static inline int
memcpy_s(void *dest, size_t d_count, const void *src, size_t s_count)
{
uint8_t *destp;
const uint8_t *srcp;
destp = (uint8_t *)dest;
srcp = (const uint8_t *)src;
// nothing to copy
if (s_count == 0) {
return INM_ERR_SUCCESS;
}
/* Validations:
* 1. dest and src shouldn't be NULL
* 2. d_count and s_count shouldn't be 0
* 3. s_count shouldn't be greater than d_count
*/
if (destp == NULL || d_count == 0 || srcp == NULL ||
s_count > d_count) {
return INM_ERR_INVALID;
}
/* Check for overlap of dest and src */
if (((srcp > destp) && (srcp < (destp + d_count))) ||
((destp > srcp) && (destp < (srcp + s_count)))) {
return INM_ERR_OVERLAP;
}
/* Copy the data from src to dest */
do {
*destp++ = *srcp++;
} while (--s_count);
return INM_ERR_SUCCESS;
}
static inline int
strcat_s(char *str_dest, size_t d_count, const char *str_src)
{
int ret = INM_ERR_NOSPC;
const char *overlap_pos, *overlap_buf;
char *str_dest_orig = str_dest;
const char *str_src_orig = str_src;
/* Validations:
* 1. str_dest & str_src shouldn't be NULL
* 2. d_count shouldn't be 0
*/
if (str_dest == NULL || d_count == 0 || str_src == NULL)
return INM_ERR_INVALID;
/* Find the end of str_dest */
while (*str_dest != '\0') {
/* Check for overlap */
if (str_dest == str_src) {
ret = INM_ERR_OVERLAP;
goto out;
}
str_dest++;
d_count--;
if (d_count == 0) {
ret = INM_ERR_UNTERM;
goto out;
}
}
if (str_dest_orig < str_src_orig)
overlap_pos = str_src_orig;
else
overlap_pos = str_dest_orig;
while (d_count > 0) {
if (str_dest_orig < str_src_orig)
overlap_buf = str_dest;
else
overlap_buf = str_src;
/* Check for overlap */
if (overlap_buf == overlap_pos){
ret = INM_ERR_OVERLAP;
goto out;
}
*str_dest = *str_src;
if (*str_dest == '\0')
return INM_ERR_SUCCESS;
str_dest++;
str_src++;
d_count--;
}
out:
*str_dest_orig = '\0';
return ret;
}
static inline int
strncat_s(char *str_dest, size_t d_count, const char *str_src, size_t s_count)
{
int ret = INM_ERR_NOSPC;
const char *overlap_pos, *overlap_buf;
char *str_dest_orig = str_dest;
const char *str_src_orig = str_src;
/* Validations:
* 1. str_dest & str_src shouldn't be NULL
* 2. d_count shouldn't be 0
*/
if (str_dest == NULL || d_count == 0 || str_src == NULL)
return INM_ERR_INVALID;
/* Find the end of str_dest */
while (*str_dest != '\0') {
/* Check for overlap */
if (str_dest == str_src) {
ret = INM_ERR_OVERLAP;
goto out;
}
str_dest++;
d_count--;
if (d_count == 0){
ret = INM_ERR_UNTERM;
goto out;
}
}
if (str_dest_orig < str_src_orig)
overlap_pos = str_src_orig;
else
overlap_pos = str_dest_orig;
while (d_count > 0) {
if (str_dest_orig < str_src_orig)
overlap_buf = str_dest;
else
overlap_buf = str_src;
/* Check for overlap */
if (overlap_buf == overlap_pos) {
ret = INM_ERR_OVERLAP;
goto out;
}
if (s_count == 0) {
*str_dest = '\0';
return INM_ERR_SUCCESS;
}
*str_dest = *str_src;
if (*str_dest == '\0')
return INM_ERR_SUCCESS;
str_dest++;
str_src++;
d_count--;
s_count--;
}
out:
*str_dest_orig = '\0';
return ret;
}
/*
* api to safely copy the string from src to tgt.
* INPUT:
* tgt: poiter to target buffer.
* src: pointer to string need to be copied.
* tgtmax: max aize of the target buffer
* RETURN:
* 0 : success of string copy.
* >0 : see failure cases defined above.
*/
static inline int
strcpy_s(char *tgt, size_t tgtmax, const char *src)
{
const char *overlap_sensor;
int ret;
int src_high_mem = 0;
char *tgt_orig = tgt;
/* Validate argument */
if(tgt == NULL || tgtmax == 0)
return INM_ERR_INVALID;
if (src == NULL) {
ret = INM_ERR_INVALID;
goto out;
}
if (tgt < src) {
overlap_sensor = src;
src_high_mem = 1;
} else {
overlap_sensor = tgt;
}
do {
if (!tgtmax) {
ret = INM_ERR_NOSPC;
goto out;
}
if (src_high_mem) {
if(tgt == overlap_sensor) {
ret = INM_ERR_OVERLAP;
goto out;
}
} else {
if (src == overlap_sensor) {
ret = INM_ERR_OVERLAP;
goto out;
}
}
--tgtmax;
} while((*tgt++ = *src++));
/*zero_out_remaining*/
while(tgtmax) {
*tgt = '\0'; tgtmax--; tgt++;
}
return INM_ERR_SUCCESS;
out:
*tgt_orig = '\0';
return ret;
}
/*
* api to safe copy the n bytes from source to target.
* INPUT:
* tgt : poiter to target buffer.
* src : pointer to string need to be copied.
* tgtmax: max aize of the target buffer
* len : lenght of the bytes need to be copied.
* RETURN:
* 0 : success of string copy.
* >0: see failure cases defined above.
* RUNTIME CONSTRAINTS:
* If len is either greater than or equal to tgtmax, then tgtmax
* should be more than strnlen(src,dmax)
*
*/
static inline int
strncpy_s(char *tgt, size_t tgtmax, const char *src, size_t len)
{
const char *overlap_sensor;
int ret;
int src_high_mem = 0;
char *tgt_orig = tgt;
/* validate argument */
if(tgt == NULL || tgtmax == 0)
return INM_ERR_INVALID;
if (src == NULL) {
ret = INM_ERR_INVALID;
goto out;
}
if (tgt < src) {
overlap_sensor = src;
src_high_mem = 1;
} else {
overlap_sensor = tgt;
}
do {
if (!tgtmax) {
ret = INM_ERR_NOSPC;
goto out;
}
if (src_high_mem) {
if(tgt == overlap_sensor) {
ret = INM_ERR_OVERLAP;
goto out;
}
} else {
if (src == overlap_sensor) {
ret = INM_ERR_OVERLAP;
goto out;
}
}
if(!len) {
goto zero_out_remaining;
}
--tgtmax;
--len;
} while((*tgt++ = *src++));
zero_out_remaining:
while(tgtmax) {
*tgt = '\0'; tgtmax--; tgt++;
}
return INM_ERR_SUCCESS;
out:
*tgt_orig = '\0';
return ret;
}
#ifndef __INM_KERNEL_DRIVERS__
static inline int
wcscat_s(wchar_t *str_dest, size_t d_count, const wchar_t *str_src)
{
int ret = INM_ERR_NOSPC;
const wchar_t *overlap_pos, *overlap_buf;
wchar_t *str_dest_orig = str_dest;
const wchar_t *str_src_orig = str_src;
/* Validations:
* 1. str_dest & str_src shouldn't be NULL
* 2. d_count shouldn't be 0
*/
if (str_dest == NULL || d_count == 0 || str_src == NULL)
return INM_ERR_INVALID;
/* Find the end of str_dest */
while (*str_dest != L'\0') {
/* Check for overlap */
if (str_dest == str_src) {
ret = INM_ERR_OVERLAP;
goto out;
}
str_dest++;
d_count--;
if (d_count == 0) {
ret = INM_ERR_UNTERM;
goto out;
}
}
if (str_dest_orig < str_src_orig)
overlap_pos = str_src_orig;
else
overlap_pos = str_dest_orig;
while (d_count > 0) {
if (str_dest_orig < str_src_orig)
overlap_buf = str_dest;
else
overlap_buf = str_src;
/* Check for overlap */
if (overlap_buf == overlap_pos) {
ret = INM_ERR_OVERLAP;
goto out;
}
*str_dest = *str_src;
if (*str_dest == L'\0')
return INM_ERR_SUCCESS;
str_dest++;
str_src++;
d_count--;
}
out:
*str_dest_orig = L'\0';
return ret;
}
/*
* api to safe copy the wchar bytes from src to tgt.
* INPUT:
* tgt: poiter to target buffer.
* src: pointer to string need to be copied.
* tgtmax: max aize of the target buffer.
* RETURN:
* 0 : success of string copy.
* >0 : see failure cases defined above.
*
*/
static inline int
wcscpy_s(wchar_t *tgt, size_t tgtmax, const wchar_t *src)
{
const wchar_t *overlap_sensor;
int ret;
int src_high_mem = 0;
wchar_t *tgt_orig = tgt;
/* Validate argument */
if (tgt == NULL || tgtmax == 0)
return INM_ERR_INVALID;
if (src == NULL) {
ret = INM_ERR_INVALID;
goto out;
}
if (tgt < src) {
overlap_sensor = src;
src_high_mem = 1;
} else {
overlap_sensor = tgt;
}
do {
if (!tgtmax) {
ret = INM_ERR_NOSPC;
goto out;
}
if (src_high_mem) {
if(tgt == overlap_sensor) {
ret = INM_ERR_OVERLAP;
goto out;
}
} else {
if (src == overlap_sensor) {
ret = INM_ERR_OVERLAP;
goto out;
}
}
--tgtmax;
} while(*tgt++ = *src++);
/*zero_out_remaining*/
while(tgtmax) {
*tgt = L'\0'; tgtmax--; tgt++;
}
return INM_ERR_SUCCESS;
out:
*tgt_orig = L'\0';
return ret;
}
#endif /* __INM_KERNEL_DRIVERS__ */
#endif /* __SAFE_C_APIS_MAJOR_H__ */