blob: e2848007f8c5521852fc036bbcae0520d1422c18 [file] [log] [blame]
//===------- string.cpp - CStdLib Runtime functions for <string.h> --------===//
//
// The SAFECode Compiler
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides CStdLib runtime wrapper versions of functions found in
// <string.h>.
//
//===----------------------------------------------------------------------===//
#include "CStdLib.h"
//
// The following functions have CStdLib wrapper versions in this file:
// - stpcpy
// - strchr
// - strrchr
// - strstr
// - strcasestr
// - strcat
// - strncat
// - strpbrk
// - strcmp
// - memcpy
// - memmove
// - mempcpy
// - memset
// - strcpy
// - strlen
// - strncpy
// - strnlen
// - strncmp
// - memcmp
// - strspn
// - strcspn
// - memchr
// - memccpy
//
/*
* pool_stpcpy()
*
* This is the non-debug version of pool_stpcpy_debug().
*
*/
char *
pool_stpcpy(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
const uint8_t complete) {
return pool_stpcpy_debug(dstPool, srcPool, dst, src, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace stpcpy()
*
* Copies the string src to dst and returns a pointer
* to the nul terminator of dst.
*
* Attempts to verify the following:
* - src is nul terminated within memory object bounds
* - src and dst do not overlap
* - dst is long enough to hold src.
*
* @param dstPool Pool handle for destination string's pool
* @param srcPool Pool handle for destination string's pool
* @param dst Pointer to destination of copy operation
* @param src Pointer to string to copy
* @param complete Completeness bitwise vector
* @param TAG Tag information for debug
* @param SRC_INFO Source and line number information
* @return Returns a pointer to the nul-terminator of dst.
*
*/
char *
pool_stpcpy_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
const uint8_t complete,
TAG,
SRC_INFO) {
void *dstBegin = NULL, *dstEnd = NULL, *srcBegin = NULL, *srcEnd = NULL;
size_t srcLen = 0;
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound, srcFound;
// Find the destination and source strings in their pools.
if (!(dstFound = pool_find(dstPool, dst, dstBegin, dstEnd))
&& dstComplete) {
std::cout << "Could not find destination object in pool!\n";
LOAD_STORE_VIOLATION(dst, dstPool, SRC_INFO_ARGS);
}
if (!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd))
&& srcComplete) {
std::cout << "Could not find source object in pool\n";
LOAD_STORE_VIOLATION(src, srcPool, SRC_INFO_ARGS);
}
// Check if source is terminated.
if (srcFound && !isTerminated(src, srcEnd, srcLen)) {
std::cout << "Source string not terminated within bounds!\n";
C_LIBRARY_VIOLATION(src, srcPool, "stpcpy", SRC_INFO_ARGS);
}
// The remainder of the checks require both objects to be found.
if (dstFound && srcFound) {
// Check for overlap of objects.
if (isOverlapped(dst, &dst[srcLen], src, &src[srcLen])) {
std::cout << "Copying overlapping strings has undefined behavior!\n";
C_LIBRARY_VIOLATION(dst, dstPool, "stpcpy", SRC_INFO_ARGS);
}
// dstLen is the maximum length string that dst can hold.
size_t dstLen = (char *) dstEnd - dst;
// Check for overflow of dst.
if (srcLen > dstLen) {
std::cout << "Destination object too short to hold string!\n";
WRITE_VIOLATION(dst, dstPool, dstLen, srcLen, SRC_INFO_ARGS);
}
}
return stpcpy(dst, src);
}
/*
* pool_strchr()
*
* This is the non-debug version of pool_strchr_debug().
*
*/
char *
pool_strchr(DebugPoolTy *sp, const char *s, int c, const uint8_t complete) {
return pool_strchr_debug(sp, s, c, complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strchr(), debug version
*
* Returns pointer to the first instance of the given character in the string, or
* NULL if not found.
*
* Ensures the following:
* - string argument points to a valid string
*
* @param sPool Pool handle for string
* @param s String pointer
* @param c Character to find
* @param complete Completeness bitwise vector
* @param TAG Tag information for debug
* @param SRC_INFO Source and line number information
* @return Pointer to first instance of c in s or NULL
*
*/
char *
pool_strchr_debug(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete,
TAG,
SRC_INFO) {
validStringCheck(s, sPool, ARG1_COMPLETE(complete), "strchr", SRC_INFO_ARGS);
return strchr((char*)s, c);
}
/*
* pool_strrchr()
*
* This is the non-debug version of pool_strchr_debug().
*
*/
char *
pool_strrchr(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete) {
return pool_strrchr_debug(sPool, s, c, complete, DEFAULT_TAG,
DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strrchr()
*
* @param sPool Pool handle for string
* @param s String pointer
* @param c Character to find
* @return Pointer to last instance of c in s or NULL
*/
char *
pool_strrchr_debug(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete,
TAG,
SRC_INFO) {
validStringCheck(s, sPool, ARG1_COMPLETE(complete), "strrchr", SRC_INFO_ARGS);
return strrchr((char*)s, c);
}
/*
* pool_strstr()
*
* This is the non-debug version of pool_strstr_debug().
*
*/
char *
pool_strstr(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const char *s1,
const char *s2,
const uint8_t complete) {
return pool_strstr_debug(s1Pool, s2Pool, s1, s2, complete, DEFAULT_TAG,
DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strstr(), debug version
*
* Searches for the first occurence of the substring s2 in s1.
* Returns a pointer to the discovered substring, or NULL if not found.
*
* Attempts to verify that s1 and s2 are valid strings terminated within
* their memory objects' boundaries.
*
* @param s1Pool Pool handle for s1
* @param s2Pool Pool handle for s2
* @param s1 Pointer to string to be searched
* @param s2 Pointer to substring to search for
* @param complete Completeness bitwise vector
* @param TAG Tag information for debug
* @param SRC_INFO Source and line number information for debug
* @retrun Returns a pointer to the first instance of s2 in s1,
* or NULL if none exists.
*
*/
char *
pool_strstr_debug(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const char *s1,
const char *s2,
const uint8_t complete,
TAG,
SRC_INFO) {
validStringCheck(s1, s1Pool, ARG1_COMPLETE(complete), "strstr",
SRC_INFO_ARGS);
validStringCheck(s2, s2Pool, ARG2_COMPLETE(complete), "strstr",
SRC_INFO_ARGS);
return strstr((char*)s1, s2);
}
/*
* pool_strcasestr()
*
* This is the non-debug version of pool_strcasestr_debug().
*
*/
char *
pool_strcasestr(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const char *s1,
const char *s2,
const uint8_t complete) {
return pool_strcasestr_debug(s1Pool, s2Pool, s1, s2, complete, DEFAULT_TAG,
DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strcasestr(), debug version
*
* Searches for the first occurence of the substring s2 in s1, case
* insensitively.
* Returns a pointer to the discovered substring, or NULL if not found.
*
* Attempts to verify that s1 and s2 are valid strings terminated within
* their memory objects' boundaries.
*
* @param s1Pool Pool handle for s1
* @param s2Pool Pool handle for s2
* @param s1 Pointer to string to be searched
* @param s2 Pointer to substring to search for
* @param complete Completeness bitwise vector
* @param TAG Tag information for debug
* @param SRC_INFO Source and line number information for debug
* @retrun Returns a pointer to the first instance of s2 in s1,
* disregarding case, or NULL if none exists.
*
*/
char *
pool_strcasestr_debug(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const char *s1,
const char *s2,
const uint8_t complete,
TAG,
SRC_INFO) {
validStringCheck(s1, s1Pool, ARG1_COMPLETE(complete), "strcasestr",
SRC_INFO_ARGS);
validStringCheck(s2, s2Pool, ARG2_COMPLETE(complete), "strcasestr",
SRC_INFO_ARGS);
return strcasestr((char*)s1, s2);
}
/*
* pool_strcat()
*
* This is the non-debug version of pool_strcat_debug().
*
*/
char *
pool_strcat(DebugPoolTy *dp,
DebugPoolTy *sp,
char *d,
const char *s,
const unsigned char c) {
return pool_strcat_debug(dp, sp, d, s, c, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strcat(), debug version
*
* Appends the source string to the end of the destination string.
* Attempts to verify the following:
* - source and destination pointers point to valid strings
* - the destination string's object has enough space to hold the
* concatenation in memory.
*
* @param dp Pool handle for destination string
* @param sp Pool handle for source string
* @param d Pointer to the destination string
* @param s Pointer to the source string
* @param c Bitwise vector holding completeness information
* for source and destination strings
* @param TAG Tag information for debug
* @param SRC_INFO Source and line number information.
* @return This returns the pointer to the destination string.
*
*/
char *
pool_strcat_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t srcLen = 0, dstLen = 0, maxLen, catLen;
void *dstBegin = NULL, *dstEnd = NULL;
void *srcBegin = NULL, *srcEnd = NULL;
char *dstNulPosition;
bool terminated = true;
bool srcObjFound, dstObjFound;
const bool srcComplete = ARG1_COMPLETE(complete);
const bool dstComplete = ARG2_COMPLETE(complete);
// Find the strings' memory objects in the pool.
if (!(srcObjFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd)) &&
srcComplete) {
std::cout << "Destination string not found in pool\n";
LOAD_STORE_VIOLATION(dstBegin, dstPool, SRC_INFO_ARGS);
}
if (!(dstObjFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd)) &&
dstComplete) {
std::cout << "Source string not found in pool!\n";
LOAD_STORE_VIOLATION(srcBegin, srcPool, SRC_INFO_ARGS);
}
// Check if both src and dst are terminated, if they were found in their pool.
if (dstObjFound && !isTerminated(dst, dstEnd, dstLen)) {
terminated = false;
std::cout << "Destination not terminated within bounds\n";
C_LIBRARY_VIOLATION(dst, dstPool, "strcat", SRC_INFO_ARGS);
}
if (srcObjFound && !isTerminated(src, srcEnd, srcLen)) {
terminated = false;
std::cout << "Source not terminated within bounds\n";
C_LIBRARY_VIOLATION(src, srcPool, "strcat", SRC_INFO_ARGS);
}
// The remainder of the checks require both memory objects to have been found
// in the pool.
if (srcObjFound && dstObjFound) {
// If both src and dst are terminated, check for string overlap.
// Overlap occurs exactly when they share the same nul terminator in memory.
if (terminated && &dst[dstLen] == &src[srcLen]) {
std::cout << "Concatenating overlapping strings is undefined\n";
C_LIBRARY_VIOLATION(dst, dstPool, "strcat", SRC_INFO_ARGS);
}
// maxLen is the maximum length string dst can hold without going out of bounds
maxLen = (char *) dstEnd - dst;
// catLen is the length of the string resulting from concatenation.
catLen = srcLen + dstLen;
// Check if the concatenation writes out of bounds.
if (catLen > maxLen) {
std::cout << "Concatenation violated destination bounds!\n";
WRITE_VIOLATION(dstBegin, dstPool, maxLen + 1, catLen + 1, SRC_INFO_ARGS);
}
// Append at the end of dst so concatenation doesn't have to scan dst again.
dstNulPosition = &dst[dstLen];
strncat(dstNulPosition, src, srcLen);
return dst;
}
else
return strcat(dst, src);
}
/*
* pool_strncat()
*
* This is the non-debug version of pool_strncat_debug().
*
*/
char *
pool_strncat(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
size_t n,
const uint8_t complete)
{
return pool_strncat_debug(dstPool, srcPool, dst, src, n, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strncat()
*
* Appends at most n characters of src onto the end of the string dst
* and then adds a nul terminator.
*
* Checks for the following:
* - src and dst are non-null
* - dst is terminated
* - dst has enough space to hold the whole concatention
* - src and dst do not overlap
* - if src is unterminated, the first n characters of src fall within
* the boundaries of src.
*
* @param dstPool Pool handle for destination string
* @param srcPool Pool handle for source string
* @param dst Destination string pointer
* @param src Source string pointer
* @param n Number of characters to copy over
* @param complete Completeness bitwise vector
* @param TAG Tag debug information
* @param SRC_INFO Source and line number information
* @return Destination string pointer
*
*/
char *
pool_strncat_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO) {
void *dstBegin = NULL, *dstEnd = NULL;
void *srcBegin = NULL, *srcEnd = NULL;
size_t dstLen = 0, srcLen = 0, maxLen, catLen, srcAmt;
char *dstNulPosition;
bool dst_terminated = true;
bool srcObjFound, dstObjFound;
const bool srcComplete = ARG1_COMPLETE(complete);
const bool dstComplete = ARG2_COMPLETE(complete);
// Retrieve destination and source string memory objects from pool.
if (!(dstObjFound = pool_find(dstPool, (void *) dst, dstBegin, dstEnd)) &&
dstComplete) {
std::cout << "Destination string not found in pool!\n";
LOAD_STORE_VIOLATION(dstBegin, dstPool, SRC_INFO_ARGS);
}
if (!(srcObjFound = pool_find(srcPool, (void *) src, srcBegin, srcEnd)) &&
srcComplete) {
std::cout << "Source string not found in pool!\n";
LOAD_STORE_VIOLATION(srcBegin, srcPool, SRC_INFO_ARGS);
}
// Check if dst is nul terminated.
if (dstObjFound && !isTerminated(dst, dstEnd, dstLen)) {
dst_terminated = false;
std::cout << "String not terminated within bounds\n";
C_LIBRARY_VIOLATION(dst, dstPool, "strncat", SRC_INFO_ARGS);
}
// According to POSIX, src doesn't have to be nul-terminated.
// If it isn't, ensure strncat that doesn't read beyond the bounds of src.
if (srcObjFound && !isTerminated(src, srcEnd, srcLen) && srcLen < n) {
std::cout << "Source object too small\n";
OOB_VIOLATION(src, srcPool, src, srcLen, SRC_INFO_ARGS);
}
// The remaining checks require destination and source objects to be found.
if (srcObjFound && dstObjFound) {
// Determine the amount of characters to be copied over from src.
// This is either n or the length of src, whichever is smaller.
srcAmt = std::min(srcLen, n);
// Check for undefined behavior due to overlapping objects.
// Overlap occurs when the characters to be copied from src
// end inside the dst string.
if (dst_terminated && dst < &src[srcAmt] && &src[srcAmt] <= &dst[dstLen]) {
std::cout << "Concatenating overlapping objects is undefined\n";
C_LIBRARY_VIOLATION(dst, dstPool, "strncat", SRC_INFO_ARGS);
}
// maxLen is the maximum length string dst can hold without overflowing.
maxLen = (char *) dstEnd - dst;
// catLen is the length of the string resulting from the concatenation.
catLen = srcAmt + dstLen;
// Check if the copy operation would go beyong the bounds of dst.
if (catLen > maxLen) {
std::cout << "Concatenation violated destination bounds!\n";
WRITE_VIOLATION(dst, dstPool, 1+maxLen, 1+catLen, SRC_INFO_ARGS);
}
// Start concatenation the end of dst so strncat() doesn't have to scan dst
// all over again.
dstNulPosition = &dst[dstLen];
strncat(dstNulPosition, src, srcAmt);
// strncat() the returns destination string.
return dst;
}
else
return strncat(dst, src, n);
}
/*
* pool_strpbrk()
*
* This is the non-debug version of pool_strpbrk_debug().
*
*/
char *
pool_strpbrk(DebugPoolTy *sp,
DebugPoolTy *ap,
const char *s,
const char *a,
const uint8_t complete) {
return pool_strpbrk_debug(sp, ap, s, a, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strpbrk()
*
* Searches for the first instance in s of any character in a, and returns a
* pointer to that instance, or returns NULL if no instance was found.
*
* Attempts to verify that both s and a are valid strings terminated within
* their memory objects' boundaries.
*
* @param sPool Pool handle for source string
* @param aPool Pool handle for accept string
* @param s String pointer
* @param a Pointer to string of characters to find
* @return Pointer to first instance in s of some character in s, or NULL
*/
char *
pool_strpbrk_debug(DebugPoolTy *sPool,
DebugPoolTy *aPool,
const char *s,
const char *a,
const uint8_t complete,
TAG,
SRC_INFO) {
validStringCheck(s, sPool, ARG1_COMPLETE(complete), "strpbrk",
DEFAULT_SRC_INFO);
validStringCheck(a, aPool, ARG2_COMPLETE(complete), "strpbrk",
DEFAULT_SRC_INFO);
return strpbrk((char*)s, a);
}
int
pool_strcmp(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2,
const uint8_t complete){
return pool_strcmp_debug(s1p,s2p,s1,s2,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strcmp()
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 c string to be compared
* @param str2 c string to be compared
* @return
*/
int
pool_strcmp_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t str1Size = 0, str2Size = 0;
void *str1Begin =(void*)str1, *str1End = NULL, *str2Begin = (void*)str2, *str2End = NULL;
const bool str1Complete = ARG1_COMPLETE(complete);
const bool str2Complete = ARG2_COMPLETE(complete);
bool str1ObjFound, str2ObjFound;
if (!(str1ObjFound = pool_find(str1Pool, (void*)str1, str1Begin, str1End))
&& str1Complete) {
std::cout << "String 1 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
if (!(str2ObjFound = pool_find(str2Pool, (void*)str2, str2Begin, str2End))
&& str2Complete) {
std::cout << "String 2 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
// Check if strings are terminated.
if (str1ObjFound && !isTerminated(str1, str1End, str1Size)) {
std::cout << "String 1 not terminated within bounds!\n";
OOB_VIOLATION(str1Begin, str1Pool, str1Begin, str1Size, SRC_INFO_ARGS);
}
if (str2ObjFound && !isTerminated(str2, str2End, str2Size)) {
std::cout << "String 2 not terminated within bounds!\n";
OOB_VIOLATION(str2Begin, str2Pool, str2Begin, str2Size, SRC_INFO_ARGS);
}
return strcmp(str1, str2);
}
/**
* Secure runtime wrapper function to replace memcpy()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param n Maximum number of bytes to copy
* @return Destination memory area
*/
void *
pool_memcpy(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
size_t n,
const uint8_t complete) {
return pool_memcpy_debug(dstPool,srcPool,dst,src, n,complete,DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace memcpy()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param n Maximum number of bytes to copy
* @return Destination memory area
*/
void *
pool_memcpy_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound = false, srcFound = false;
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(dstFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd)) && dstComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
if(!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd)) && srcComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool, SRC_INFO_ARGS);
}
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
// The remainder of the checks require the objects to have been located in
// their pools.
if (dstFound && srcFound){
if (n > srcSize || n > dstSize){
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize, SRC_INFO_ARGS);
}
if(isOverlapped(dst,(const char*)dst+n-1,src,(const char*)src+n-1)){
std::cout<<"Two memory objects overlap each other!/n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
}
memcpy(dst, src, n);
return dst;
}
/**
* Secure runtime wrapper function to replace memmove()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param n Maximum number of bytes to copy
* @return Destination memory area
*/
void *
pool_memmove(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
size_t n,
const uint8_t complete) {
return pool_memmove_debug(dstPool,srcPool,dst,src, n,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace memmove()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param n Maximum number of bytes to copy
* @return Destination memory area
*/
void *
pool_memmove_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0, stop = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
//assert(dstPool && srcPool && dst && src && "Null pool parameters!");
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound, srcFound;
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(dstFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd))
&& dstComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
if(!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd))
&& srcComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool, SRC_INFO_ARGS);
}
if (dstFound && srcFound)
{
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
stop = std::min(n, srcSize);
if (n > srcSize || n > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize, SRC_INFO_ARGS);
}
}
memmove(dst, src, stop);
return dst;
}
#if !defined(__APPLE__)
/**
* Secure runtime wrapper function to replace mempcpy()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param n Maximum number of bytes to copy
* @return Byte following the last written byte
*/
void *
pool_mempcpy(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
size_t n,
const uint8_t complete) {
return pool_mempcpy_debug(dstPool,srcPool,dst,src, n,complete,DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace mempcpy()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param n Maximum number of bytes to copy
* @return Byte following the last written byte
*/
void *
pool_mempcpy_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound, srcFound;
// assert(dstPool && srcPool && dst && src && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(dstFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd))
&& dstComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
if(!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd))
&& srcComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool, SRC_INFO_ARGS);
}
if (dstFound && srcFound)
{
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
// Check that copy size is too big
if (n > srcSize || n > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize, SRC_INFO_ARGS);
}
// Check if two memory object overlap
if(isOverlapped(dst,(const char*)dst+n-1,src,(const char*)src+n-1)){
std::cout<<"Two memory objects overlap each other!/n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
}
return mempcpy(dst, src, n);
}
#endif
/**
* Secure runtime wrapper function to replace memset()
*
* @param stringPool Pool handle for the string
* @param string String pointer
* @param c an int value to be set
* @param n number of bytes to be set
* @return Pointer to memory area
*/
void *pool_memset(DebugPoolTy *stringPool,
void *string,
int c,
size_t n,
const uint8_t complete) {
return pool_memset_debug(stringPool, string, c, n,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace memset()
*
* @param stringPool Pool handle for the string
* @param string String pointer
* @param c an int value to be set
* @param n number of bytes to be set
* @return Pointer to memory area
*/
void *
pool_memset_debug(DebugPoolTy *stringPool,
void *string,
int c,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t stringSize = 0;
void *stringBegin = string, *stringEnd = NULL;
const bool objComplete = ARG1_COMPLETE(complete);
bool objFound;
assert(stringPool && string && "Null pool parameters!");
//// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(objFound = pool_find(stringPool, (void*)string, stringBegin, stringEnd))
&& objComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(string,stringPool, SRC_INFO_ARGS);
}
stringSize = (char *)stringEnd - (char *)string + 1;
if (objFound && n > stringSize) {
std::cout << "Cannot write more bytes than the size of the destination string!\n";
WRITE_VIOLATION(stringBegin, stringPool, stringSize, 0, SRC_INFO_ARGS);
}
return memset(string, c, n);
}
/**
* Secure runtime wrapper function to replace strcpy()
*
* @param dstPool Pool handle for destination buffer
* @param srcPool Pool handle for source string
* @param dst Destination string pointer
* @param src Source string pointer
* @return Destination string pointer
*/
char *
pool_strcpy(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
const uint8_t complete) {
return pool_strcpy_debug(dstPool, srcPool, dst, src, complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strcpy()
*
* @param dstPool Pool handle for destination buffer
* @param srcPool Pool handle for source string
* @param dst Destination string pointer
* @param src Source string pointer
* @return Destination string pointer
*/
char *
pool_strcpy_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t dstSize = 0, srcSize = 0, len = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound, srcFound;
// Ensure all valid pointers.
// assert(dstPool && srcPool && dst && src && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(dstFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd))
&& dstComplete) {
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
if(!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd))
&& srcComplete) {
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool, SRC_INFO_ARGS);
}
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
if (srcFound)
{
len = strnlen(src,srcSize);
if (len == srcSize) {
std::cout << "Source string is not NULL terminated!\n";
OOB_VIOLATION(src,srcPool,src,len,SRC_INFO_ARGS);
}
if (dstFound)
{
if (len+1 > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(dstBegin, dstPool, dstSize, srcSize, SRC_INFO_ARGS);
}
if(isOverlapped(dst,(const char*)dst+len,src,(const char*)src+len)){
std::cout<<"Two memory objects overlap each other!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
}
}
strncpy(dst, src, len+1);
return dst;
}
/**
* Secure runtime wrapper function to replace strlen()
*
* @param stringPool Pool handle for the string
* @param string String pointer
* @return Length of the string
*/
size_t
pool_strlen(DebugPoolTy *stringPool,
const char *string,
const uint8_t complete) {
return pool_strlen_debug(stringPool, string,
complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strlen()
*
* @param strPool Pool handle for the string
* @param str String pointer
* @return Length of the string
*/
size_t
pool_strlen_debug(DebugPoolTy *strPool,
const char *str,
const uint8_t complete,
TAG,
SRC_INFO) {
const bool strComplete = ARG1_COMPLETE(complete);
bool strFound;
size_t len = 0;
void *strBegin = 0, *strEnd = 0;
if (!(strFound = pool_find(strPool, (void *) str, strBegin, strEnd)) &&
strComplete)
{
LOAD_STORE_VIOLATION(str, strPool, SRC_INFO_ARGS);
}
if (strFound)
{
if (!isTerminated(str, strEnd, len))
C_LIBRARY_VIOLATION(str, strPool, "strlen", SRC_INFO_ARGS);
else
return len;
}
return strlen(str);
}
//// FIXME: WHen it is tested, compiled program outputs "Illegal Instruction"
/**
* Secure runtime wrapper function to replace strncpy()
*
* @param dstPool Pool handle for destination buffer
* @param srcPool Pool handle for source string
* @param dst Destination string pointer
* @param src Source string pointer
* @param n Maximum number of bytes to copy
* @return Destination string pointer
*/
char *
pool_strncpy(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
size_t n,
const uint8_t complete){
return pool_strncpy_debug(dstPool,srcPool,dst,src, n,
complete,DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strncpy()
*
* @param dstPool Pool handle for destination buffer
* @param srcPool Pool handle for source string
* @param dst Destination string pointer
* @param src Source string pointer
* @param n Maximum number of bytes to copy
* @return Destination string pointer
*/
char *
pool_strncpy_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0, stop = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound, srcFound;
// assert(dstPool && srcPool && dst && src && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(dstFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd)) &&
dstComplete) {
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
if(!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd))
&& srcComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool, SRC_INFO_ARGS);
}
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
stop = strnlen(src,srcSize);
// If source string is not bounded and copy length is longer than the source object
// Behavior is undefined
if (srcFound && stop==srcSize && n > srcSize) {
std::cout << "String is not bounded and copy length is out of bound!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize, SRC_INFO_ARGS);
}
// Check if destination will be overflowed
if (dstFound && n > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize, SRC_INFO_ARGS);
}
// Check if two strings are over lapped
if(srcFound && dstFound &&
isOverlapped(dst,(const char*)dst+stop-1,src,(const char*)src+stop-1)){
std::cout<<"Two memory objects overlap each other!/n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
// Copy string
strncpy_asm(dst, src, stop+1);
// Check whether result string is NULL terminated
// FIXME: Is this necessary?
if(dstFound && !isTerminated(dst,dstEnd,stop)){
std::cout<<"NULL terminator is not copied!\n";
OOB_VIOLATION(dst,dstPool,dst,stop,SRC_INFO_ARGS);
}
// Pad with zeros
memset(dst+stop+1,0,n-stop-1);
return dst;
}
/**
* Secure runtime wrapper function to replace strnlen()
*
* @param stringPool Pool handle for the string
* @param string String pointer
* @return Length of the string
*/
size_t
pool_strnlen(DebugPoolTy *stringPool,
const char *string,
size_t maxlen,
const uint8_t complete) {
return pool_strnlen_debug(stringPool, string, maxlen,
complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strnlen()
*
* @param stringPool Pool handle for the string
* @param string String pointer
* @return Length of the string
*/
size_t
pool_strnlen_debug(DebugPoolTy *stringPool,
const char *string,
size_t maxlen,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t len = 0, difflen = 0;
void *stringBegin = (char *)string, *stringEnd = NULL;
const bool strComplete = ARG1_COMPLETE(complete);
bool strFound;
// assert(stringPool && string && "Null pool parameters!");
// Retrieve string from the pool
if(!(strFound = pool_find(stringPool, (void*)string, stringBegin, stringEnd))
&& strComplete) {
std::cout<<"String not found in pool!\n";
LOAD_STORE_VIOLATION(string,stringPool, SRC_INFO_ARGS);
}
difflen = (char *)stringEnd - (char *)string +1;
len = strnlen(string, difflen);
// If the string is not terminated within range and maxlen is bigger than object size
if(strFound && maxlen > len && len==difflen){
std::cout<<"String is not bounded!\n";
OOB_VIOLATION(string,stringPool,string,difflen,SRC_INFO_ARGS);
}
return len;
}
/**
* Secure runtime wrapper function to replace strncmp()
*
* @param str1Pool Pool handle for string1
* @param str2Pool Pool handle for string2
* @param num Maximum number of chars to compare
* @param str1 string1 to be compared
* @param str2 string2 to be compared
* @return position of first different character, or 0 it they are the same
*/
int
pool_strncmp(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2,
size_t num,
const uint8_t complete){
return pool_strncmp_debug(s1p,s2p,s1,s2,num,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strncmp()
*
* @param str1Pool Pool handle for string1
* @param str2Pool Pool handle for string2
* @param num Maximum number of chars to compare
* @param str1 string1 to be compared
* @param str2 string2 to be compared
* @return position of first different character, or 0 it they are the same
*/
int
pool_strncmp_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
size_t num,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t str1Size = 0, str2Size = 0;
void *str1Begin =(void*)str1, *str1End = NULL, *str2Begin = (void*)str2, *str2End = NULL;
const bool str1Complete = ARG1_COMPLETE(complete);
const bool str2Complete = ARG2_COMPLETE(complete);
bool str1Found, str2Found;
// assert(str1Pool && str2Pool && str2 && str1 && "Null pool parameters!");
if (!(str1Found = pool_find(str1Pool, (void*)str1, str1Begin, str1End))
&& str1Complete) {
std::cout << "String 1 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
if (!(str2Found = pool_find(str2Pool, (void*)str2, str2Begin, str2End))
&& str2Complete) {
std::cout << "String 2 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
str1Size = (char*) str1End - str1+1;
str2Size = (char*) str2End - str2+1;
if (str1Found && str1Size<num) {
std::cout << "Possible read out of bound in string1!\n";
OOB_VIOLATION(str1Begin, str1Pool, str1Begin, str1Size, SRC_INFO_ARGS);
}
if (str2Found && str2Size<num) {
std::cout << "Possible read out of bound in string2!\n";
OOB_VIOLATION(str2Begin, str2Pool, str2Begin, str2Size, SRC_INFO_ARGS);
}
return strncmp(str1, str2,num);
}
/**
* Secure runtime wrapper function to replace memcmp()
*
* @param str1Pool Pool handle for memory object1
* @param str2Pool Pool handle for memory object1
* @param num Maximum number of bytes to compare
* @param str1 memory object1 to be compared
* @param str2 memory object2 to be compared
* @return position of first different character, or 0 it they are the same
*/
int
pool_memcmp(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const void *s1,
const void *s2,
size_t num,
const uint8_t complete){
return pool_memcmp_debug(s1p,s2p,s1,s2,num,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace memcmp()
*
* @param str1Pool Pool handle for memory object1
* @param str2Pool Pool handle for memory object1
* @param num Maximum number of bytes to compare
* @param str1 memory object1 to be compared
* @param str2 memory object2 to be compared
* @return position of first different character, or 0 it they are the same
*/
int
pool_memcmp_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const void *str1,
const void *str2,
size_t num,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t str1Size = 0, str2Size = 0;
void *str1Begin =(void*)str1, *str1End = NULL, *str2Begin = (void*)str2, *str2End = NULL;
const bool str1Complete = ARG1_COMPLETE(complete);
const bool str2Complete = ARG2_COMPLETE(complete);
bool str1Found, str2Found;
// assert(str1Pool && str2Pool && str2 && str1 && "Null pool parameters!");
if (!(str1Found = pool_find(str1Pool, (void*)str1, str1Begin, str1End))
&& str1Complete) {
std::cout << "String 1 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
if (!(str2Found = pool_find(str2Pool, (void*)str2, str2Begin, str2End))
&& str2Complete) {
std::cout << "String 2 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
str1Size = (char*) str1End - (char*)str1+1;
str2Size = (char*) str2End - (char*)str2+1;
if (str1Found && str1Size<num) {
std::cout << "Possible read out of bound in string1!\n";
OOB_VIOLATION(str1Begin, str1Pool, str1Begin, str1Size, SRC_INFO_ARGS);
}
if (str2Found && str2Size<num) {
std::cout << "Possible read out of bound in string2!\n";
OOB_VIOLATION(str2Begin, str2Pool, str2Begin, str2Size, SRC_INFO_ARGS);
}
return memcmp(str1, str2,num);
}
/**
* Secure runtime wrapper function to replace strspn()
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 c string to be scanned
* @param str2 c string consisted of matching characters
* @return length if initial portion of str1, which consists of
* characters only from str2.
*/
int
pool_strspn(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2,
const uint8_t complete){
return pool_strspn_debug(s1p,s2p,s1,s2,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strspn()
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 c string to be compared
* @param str2 c string to be compared
* @return length if initial portion of str1, which consists of
* characters only from str2.
*/
int
pool_strspn_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t str1Size = 0, str2Size = 0;
void *str1Begin =(void*)str1, *str1End = NULL, *str2Begin = (void*)str2, *str2End = NULL;
const bool str1Complete = ARG1_COMPLETE(complete);
const bool str2Complete = ARG2_COMPLETE(complete);
bool str1Found, str2Found;
// assert(str1Pool && str2Pool && str2 && str1 && "Null pool parameters!");
if (!(str1Found = pool_find(str1Pool, (void*)str1, str1Begin, str1End))
&& str1Complete) {
std::cout << "String 1 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
if (!(str2Found = pool_find(str2Pool, (void*)str2, str2Begin, str2End))
&& str2Complete) {
std::cout << "String 2 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
// Check if strings are terminated.
if (str1Found && !isTerminated(str1, str1End, str1Size)) {
std::cout << "String 1 not terminated within bounds!\n";
OOB_VIOLATION(str1Begin, str1Pool, str1Begin, str1Size, SRC_INFO_ARGS);
}
if (str2Found && !isTerminated(str2, str2End, str2Size)) {
std::cout << "String 2 not terminated within bounds!\n";
OOB_VIOLATION(str2Begin, str2Pool, str2Begin, str2Size, SRC_INFO_ARGS);
}
return strspn(str1, str2);
}
/**
* Secure runtime wrapper function to replace strcspn()
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 c string to be scanned
* @param str2 c string consisted of matching characters
* @return length if initial portion of str1, which does not
* consist of any characters from str2.
*/
int pool_strcspn(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2,
const uint8_t complete){
return pool_strcspn_debug(s1p,s2p,s1,s2,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strcspn()
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 c string to be compared
* @param str2 c string to be compared
* @return length if initial portion of str1, which does not
* consist of any characters from str2.
*/
int pool_strcspn_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
const uint8_t complete,
TAG,
SRC_INFO) {
size_t str1Size = 0, str2Size = 0;
void *str1Begin =(void*)str1, *str1End = NULL, *str2Begin = (void*)str2, *str2End = NULL;
const bool str1Complete = ARG1_COMPLETE(complete);
const bool str2Complete = ARG2_COMPLETE(complete);
bool str1Found, str2Found;
// assert(str1Pool && str2Pool && str2 && str1 && "Null pool parameters!");
if (!(str1Found = pool_find(str1Pool, (void*)str1, str1Begin, str1End))
&& str1Complete) {
std::cout << "String 1 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
if (!(str2Found = pool_find(str2Pool, (void*)str2, str2Begin, str2End))
&& str2Complete) {
std::cout << "String 2 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool, SRC_INFO_ARGS);
}
// Check if strings are terminated.
if (str1Found && !isTerminated(str1, str1End, str1Size)) {
std::cout << "String 1 not terminated within bounds!\n";
OOB_VIOLATION(str1Begin, str1Pool, str1Begin, str1Size, SRC_INFO_ARGS);
}
if (str2Found && !isTerminated(str2, str2End, str2Size)) {
std::cout << "String 2 not terminated within bounds!\n";
OOB_VIOLATION(str2Begin, str2Pool, str2Begin, str2Size, SRC_INFO_ARGS);
}
return strcspn(str1, str2);
}
/**
* Secure runtime wrapper function to replace memchr()
*
* @param stringPool Pool handle for the string
* @param string Memory object
* @param c An int value to be found
* @param n Number of bytes to search in
* @return Pointer to position where c is first found
*/
void *
pool_memchr(DebugPoolTy *stringPool,
void *string,
int c,
size_t n,
const uint8_t complete) {
return pool_memchr_debug(stringPool, string, c, n,complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace memchr()
*
* @param stringPool Pool handle for the string
* @param string Memory object
* @param c An int value to be found
* @param n Number of bytes to search in
* @return Pointer to position where c is first found
*/
void *
pool_memchr_debug(DebugPoolTy *stringPool,
void *string, int c,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t stringSize = 0;
void *stringBegin = string, *stringEnd = NULL, *stop= NULL;
const bool strComplete = ARG1_COMPLETE(complete);
bool strFound;
//assert(stringPool && string && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(strFound = pool_find(stringPool, (void*)string, stringBegin, stringEnd))
&& strComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(string,stringPool, SRC_INFO_ARGS);
}
if (strFound)
{
stringSize = (char *)stringEnd - (char *)string + 1;
stop = memchr(string,c,stringSize);
if (stop && (char*)stop<(char*)string+std::min(n,stringSize))
return stop;
else {
std::cout << "Possible read out of bound in memory object!\n";
OOB_VIOLATION(stringBegin, stringPool, stringBegin, stringSize, SRC_INFO_ARGS);
return NULL;
}
}
else
return memchr(string, c, n);
}
/**
* Secure runtime wrapper function to replace memccpy()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param c It stops copying when it sees this char
* @param n Maximum number of bytes to copy
* @return A pointer to the first byte after c in dst or,
* If c was not found in the first n bytes of s2, it returns a null pointer.
*/
void *
pool_memccpy(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
char c,
size_t n,
const uint8_t complete) {
return pool_memccpy_debug(dstPool,srcPool,dst,src, c, n,complete,DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace memccpy()
*
* @param dstPool Pool handle for destination memory area
* @param srcPool Pool handle for source memory area
* @param dst Destination memory area
* @param src Source memory area
* @param c It stops copying when it sees this char
* @param n Maximum number of bytes to copy
* @return A pointer to the first byte after c in dst or,
* If c was not found in the first n bytes of s2, it returns a null pointer.
*/
void *
pool_memccpy_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
void *dst,
const void *src,
char c,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL, *stop = NULL;
const bool dstComplete = ARG1_COMPLETE(complete);
const bool srcComplete = ARG2_COMPLETE(complete);
bool dstFound, srcFound;
//assert(dstPool && srcPool && dst && src && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!(dstFound = pool_find(dstPool, (void*)dst, dstBegin, dstEnd))
&& dstComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
if(!(srcFound = pool_find(srcPool, (void*)src, srcBegin, srcEnd))
&& srcComplete){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool, SRC_INFO_ARGS);
}
if (dstFound && srcFound)
{
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
stop= memchr((void*)src,c,srcSize);
if(!stop){
if (n > srcSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize, SRC_INFO_ARGS);
}
if (n >dstSize) {
std::cout << "Cannot copy more bytes than the size of the destination!\n";
WRITE_VIOLATION(dstBegin, dstPool, dstSize, srcSize, SRC_INFO_ARGS);
}
if(isOverlapped(dst,(const char*)dst+n-1,src,(const char*)src+n-1)){
std::cout<<"Two memory objects overlap each other!/n";
LOAD_STORE_VIOLATION(dst,dstPool, SRC_INFO_ARGS);
}
}
if((size_t)((char*)stop-(char*)src+1)>dstSize){
std::cout << "Cannot copy more bytes than the size of the destination!\n";
WRITE_VIOLATION(dstBegin, dstPool, dstSize, srcSize, SRC_INFO_ARGS);
}
}
memccpy(dst, src, c, n);
return dst;
}