blob: aa7c45b84931b992bcffa106e95c3f358a4387a6 [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 "PoolAllocator.h"
#include <cassert>
#include <algorithm>
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 ? end - s : maxlen);
}
}
/**
* Optimized inline assembly versions 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
*/
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 .1 \n"
" movsbl (%%edx), %%ecx \n"
" movb %%cl, (%%eax) \n"
" incl %%eax \n"
" incl %%edx \n"
" testl %%ecx, %%ecx \n"
" jne .0 \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);
#endif
return copied;
}
/**
* Secure runtime wrapper function to replace strcpy()
*
* @param srcPool Pool handle for source string
* @param dstPool Pool handle for destination buffer
* @param src Source string pointer
* @param dst Destination string pointer
* @return Destination string pointer
*/
char *pool_strcpy(PoolTy *srcPool, PoolTy *dstPool, const char *src, char *dst) {
size_t copied = 0, stop = 0;
void *srcBegin = (char *)src, *srcEnd = NULL, *dstBegin = dst, *dstEnd = NULL;
assert(srcPool && dstPool && src && dst && "CStdLib (pool_strcpy): Null pool parameters!\n");
bool foundSrc = srcPool->Objects.find(srcBegin, srcBegin, srcEnd);
assert(foundSrc && "CStdLib (pool_strcpy): Source string not found in pool!\n");
bool foundDst = dstPool->Objects.find(dstBegin, dstBegin, dstEnd);
assert(foundDst && "CStdLib (pool_strcpy): Destination buffer not found in pool!\n");
assert((srcBegin <= srcEnd) && "CStdLib (pool_strcpy): Source pointer out of bounds!\n");
assert((dstBegin <= dstEnd) && "CStdLib (pool_strcpy): Destination pointer out of bounds!\n");
stop = std::min((char *)srcEnd - (char *)src, (char *)dstEnd - dst);
copied = strncpy_asm(dst, src, stop);
assert(!dst[copied] && "CStdLib (pool_strcpy): Copy violated destination bounds!\n");
return dst;
}