blob: 1ab7722c756dfda932bb90bba4733c970ff8e010 [file] [log] [blame]
//===------- strings.cpp - CStdLib runtime for functions in <strings.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
// <strings.h>.
//
//===----------------------------------------------------------------------===//
#include "CStdLib.h"
/*
* pool_bcmp()
*
* This is the non-debug version of pool_bcmp_debug().
*
*/
int
pool_bcmp(DebugPoolTy *aPool,
DebugPoolTy *bPool,
const void *a,
const void *b,
size_t n,
const uint8_t complete)
{
return pool_bcmp_debug(aPool, bPool, a, b, n, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace bcmp(), debug version
*
* Returns 0 if the first n bytes of the memory areas pointed to by a and b are
* identical in value, and nonzero otherwise.
*
* Attempts to verify that the first n bytes of the memory areas pointed to by
* a and b are both completely contained within their respective objects.
*
* @param aPool Pool handle for a
* @param bPool Pool handle for b
* @param a Pointer to first memory area
* @param b Pointer to second memory area
* @param n Amount of bytes to compare
* @param complete Completeness bitwise vector
* @param TAG Tag infomation for debug
* @param SRC_INFO Source and line information for debug
* @return Returns 0 if the first n bytes of the areas pointed to by
* a and b are identical in value, and nonzero otherwise.
*
*/
int
pool_bcmp_debug(DebugPoolTy *aPool,
DebugPoolTy *bPool,
const void *a,
const void *b,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO)
{
void *aStart = NULL, *aEnd = NULL;
void *bStart = NULL, *bEnd = NULL;
const bool aComplete = ARG1_COMPLETE(complete);
const bool bComplete = ARG2_COMPLETE(complete);
bool aFound, bFound;
// Retrieve both objects from their pointers' pools.
if (!(aFound = pool_find(aPool, (void *) a, aStart, aEnd)) && aComplete)
LOAD_STORE_VIOLATION(a, aPool, SRC_INFO_ARGS);
if (!(bFound = pool_find(bPool, (void *) b, bStart, bEnd)) && bComplete)
LOAD_STORE_VIOLATION(b, bPool, SRC_INFO_ARGS);
// Determine if both pointers can be read safely up to n bytes into their
// target without going out of bounds of the memory object.
size_t aBytes = 1 + (char *) aEnd - (char *) a;
if (aFound && n > aBytes)
OOB_VIOLATION(a, aPool, a, n, SRC_INFO_ARGS);
size_t bBytes = 1 + (char *) bEnd - (char *) b;
if (bFound && n > bBytes)
OOB_VIOLATION(b, bPool, b, n, SRC_INFO_ARGS);
return bcmp(a, b, n);
}
/*
* pool_bcopy()
*
* This is the non-debug version of pool_bcmp_debug().
*
*/
void
pool_bcopy(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const void *s1,
void *s2,
size_t n,
const uint8_t complete)
{
pool_bcopy_debug(s1Pool, s2Pool, s1, s2, n, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace bcopy(), debug version
*
* Copies n bytes from s1 into s2.
*
* Attempts to verify that:
* - the first n bytes of s1 are completely contained in s1's memory object
* - the area pointed to by s2 has enough space to hold the result of the copy
*
* @param s1Pool Pool handle for s1
* @param s2Pool Pool handle for s2
* @param s1 Pointer to source memory area
* @param s2 Pointer to destination memory area
* @param n Amount of bytes to copy
* @param complete Completeness bitwise vector
* @param TAG Tag infomation for debug
* @param SRC_INFO Source and line information for debug
* @return Does not return a value
*
*/
void
pool_bcopy_debug(DebugPoolTy *s1Pool,
DebugPoolTy *s2Pool,
const void *s1,
void *s2,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO)
{
void *s1Start = NULL, *s1End = NULL;
void *s2Start = NULL, *s2End = NULL;
const bool s1Complete = ARG1_COMPLETE(complete);
const bool s2Complete = ARG2_COMPLETE(complete);
bool s1Found, s2Found;
// Retrieve both memory objects' boundaries from their pointers' pools.
if (!(s1Found = pool_find(s1Pool, (void *) s1, s1Start, s1End)) && s1Complete)
LOAD_STORE_VIOLATION(s1, s1Pool, SRC_INFO_ARGS);
if (!(s2Found = pool_find(s2Pool, s2, s2Start, s2End)) && s2Complete)
LOAD_STORE_VIOLATION(s2, s2Pool, SRC_INFO_ARGS);
// Determine if the copy operation does not read or write data out of bounds
// of the pointer's memory areas.
size_t s1Bytes = 1 + (char *) s1End - (char *) s1;
if (s1Found && n > s1Bytes)
OOB_VIOLATION(s1, s1Pool, s1, n, SRC_INFO_ARGS);
size_t s2Bytes = 1 + (char *) s2End - (char *) s2;
if (s2Found && n > s2Bytes)
WRITE_VIOLATION(s2, s2Pool, s2Bytes, n, SRC_INFO_ARGS);
bcopy(s1, s2, n);
}
/*
* pool_bzero()
*
* This is the non-debug version of pool_bzero_debug().
*
*/
void
pool_bzero(DebugPoolTy *sPool,
void *s,
size_t n,
const uint8_t complete)
{
pool_bzero_debug(sPool, s, n, complete, DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace bzero(), debug version
*
* Overwrites the first n bytes of the memory area pointed to by s with bytes
* of value 0.
*
* Attempts to verify that the first n bytes of s are completely contained
* in s's memory object.
*
* @param sPool Pool handle for s
* @param s Pointer to memory area to be zeroed
* @param n Amount of bytes to zero
* @param complete Completeness bitwise vector
* @param TAG Tag infomation for debug
* @param SRC_INFO Source and line information for debug
* @return Does not return a value
*
*/
void
pool_bzero_debug(DebugPoolTy *sPool,
void *s,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO)
{
void *sStart = NULL, *sEnd = NULL;
const bool sComplete = ARG1_COMPLETE(complete);
bool sFound;
// Get the memory object that s points to from the pool.
if (!(sFound = pool_find(sPool, (void *) s, sStart, sEnd)) && sComplete)
LOAD_STORE_VIOLATION(s, sPool, SRC_INFO_ARGS);
// Determine if the write operation would write beyond the end of the
// memory object.
size_t sBytes = 1 + (char *) sEnd - (char *) s;
if (sFound && n > sBytes)
WRITE_VIOLATION(s, sPool, sBytes, n, SRC_INFO_ARGS);
bzero(s, n);
}
/*
* pool_index()
*
* This is the non-debug version of pool_index_debug().
*
*/
char *
pool_index(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete)
{
return pool_index_debug(sPool, s, c, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace index(), debug version
*
* Returns a pointer to the first instance of the character c in the string s,
* or NULL if c is not found.
*
* Attempts to verify that s is a string terminated within object boundaries.
*
* @param sPool Pool handle for s
* @param s Pointer to string to search
* @param c Character to find in s
* @param complete Completeness bitwise vector
* @param TAG Tag infomation for debug
* @param SRC_INFO Source and line information for debug
* @return A pointer to the first instance of c in s, or NULL if c is
* not found
*
*/
char *
pool_index_debug(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete,
TAG,
SRC_INFO)
{
validStringCheck(s, sPool, ARG1_COMPLETE(complete), "index", SRC_INFO_ARGS);
return index((char *)s, c);
}
/*
* pool_rindex()
*
* This is the non-debug version of pool_rindex_debug().
*
*/
char *
pool_rindex(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete)
{
return pool_rindex_debug(sPool, s, c, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace rindex(), debug version
*
* Returns a pointer to the last instance of the character c in the string s,
* or NULL if c is not found.
*
* Attempts to verify that s is a string terminated within object boundaries.
*
* @param sPool Pool handle for s
* @param s Pointer to string to search
* @param c Character to find in s
* @param complete Completeness bitwise vector
* @param TAG Tag infomation for debug
* @param SRC_INFO Source and line information for debug
* @return A pointer to the last instance of c in s, or NULL if c is
* not found
*
*/
char *
pool_rindex_debug(DebugPoolTy *sPool,
const char *s,
int c,
const uint8_t complete,
TAG,
SRC_INFO)
{
validStringCheck(s, sPool, ARG1_COMPLETE(complete), "rindex", SRC_INFO_ARGS);
return rindex((char *)s, c);
}
/*
* pool_strcasecmp()
*
* This is the non-debug version of pool_strcasecmp_debug().
*
*/
int
pool_strcasecmp(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2,
const uint8_t complete)
{
return pool_strcasecmp_debug(s1p, s2p, s1, s2, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strcasecmp(), debug version
*
* Compares str1 and str2 in a case-insensitive manner.
*
* Attempts to verify that str1 and str2 point to valid strings terminated
* within their memory objects' boundaries.
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 First string to be compared
* @param str2 Second string to be compared
* @param complete Completeness bitwise vector
* @param TAG Tag information for debug
* @param SRC_INFO Source file and line number information for debug
* @return Returns zero if str1 = str2,
* a positive integer if str1 > str2
* a negative integer if str1 < str2,
* with string comparison done case insensitively
*
*/
int
pool_strcasecmp_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
const uint8_t complete,
TAG,
SRC_INFO)
{
validStringCheck(str1, str1Pool, ARG1_COMPLETE(complete),
"strcasecmp", SRC_INFO_ARGS);
validStringCheck(str2, str2Pool, ARG2_COMPLETE(complete),
"strcasecmp", SRC_INFO_ARGS);
return strcasecmp(str1, str2);
}
/*
* pool_strncasecmp()
*
* This is the non-debug version of pool_strncasecmp_debug().
*
*/
int
pool_strncasecmp(DebugPoolTy *s1p,
DebugPoolTy *s2p,
const char *s1,
const char *s2,
size_t num,
const uint8_t complete){
return pool_strncasecmp_debug(s1p, s2p, s1, s2, num, complete,
DEFAULT_TAG, DEFAULT_SRC_INFO);
}
/**
* Secure runtime wrapper function to replace strncasecmp()
*
* Compares at most the first n characters from str1 and str2 in a case
* insensitive manner.
*
* Attempts to verify that str1 and str2 point to valid strings terminated
* within memory object boundaries
*
* @param str1Pool Pool handle for str1
* @param str2Pool Pool handle for str2
* @param str1 First string to be compared
* @param str2 Second string to be compared
* @param complete Completeness bitwise vector
* @param TAG Tag information for debug
* @param SRC_INFO Source file and line number information for debug
* @return Taking s1 to be the string or array found in the
* first n characters of the area pointed to by str1,
* and s2 to be the string or array found in the first
* n characters of the area pointed to by s2, returns
* zero if s1 = s2, a positive integer if s1 > s2,
* and a negative integer if s1 < s2, with string
* comparison being done case insensitively
*
*/
int
pool_strncasecmp_debug(DebugPoolTy *str1Pool,
DebugPoolTy *str2Pool,
const char *str1,
const char *str2,
size_t n,
const uint8_t complete,
TAG,
SRC_INFO)
{
validStringCheck(str1, str1Pool, ARG1_COMPLETE(complete),
"strncasecmp", SRC_INFO_ARGS);
validStringCheck(str2, str2Pool, ARG2_COMPLETE(complete),
"strncasecmp", SRC_INFO_ARGS);
return strncasecmp(str1, str2, n);
}