/*! * \copy * Copyright (c) 2010-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 * COPYRIGHT HOLDER 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. * * * \file crt_util_safe_x.h * * \brief Safe CRT like util for cross platfroms support * * \date 06/04/2010 Created * ************************************************************************************* */ #ifndef WELS_CRT_UTIL_SAFE_CROSS_PLATFORMS_H__ #define WELS_CRT_UTIL_SAFE_CROSS_PLATFORMS_H__ #include #include #include #include #include #include #if defined(_WIN32) #include #include #include #else #include #include #include "typedefs.h" #endif//_WIN32 #include "typedefs.h" #ifdef __cplusplus extern "C" { #endif #define WELS_FILE_SEEK_SET SEEK_SET #define WELS_FILE_SEEK_CUR SEEK_CUR #define WESL_FILE_SEEK_END SEEK_END typedef FILE WelsFileHandle; #ifdef _WIN32 typedef struct _timeb SWelsTime; #else typedef struct timeb SWelsTime; #endif int32_t WelsSnprintf (str_t* buffer, int32_t sizeOfBuffer, const str_t* format, ...); str_t* WelsStrncpy (str_t* dest, int32_t sizeInBytes, const str_t* src, int32_t count); str_t* WelsStrcat (str_t* dest, int32_t sizeInBytes, str_t* src); int32_t WelsStrnlen (const str_t* str, int32_t maxlen); int32_t WelsVsnprintf (str_t* buffer, int32_t sizeOfBuffer, const str_t* format, va_list argptr); WelsFileHandle* WelsFopen (const str_t* filename, const str_t* mode); int32_t WelsFclose (WelsFileHandle* fp); int32_t WelsFread (void* buffer, int32_t size, int32_t count, WelsFileHandle* fp); int32_t WelsFwrite (const void* buffer, int32_t size, int32_t count, WelsFileHandle* fp); int32_t WelsFseek (WelsFileHandle* fp, int32_t offset, int32_t origin); int32_t WelsFflush (WelsFileHandle* fp); int32_t WelsGetTimeOfDay (SWelsTime* tp); int32_t WelsStrftime (str_t* buffer, int32_t size, const str_t* format, const SWelsTime* tp); uint16_t WelsGetMillisecond (const SWelsTime* tp); #ifdef __cplusplus } #endif /* * Safe Lib specific errno codes. These can be added to the errno.h file * if desired. */ #define ESNULLP ( 400 ) /* null ptr */ #define ESZEROL ( 401 ) /* length is zero */ #define ESLEMIN ( 402 ) /* length is below min */ #define ESLEMAX ( 403 ) /* length exceeds max */ #define ESOVRLP ( 404 ) /* overlap undefined */ #define ESEMPTY ( 405 ) /* empty string */ #define ESNOSPC ( 406 ) /* not enough space for s2 */ #define ESUNTERM ( 407 ) /* unterminated string */ #define ESNODIFF ( 408 ) /* no difference */ #define ESNOTFND ( 409 ) /* not found */ /* EOK may or may not be defined in errno.h */ #ifndef EOK #define EOK 0 #endif #if (defined(WIN32) && defined(_MSC_VER) && (_MSC_VER<1500)) || defined(__GNUC__) static __inline int wels_strncpy_s (char* dest, int dmax, const char* src, int slen) { int orig_dmax; char* orig_dest; const char* overlap_bumper; if (dest == NULL) { // invoke_safe_lib_constraint_handler("strncpy_s: dest is null", // NULL, ESNULLP); return (ESNULLP); } if (dmax <= 0) { // invoke_safe_lib_constraint_handler("strncpy_s: dmax is 0", // NULL, ESZEROL); return (ESZEROL); } // if (dmax > RSIZE_MAX_STR) { // invoke_safe_lib_constraint_handler("strncpy_s: dmax exceeds max", // NULL, ESLEMAX); // return (ESLEMAX); // } if (src == NULL) { // handle_error(orig_dest, orig_dmax, "strncpy_s: src is null", ESNULLP); return (ESNULLP); } if (slen <= 0) { // handle_error(orig_dest, orig_dmax, "strncpy_s: slen is zero", ESZEROL); return (ESZEROL); } // if (slen > RSIZE_MAX_STR) { // handle_error(orig_dest, orig_dmax, "strncpy_s: slen exceeds max", ESLEMAX); // return (ESLEMAX); // } /* hold base in case src was not copied */ orig_dmax = dmax; orig_dest = dest; if (dest < src) { overlap_bumper = src; while (dmax > 0) { if (dest == overlap_bumper) { // handle_error(orig_dest, orig_dmax, "strncpy_s: overlapping objects", ESOVRLP); return (ESOVRLP); } if (slen == 0) { /* * Copying truncated to slen chars. Note that the TR says to * copy slen chars plus the null char. We null the slack. */ #ifdef SAFE_LIB_STR_NULL_SLACK while (dmax) { *dest = '\0'; dmax--; dest++; } #else *dest = '\0'; #endif return (EOK); } *dest = *src; if (*dest == '\0') { #ifdef SAFE_LIB_STR_NULL_SLACK /* null slack */ while (dmax) { *dest = '\0'; dmax--; dest++; } #endif return (EOK); } dmax--; slen--; dest++; src++; } } else { overlap_bumper = dest; while (dmax > 0) { if (src == overlap_bumper) { // handle_error(orig_dest, orig_dmax, "strncpy_s: overlapping objects", ESOVRLP); return (ESOVRLP); } if (slen == 0) { /* * Copying truncated to slen chars. Note that the TR says to * copy slen chars plus the null char. We null the slack. */ #ifdef SAFE_LIB_STR_NULL_SLACK while (dmax) { *dest = '\0'; dmax--; dest++; } #else *dest = '\0'; #endif return (EOK); } *dest = *src; if (*dest == '\0') { #ifdef SAFE_LIB_STR_NULL_SLACK /* null slack */ while (dmax) { *dest = '\0'; dmax--; dest++; } #endif return (EOK); } dmax--; slen--; dest++; src++; } } /* * the entire src was not copied, so zero the string */ // handle_error(orig_dest, orig_dmax, "strncpy_s: not enough space for src", ESNOSPC); return (ESNOSPC); } static __inline int wels_strcat_s (char* dest, int dmax, const char* src) { int orig_dmax; char* orig_dest; const char* overlap_bumper; if (dest == NULL) { // invoke_safe_lib_constraint_handler("strcat_s: dest is null", // NULL, ESNULLP); return (ESNULLP); } if (src == NULL) { // invoke_safe_lib_constraint_handler("strcat_s: src is null", // NULL, ESNULLP); return (ESNULLP); } if (dmax <= 0) { // invoke_safe_lib_constraint_handler("strcat_s: dmax is 0", // NULL, ESZEROL); return (ESZEROL); } // if (dmax > RSIZE_MAX_STR) { // invoke_safe_lib_constraint_handler("strcat_s: dmax exceeds max", // NULL, ESLEMAX); // return (ESLEMAX); // } /* hold base of dest in case src was not copied */ orig_dmax = dmax; orig_dest = dest; if (dest < src) { overlap_bumper = src; /* Find the end of dest */ while (*dest != '\0') { if (dest == overlap_bumper) { // handle_error(orig_dest, orig_dmax, "strcat_s: overlapping objects", ESOVRLP); return (ESOVRLP); } dest++; dmax--; if (dmax == 0) { // handle_error(orig_dest, orig_dmax, "strcat_s: dest unterminated", ESUNTERM); return (ESUNTERM); } } while (dmax > 0) { if (dest == overlap_bumper) { // handle_error(orig_dest, orig_dmax, "strcat_s: overlapping objects", ESOVRLP); return (ESOVRLP); } *dest = *src; if (*dest == '\0') { #ifdef SAFE_LIB_STR_NULL_SLACK /* null slack to clear any data */ while (dmax) { *dest = '\0'; dmax--; dest++; } #endif return (EOK); } dmax--; dest++; src++; } } else { overlap_bumper = dest; /* Find the end of dest */ while (*dest != '\0') { /* * NOTE: no need to check for overlap here since src comes first * in memory and we're not incrementing src here. */ dest++; dmax--; if (dmax == 0) { // handle_error(orig_dest, orig_dmax, "strcat_s: dest unterminated", ESUNTERM); return (ESUNTERM); } } while (dmax > 0) { if (src == overlap_bumper) { // handle_error(orig_dest, orig_dmax, "strcat_s: overlapping objects", ESOVRLP); return (ESOVRLP); } *dest = *src; if (*dest == '\0') { #ifdef SAFE_LIB_STR_NULL_SLACK /* null slack to clear any data */ while (dmax) { *dest = '\0'; dmax--; dest++; } #endif return (EOK); } dmax--; dest++; src++; } } /* * the entire src was not copied, so null the string */ // handle_error(orig_dest, orig_dmax, "strcat_s: not enough space for src", ESNOSPC); return (ESNOSPC); } static __inline int wels_strnlen_s (const char* dest, int dmax) { int count; if (dest == NULL) { return (0); } if (dmax <= 0) { // invoke_safe_lib_constraint_handler("strnlen_s: dmax is 0", // NULL, ESZEROL); return (0); } // if (dmax > RSIZE_MAX_STR) { // invoke_safe_lib_constraint_handler("strnlen_s: dmax exceeds max", // NULL, ESLEMAX); // return (0); // } count = 0; while (*dest && dmax) { count++; dmax--; dest++; } return (count); } #endif//(WIN32 && _MSC_VER && _MSC_VER<1500) || __GNUC__ #if defined(WIN32) && defined(_MSC_VER) #if _MSC_VER >= 1500 // VS2008 #define STRNCPY strncpy_s #define STRCAT strcat_s #define STRNLEN strnlen_s #else // mainly for VC6 #define STRNCPY wels_strncpy_s // override s.t.r.n.c.p.y here for safe #define STRCAT wels_strcat_s // override s.t.r.c.a.t here for safe #define STRNLEN wels_strnlen_s // override s.t.r.n.l.e.n here for safe #endif//_MSC_VER >= 1500 #else//__GNUC__ #define STRNCPY wels_strncpy_s // override s.t.r.n.c.p.y here for safe #define STRCAT wels_strcat_s // override s.t.r.c.a.t here for safe #define STRNLEN wels_strnlen_s // override s.t.r.n.l.e.n here for safe #endif//WIN32 #endif//WELS_CRT_UTIL_SAFE_CROSS_PLATFORMS_H__