diff --git a/compiler/Runtime.cpp b/compiler/Runtime.cpp index a97b30f6..eb988181 100644 --- a/compiler/Runtime.cpp +++ b/compiler/Runtime.cpp @@ -192,11 +192,14 @@ Runtime::Runtime(Module &M) { /// Decide whether a function is called symbolically. bool isInterceptedFunction(const Function &f) { static const StringSet<> kInterceptedFunctions = { - "malloc", "calloc", "mmap", "mmap64", "open", "read", - "lseek", "lseek64", "fopen", "fopen64", "fread", "fseek", - "fseeko", "rewind", "fseeko64", "getc", "ungetc", "memcpy", - "memset", "strncpy", "strchr", "memcmp", "memmove", "ntohl", - "fgets", "fgetc", "getchar", "bcopy", "bcmp", "bzero"}; + "malloc", "calloc", "mmap", "mmap64", "open", + "read", "lseek", "lseek64", "fopen", "fopen64", + "fread", "fseek", "fseeko", "rewind", "fseeko64", + "getc", "ungetc", "memcpy", "memset", "strncpy", + "strchr", "memcmp", "memmove", "ntohl", "fgets", + "fgetc", "getchar", "bcopy", "bcmp", "bzero", + "freopen", "fread_unlocked", "getc_unlocked", "getline", "getutxent", + "getutent"}; return (kInterceptedFunctions.count(f.getName()) > 0); } diff --git a/runtime/LibcWrappers.cpp b/runtime/LibcWrappers.cpp index cfe55525..3dcdf835 100644 --- a/runtime/LibcWrappers.cpp +++ b/runtime/LibcWrappers.cpp @@ -47,6 +47,9 @@ #include "Config.h" #include "Shadow.h" #include +#include +#include +#include #define SYM(x) x##_symbolized @@ -235,6 +238,23 @@ uint32_t SYM(lseek)(int fd, uint32_t offset, int whence) { return (uint32_t)-1; } +FILE *SYM(freopen)(const char *filename, const char *mode, FILE *stream) { + auto *result = freopen(filename, mode, stream); + _sym_set_return_expression(nullptr); + if (result != nullptr && !g_config.fullyConcrete && + !g_config.inputFile.empty() && + strstr(filename, g_config.inputFile.c_str()) != nullptr) { + if (inputFileDescriptor != -1) + std::cerr << "Warning: input file opened multiple times; this is not yet " + "supported" + << std::endl; + inputFileDescriptor = fileno(result); + inputOffset = 0; + } + + return result; +} + FILE *SYM(fopen)(const char *pathname, const char *mode) { auto *result = fopen(pathname, mode); _sym_set_return_expression(nullptr); @@ -275,6 +295,27 @@ size_t SYM(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream) { return result; } +size_t SYM(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream) { + tryAlternative(ptr, _sym_get_parameter_expression(0), SYM(fread_unlocked)); + tryAlternative(size, _sym_get_parameter_expression(1), SYM(fread_unlocked)); + tryAlternative(nmemb, _sym_get_parameter_expression(2), SYM(fread_unlocked)); + + auto result = fread_unlocked(ptr, size, nmemb, stream); + _sym_set_return_expression(nullptr); + + if (fileno(stream) == inputFileDescriptor) { + // Reading symbolic input. + ReadWriteShadow shadow(ptr, result * size); + std::generate(shadow.begin(), shadow.end(), + []() { return _sym_get_input_byte(inputOffset++); }); + } else if (!isConcrete(ptr, result * size)) { + ReadWriteShadow shadow(ptr, result * size); + std::fill(shadow.begin(), shadow.end(), nullptr); + } + + return result; +} + char *SYM(fgets)(char *str, int n, FILE *stream) { tryAlternative(str, _sym_get_parameter_expression(0), SYM(fgets)); tryAlternative(n, _sym_get_parameter_expression(1), SYM(fgets)); @@ -358,6 +399,44 @@ int SYM(fseeko64)(FILE *stream, uint64_t offset, int whence) { return result; } +struct utmp *SYM(getutent)() { + auto *result = getutent(); + _sym_set_return_expression(nullptr); + + // Reading symbolic input. + ReadWriteShadow shadow(result, sizeof(struct utmp)); + std::generate(shadow.begin(), shadow.end(), + []() { return _sym_get_input_byte(inputOffset++); }); + + return result; +} + +struct utmpx *SYM(getutxent)() { + return (utmpx *)SYM(getutent)(); +} + +ssize_t SYM(getline)(char **ptr, size_t *n, FILE *stream) { + + tryAlternative(ptr, _sym_get_parameter_expression(0), SYM(getline)); + tryAlternative(n, _sym_get_parameter_expression(1), SYM(getline)); + + auto result = getdelim(ptr, n, '\n', stream); + + _sym_set_return_expression(nullptr); + + if (fileno(stream) == inputFileDescriptor) { + // Reading symbolic input. + ReadWriteShadow shadow(*ptr, result * (*n)); + std::generate(shadow.begin(), shadow.end(), + []() { return _sym_get_input_byte(inputOffset++); }); + } else if (!isConcrete(*ptr, result * (*n))) { + ReadWriteShadow shadow(*ptr, result * (*n)); + std::fill(shadow.begin(), shadow.end(), nullptr); + } + + return result; +} + int SYM(getc)(FILE *stream) { auto result = getc(stream); if (result == EOF) { @@ -374,6 +453,22 @@ int SYM(getc)(FILE *stream) { return result; } +int SYM(getc_unlocked)(FILE *stream) { + auto result = getc_unlocked(stream); + if (result == EOF) { + _sym_set_return_expression(nullptr); + return result; + } + + if (fileno(stream) == inputFileDescriptor) + _sym_set_return_expression(_sym_build_zext( + _sym_get_input_byte(inputOffset++), sizeof(int) * 8 - 8)); + else + _sym_set_return_expression(nullptr); + + return result; +} + int SYM(fgetc)(FILE *stream) { auto result = fgetc(stream); if (result == EOF) {