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__ */