blob: 0e575213f77313e8077d9c94ba3d4cf69a4dba08 [file] [log] [blame]
//===------- CStdLib.cpp - CStdLib transform pass runtime functions -------===//
//
// 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 all external functions included by the CStdLib pass.
//
//===----------------------------------------------------------------------===//
#include "DebugReport.h"
#include "PoolAllocator.h"
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream> // Debug
#define TAG unsigned tag
#define SRC_INFO const char *SourceFile, unsigned lineNo
// Default versions of arguments to debug functions
#define DEFAULT_TAG 0
#define DEFAULT_SRC_INFO "<Unknown>", 0
#define SRC_INFO_ARGS SourceFile, lineNo
// Various violation types
#define OOB_VIOLATION(fault_ptr, handle, start, len) \
OutOfBoundsViolation v; \
v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS; \
v.faultPC = __builtin_return_address(0); \
v.faultPtr = fault_ptr; \
v.SourceFile = SourceFile; \
v.lineNo = lineNo; \
v.PoolHandle = handle; \
v.objStart = start; \
v.objLen = len; \
v.dbgMetaData = NULL; \
ReportMemoryViolation(&v);
#define WRITE_VIOLATION(fault_ptr, handle, dst_sz, src_sz) \
WriteOOBViolation v; \
v.type = ViolationInfo::FAULT_WRITE_OUT_OF_BOUNDS,\
v.faultPC = __builtin_return_address(0), \
v.faultPtr = fault_ptr, \
v.SourceFile = SourceFile, \
v.lineNo = lineNo, \
v.PoolHandle = handle, \
v.dstSize = dst_sz, \
v.srcSize = src_sz, \
v.dbgMetaData = NULL; \
ReportMemoryViolation(&v);
#define LOAD_STORE_VIOLATION(fault_ptr, handle) \
DebugViolationInfo v; \
v.faultPC = __builtin_return_address(0), \
v.faultPtr = fault_ptr, \
v.dbgMetaData = NULL, \
v.PoolHandle = handle, \
v.SourceFile = SourceFile, \
v.lineNo = lineNo; \
ReportMemoryViolation(&v);
using namespace NAMESPACE_SC;
extern "C" {
size_t strnlen(const char *s, size_t maxlen) {
size_t i;
for (i = 0; i < maxlen && s[i]; ++i)
;
return i;
}
size_t strnlen_opt(const char *s, size_t maxlen) {
const char *end = (const char *)memchr(s, '\0', maxlen);
return (end ? ((size_t) (end - s)) : maxlen);
}
}
/**
* Optimized inline assembly implementation of strncpy that returns the number
* of characters copied (including \0)
*
* @param dst Destination string pointer
* @param src Source string pointer
* @param size Number of characters to copy
* @return Number of characters copied (including \0)
*/
static size_t strncpy_asm(char *dst, const char *src, size_t size) {
long copied;
#if defined(i386) || defined(__i386__) || defined(__x86__)
__asm__ __volatile__(
"0: xorl %%ecx, %%ecx \n"
" cmpl %%edi, %%ecx \n"
" adcl $0, %%ecx \n"
" decl %%edi \n"
" testl %%ecx, %%ecx \n"
" je 1f \n"
" movsbl (%%edx), %%ecx \n"
" movb %%cl, (%%eax) \n"
" incl %%eax \n"
" incl %%edx \n"
" testl %%ecx, %%ecx \n"
" jne 0b \n"
"1: subl %%esi, %%eax \n"
: "=a"(copied)
: "a"(dst), "S"(dst), "d"(src), "D"(size)
: "%ecx", "memory"
);
#else
strncpy(dst, src, size);
copied = strnlen(dst, size - 1);
#endif
return copied;
}
/**
* Check for string termination.
*
* @param start The start of the string
* @param end The end of the object. String is not scanned farther than here.
* @param p Reference to size object. Filled with the length of the string if
* string is terminated, otherwised filled with the size of the object.
* @return Whether the string is terminated within bounds.
*
* Note that start and end should be valid boundaries for a valid object.
*/
static bool isTerminated(void *start, void *end, size_t &p)
{
size_t max = 1 + ((char *)end - (char *)start), len;
len = strnlen((char *)start, max);
p = len;
if (len == max)
return false;
else
return true;
}
/**
*Check for object overlap.
*
* @param ptr1Start The start of the first memory object
* @param ptr1End The end of the first memory object or the bound that writing
* operation actually touch.
* @param ptr2Start The start of the second memory object
* @param ptr2End The end of the second memory object or the bound that writing
* operation actually touch.
*
* @return Whether these 2 memory object overlaps
*/
static bool isOverlapped(const void* ptr1Start,
const void* ptr1End,
const void* ptr2Start,
const void* ptr2End){
if( ((long int)ptr1Start>(long int)ptr2End && (long int)ptr1End>(long int)ptr2Start) ||
((long int)ptr1Start<(long int)ptr2End && (long int)ptr1End<(long int)ptr2Start) )
return false;
return true;
}
/**
* Function to search within the object and external object pools
*
* @param pool Pool handle
* @param poolBegin Pointer to set to the beginning of the pool handle
* @param poolEnd Pointer to set to the end of the pool handle
* @return Object found in pool
*/
bool pool_find(DebugPoolTy *pool, void *&poolBegin, void *&poolEnd) {
// Retrieve memory area's bounds from pool handle.
if (pool->Objects.find(poolBegin, poolBegin, poolEnd) || ExternalObjects.find(poolBegin, poolBegin, poolEnd))
return true;
return false;
}
/**
* Check if object bounds are valid. Report any errors.
*
* @param handle The pool handle this object comes from.
* @param start Start of object
* @param end End of object
*/
static inline void doOOBCheck(DebugPoolTy *handle, const void *start, const void *end, SRC_INFO)
{
if (end < start)
{
std::cout << "Pointer out of bounds!\n";
OutOfBoundsViolation v;
v.type = ViolationInfo::FAULT_OUT_OF_BOUNDS,
v.faultPC = __builtin_return_address(0),
v.faultPtr = start,
v.dbgMetaData = NULL,
v.PoolHandle = handle,
v.SourceFile = SourceFile,
v.lineNo = lineNo,
v.objStart = start,
v.objLen = ((char*)end - (char *)start) + 1;
ReportMemoryViolation(&v);
}
}
/**
* Secure runtime wrapper function to replace strchr()
*
* @param sp Pool handle for string
* @param s String pointer
* @param c Character to find
* @return Pointer to first instance of c in s or NULL
*/
char *pool_strchr(DebugPoolTy *sp,
const char *s,
int c,
unsigned char complete)
{
return pool_strchr_debug(sp, s, c, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strchr()
*
* @param sPool Pool handle for string
* @param s String pointer
* @param c Character to find
* @return Pointer to first instance of c in s or NULL
*/
char *pool_strchr_debug(DebugPoolTy *sPool,
const char *s,
int c,
unsigned char complete,
TAG,
SRC_INFO)
{
void *objStart = (void *) s, *objEnd;
size_t len;
// Ensure string and pool are non-null.
assert(sPool && s && "Null pool handles!");
// Find string in pool.
if (!pool_find(sPool, objStart, objEnd)) {
std::cout << "String not found in pool!\n";
LOAD_STORE_VIOLATION(objStart, sPool)
}
// Check if string is out of bounds.
doOOBCheck(sPool, objStart, objEnd, SRC_INFO_ARGS);
// Check if string is terminated.
if (!isTerminated(objStart, objEnd, len)) {
std::cout << "String not terminated within bounds\n";
OOB_VIOLATION(s, sPool, s, len);
}
return strchr((char*)s, c);
}
/**
* 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(DebugPoolTy *sPool,
const char *s,
int c,
const unsigned char 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 unsigned char complete,
TAG,
SRC_INFO)
{
void *objStart = (void *) s, *objEnd;
size_t len;
// Ensure string and pool are non-null.
assert(sPool && s && "Null pool handles!");
// Find string in pool.
if (!pool_find(sPool, objStart, objEnd)) {
std::cout << "String not found in pool!\n";
LOAD_STORE_VIOLATION(objStart, sPool)
}
// Check if string is out of bounds.
doOOBCheck(sPool, objStart, objEnd, SRC_INFO_ARGS);
// Check if string is terminated.
if (!isTerminated(objStart, objEnd, len)) {
std::cout << "String not terminated within bounds\n";
OOB_VIOLATION(s, sPool, s, len);
}
return strrchr((char*)s, c);
}
char *pool_strstr(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const char *s1,
const char *s2,
unsigned char complete)
{
return pool_strstr_debug(s1Pool, s2Pool, s1, s2, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
char *pool_strstr_debug(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const char *s1,
const char *s2,
unsigned char complete,
TAG,
SRC_INFO)
{
void *s1Begin = (void *) s1, *s1End;
void *s2Begin = (void *) s2, *s2End;
size_t s1Len, s2Len;
// Ensure non-null arguments.
assert(s1Pool && s1 && s2Pool && s2 && "Null pool parameters!");
// Find strings in the pool.
if (!pool_find(s1Pool, s1Begin, s1End)) {
std::cout << "String not found in pool!\n";
LOAD_STORE_VIOLATION(s1Begin, s1Pool)
}
if (!pool_find(s2Pool, s2Begin, s2End)) {
std::cout << "String not found pool!\n";
LOAD_STORE_VIOLATION(s2Begin, s2Pool)
}
// Check if strings are out of bounds.
doOOBCheck(s1Pool, s1Begin, s1End, SRC_INFO_ARGS);
doOOBCheck(s2Pool, s2Begin, s2End, SRC_INFO_ARGS);
// Check if both strings are terminated.
if (!isTerminated(s1Begin, s1End, s1Len)) {
std::cout << "String not terminated within bounds!\n";
OOB_VIOLATION(s1Begin, s1Pool, s1Begin, s1Len)
}
if (!isTerminated(s2Begin, s2End, s2Len)) {
std::cout << "String not terminated within bounds!\n";
OOB_VIOLATION(s2Begin, s2Pool, s2Begin, s2Len)
}
return strstr((char*)s1, s2);
}
/**
* Secure runtime wrapper function to replace strcat()
*
* @param dp Pool handle for destination string
* @param sp Pool handle for source string
* @param d Destination string pointer
* @param s Source string pointer
* @return Destination string pointer
*/
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()
*
* @param dstPool Pool handle for destination string
* @param srcPool Pool handle for source string
* @param dst Destination string pointer
* @param src Source string pointer
* @return Destination string pointer
*/
char *pool_strcat_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
const unsigned char complete,
TAG,
SRC_INFO)
{
size_t srcLen, dstLen, maxLen, catLen;
void *dstBegin = (void *) dst, *dstEnd = NULL;
void *srcBegin = (void *) src, *srcEnd = NULL;
char *dstNulPosition;
// Ensure non-null pool and string arguments.
assert(dstPool && dst && srcPool && src && "Null pool parameters!");
// Find the strings in the pool.
if (!pool_find(dstPool, dstBegin, dstEnd)) {
std::cout << "Destination string not found in pool\n";
LOAD_STORE_VIOLATION(dstBegin, dstPool)
}
if (!pool_find(srcPool, srcBegin, srcEnd)) {
std::cout << "Source string not found in pool!\n";
LOAD_STORE_VIOLATION(srcBegin, srcPool)
}
// Check if the strings are out of bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, SRC_INFO_ARGS);
// Check if both src and dst are terminated.
if (!isTerminated(dstBegin, dstEnd, dstLen)) {
std::cout << "Destination not terminated within bounds\n";
OOB_VIOLATION(dstBegin, dstPool, dstBegin, dstLen)
}
if (!isTerminated(srcBegin, srcEnd, srcLen)) {
std::cout << "Source not terminated within bounds\n";
OOB_VIOLATION(srcBegin, srcPool, srcBegin, srcLen)
}
// maxLen is the maximum length string dst can hold without going out of bounds
maxLen = (char *) dstEnd - (char *) dstBegin;
// 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)
}
// Append at the end of dst so concatenation doesn't have to scan dst again.
dstNulPosition = &dst[dstLen];
strncat(dstNulPosition, src, srcLen);
// strcat returns the destination string.
return dst;
}
/**
* Secure runtime wrapper function to replace strncat()
*
* @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
* @return Destination string pointer
*/
char *pool_strncat(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
size_t n,
const unsigned char complete)
{
return pool_strncat_debug(dstPool, srcPool, dst, src, n, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strncat()
*
* @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
* @return Destination string pointer
*/
char *pool_strncat_debug(DebugPoolTy *dstPool,
DebugPoolTy *srcPool,
char *dst,
const char *src,
size_t n,
const unsigned char complete,
TAG,
SRC_INFO)
{
void *dstBegin = (void *) dst, *dstEnd;
void *srcBegin = (void *) src, *srcEnd;
size_t dstLen, srcLen, maxLen, catLen, srcAmt;
char *dstNulPosition;
// Ensure non-null arguments.
assert(dstPool && dst && srcPool && src && "Null pool parameters!");
// Retrieve destination and source strings from pool.
if (!pool_find(dstPool, dstBegin, dstEnd)) {
std::cout << "Destination string not found in pool!\n";
LOAD_STORE_VIOLATION(dstBegin, dstPool)
}
if (!pool_find(srcPool, srcBegin, srcEnd)) {
std::cout << "Source string not found in pool!\n";
LOAD_STORE_VIOLATION(srcBegin, srcPool)
}
// Check if strings are in bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, SRC_INFO_ARGS);
// Check if dst is nul terminated.
if (!isTerminated(dstBegin, dstEnd, dstLen)) {
std::cout << "String not terminated within bounds\n";
OOB_VIOLATION(dst, dstPool, dstBegin, dstLen)
}
// 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 (!isTerminated(srcBegin, srcEnd, srcLen) && srcLen < n) {
std::cout << "Source object too small\n";
OOB_VIOLATION(src, srcPool, srcBegin, srcLen)
}
// 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);
// maxLen is the maximum length string dst can hold without overflowing.
maxLen = (char *) dstEnd - (char *) dstBegin;
// 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)
}
// 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;
}
/**
* Secure runtime wrapper function to replace strpbrk()
*
* @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(DebugPoolTy *sp,
DebugPoolTy *ap,
const char *s,
const char *a,
const unsigned char complete)
{
return pool_strpbrk_debug(sp, ap, s, a, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strpbrk()
*
* @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 unsigned char complete,
TAG,
SRC_INFO)
{
void *sBegin = (void *) s, *sEnd;
void *aBegin = (void *) a, *aEnd;
size_t sLen, aLen;
// Ensure non-null arguments.
assert(sPool && s && aPool && a && "Null pool parameters!");
// Retrieve strings from pool.
if (!pool_find(sPool, sBegin, sEnd)) {
std::cout << "String not found in pool!\n";
LOAD_STORE_VIOLATION(sBegin, sPool)
}
if (!pool_find(aPool, aBegin, aEnd)) {
std::cout << "String not found pool!\n";
LOAD_STORE_VIOLATION(aBegin, aPool)
}
// Check if strings fall in bounds.
doOOBCheck(sPool, sBegin, sEnd, SRC_INFO_ARGS);
doOOBCheck(aPool, aBegin, aEnd, SRC_INFO_ARGS);
// Check if strings are terminated.
if (!isTerminated(sBegin, sEnd, sLen)) {
std::cout << "String not terminated within bounds!\n";
OOB_VIOLATION(sBegin, sPool, sBegin, sLen)
}
if (!isTerminated(aBegin, aEnd, aLen)) {
std::cout << "String not terminated within bounds!\n";
OOB_VIOLATION(aBegin, aPool, aBegin, aLen)
}
return strpbrk((char*)s, a);
}
/**
* 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 position of first different character, or 0 it they are the same
*/
int pool_strcmp(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2){
return pool_strcmp_debug(s1p,s2p,s1,s2, 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 position of first different character, or 0 it they are the same
*/
int pool_strcmp_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
TAG,
SRC_INFO) {
size_t str1Size = 0, str2Size = 0;
void *str1Begin =(void*)str1, *str1End = NULL, *str2Begin = (void*)str2, *str2End = NULL;
assert(str1Pool && str2Pool && str2 && str1 && "Null pool parameters!");
if (!pool_find(str1Pool, str1Begin, str1End)) {
std::cout << "String 1 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool)
}
if (!pool_find(str2Pool, str2Begin, str2End)) {
std::cout << "String 2 not found in pool!\n";
LOAD_STORE_VIOLATION(str1Begin, str1Pool)
}
// Check that both strings pointers fall within their respective bounds.
doOOBCheck(str1Pool, str1Begin, str1End, SRC_INFO_ARGS);
doOOBCheck(str2Pool, str2Begin, str2End, SRC_INFO_ARGS);
// Check if strings are terminated.
if (!isTerminated(str1Begin, str1End, str1Size)) {
std::cout << "String 1 not terminated within bounds!\n";
OOB_VIOLATION(str1Begin, str1Pool, str1Begin, str1Size)
}
if (!isTerminated(str2Begin, str2End, str2Size)) {
std::cout << "String 2 not terminated within bounds!\n";
OOB_VIOLATION(str2Begin, str2Pool, str2Begin, str2Size)
}
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) {
return pool_memcpy_debug(dstPool,srcPool,dst,src, n,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,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
assert(dstPool && srcPool && dst && src && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!pool_find(dstPool, dstBegin, dstEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool);
}
if(!pool_find(srcPool, srcBegin, srcEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool);
}
// Check that both the destination and source pointers fall within their respective bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, SRC_INFO_ARGS);
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
if (n > srcSize || n > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize);
}
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);
}
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) {
return pool_memmove_debug(dstPool,srcPool,dst,src, n,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,
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!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!pool_find(dstPool, dstBegin, dstEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool);
}
if(!pool_find(srcPool, srcBegin, srcEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool);
}
// Check that both the destination and source pointers fall within their respective bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, SRC_INFO_ARGS);
// 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);
}
memmove(dst, src, stop);
return dst;
}
/**
* 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) {
return pool_mempcpy_debug(dstPool,srcPool,dst,src, n,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,
TAG,
SRC_INFO){
size_t dstSize = 0, srcSize = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
assert(dstPool && srcPool && dst && src && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!pool_find(dstPool, dstBegin, dstEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool);
}
if(!pool_find(srcPool, srcBegin, srcEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool);
}
// Check that both the destination and source pointers fall within their respective bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, SRC_INFO_ARGS);
// 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);
}
// 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);
}
return mempcpy(dst, src, n);
}
/**
* Secure runtime wrapper function to replace memset()
*
* @param stringPool Pool handle for the string
* @param string String pointer
* @return Pointer to memory area
*/
void *pool_memset(DebugPoolTy *stringPool,
void *string,
int c,
size_t n,
const unsigned char 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
* @return Pointer to memory area
*/
void *pool_memset_debug(DebugPoolTy *stringPool,
void *string,
int c,
size_t n,
const unsigned char complete,
TAG,
SRC_INFO){
size_t stringSize = 0;
void *stringBegin = string, *stringEnd = NULL;
assert(stringPool && string && "Null pool parameters!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!pool_find(stringPool, stringBegin, stringEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(string,stringPool);
}
// check if string falls in bound
doOOBCheck(stringPool, stringBegin, stringEnd, SRC_INFO_ARGS);
stringSize = (char *)stringEnd - (char *)string + 1;
if (n > stringSize) {
std::cout << "Cannot write more bytes than the size of the destination string!\n";
WRITE_VIOLATION(stringBegin, stringPool, stringSize, 0);
}
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 unsigned char 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 unsigned char complete, TAG, SRC_INFO) {
size_t dstSize = 0, srcSize = 0, len = 0;
void *dstBegin = dst, *dstEnd = NULL, *srcBegin = (char *)src, *srcEnd = NULL;
// 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(!pool_find(dstPool, dstBegin, dstEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool);
}
if(!pool_find(srcPool, srcBegin, srcEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool);
}
// Check that both the destination and source pointers fall within their respective bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, SRC_INFO_ARGS);
// Calculate the maximum number of bytes to copy.
dstSize = (char *)dstEnd - (char *)dst + 1;
srcSize = (char *)srcEnd - (char *)src + 1;
len = strnlen(src,srcSize);
if (len == srcSize) {
std::cout << "Source string is not NULL terminated!\n";
OOB_VIOLATION(src,srcPool,src,len)
}
if (len+1 > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(dstBegin, dstPool, dstSize, srcSize);
}
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);
}
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 unsigned char complete) {
return pool_strlen_debug(stringPool, string, complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* 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_debug(DebugPoolTy *stringPool, const char *string, const unsigned char complete, TAG, SRC_INFO) {
size_t len = 0, maxlen = 0;
void *stringBegin = (char *)string, *stringEnd = NULL;
assert(stringPool && string && "Null pool parameters!");
// Retrieve the string bound from pool
if(!pool_find(stringPool, stringBegin, stringEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(string,stringPool);
}
// Boundary check
doOOBCheck(stringPool, stringBegin, stringEnd, SRC_INFO_ARGS);
// Null termination check
maxlen = (char *)stringEnd - (char *)string+1;
len = strnlen(string, maxlen);
if (len == maxlen) {
std::cout << "String not terminated within bounds!\n";
OOB_VIOLATION(string,stringPool,string,len)
}
return len;
}
/**
* 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 unsigned char 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 unsigned char 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!");
// Retrieve both the destination and source buffer's bounds from the pool handle.
if(!pool_find(dstPool, dstBegin, dstEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(dst,dstPool);
}
if(!pool_find(srcPool, srcBegin, srcEnd)){
std::cout<<"Memory object not found in pool!\n";
LOAD_STORE_VIOLATION(src,srcPool);
}
// Check that both the destination and source pointers fall within their respective bounds.
doOOBCheck(dstPool, dstBegin, dstEnd, SRC_INFO_ARGS);
doOOBCheck(srcPool, srcBegin, srcEnd, 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 (stop==srcSize && n > srcSize) {
std::cout << "String is not bounded and copy length is out of bound!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize);
}
// Check if destination will be overflowed
if (n > dstSize) {
std::cout << "Cannot copy more bytes than the size of the source!\n";
WRITE_VIOLATION(srcBegin, srcPool, dstSize, srcSize);
}
// Check if two strings are over lapped
if(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);
}
// Copy string
strncpy_asm(dst, src, stop+1);
// Check whether result string is NULL terminated
if(!isTerminated(dst,dstEnd,stop)){
std::cout<<"NULL terminator is not copied!\n";
OOB_VIOLATION(dst,dstPool,dst,stop);
}
// 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 unsigned char 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 unsigned char complete, TAG, SRC_INFO) {
size_t len = 0, difflen = 0;
void *stringBegin = (char *)string, *stringEnd = NULL;
assert(stringPool && string && "Null pool parameters!");
// Retrieve string from the pool
if(!pool_find(stringPool, stringBegin, stringEnd)){
std::cout<<"String not found in pool!\n";
LOAD_STORE_VIOLATION(string,stringPool);
}
// boundary check for string object
doOOBCheck(stringPool, stringBegin, stringEnd, 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(maxlen > len && len==difflen){
std::cout<<"String is not bounded!\n";
OOB_VIOLATION(string,stringPool,string,difflen);
}
return len;
}