Initial commit.
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Trail of Bits, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_MCTEST_MCTEST_H_
|
||||
#define INCLUDE_MCTEST_MCTEST_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Symbolize the data in the range `[begin, end)`. */
|
||||
extern void McTest_SymbolizeData(void *begin, void *end);
|
||||
|
||||
inline static void *McTest_Malloc(size_t num_bytes) {
|
||||
void *data = malloc(num_bytes);
|
||||
uintptr_t data_end = ((uintptr_t) data) + num_bytes;
|
||||
McTest_SymbolizeData(data, (void *) data_end);
|
||||
return data;
|
||||
}
|
||||
|
||||
#define MCTEST_MAKE_SYMBOLIC_ARRAY(Tname, tname) \
|
||||
inline static tname *McTest_Symbolic ## Tname ## Array(size_t num_elms) { \
|
||||
tname *arr = (tname *) malloc(sizeof(tname) * num_elms); \
|
||||
McTest_SymbolizeData(arr, &(arr[num_elms])); \
|
||||
return arr; \
|
||||
}
|
||||
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(Int64, int64_t)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(UInt64, uint64_t)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(Int, int)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(UInt, uint32_t)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(Short, int16_t)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(UShort, uint16_t)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(Char, char)
|
||||
MCTEST_MAKE_SYMBOLIC_ARRAY(UChar, unsigned char)
|
||||
|
||||
#undef MCTEST_MAKE_SYMBOLIC_ARRAY
|
||||
|
||||
/* Return a symbolic C string. */
|
||||
inline static char *McTest_CStr(size_t len) {
|
||||
char *str = (char *) malloc(sizeof(char) * len);
|
||||
if (len) {
|
||||
McTest_SymbolizeData(str, &(str[len - 1]));
|
||||
str[len - 1] = '\0';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Creates an assumption about a symbolic value. Returns `1` if the assumption
|
||||
* can hold and was asserted. */
|
||||
extern int McTest_Assume(int expr);
|
||||
|
||||
/* Asserts that `expr` must hold. */
|
||||
inline static void McTest_Assert(int expr) {
|
||||
if (McTest_Assume(!expr)) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a symbolic value of a given type. */
|
||||
extern int McTest_Bool(void);
|
||||
extern size_t McTest_Size(void);
|
||||
extern uint64_t McTest_UInt64(void);
|
||||
extern uint32_t McTest_UInt(void);
|
||||
|
||||
inline static int64_t McTest_Int64(void) {
|
||||
return (int64_t) McTest_UInt64();
|
||||
}
|
||||
|
||||
inline static int32_t McTest_Int(void) {
|
||||
return (int32_t) McTest_UInt();
|
||||
}
|
||||
|
||||
inline static uint16_t McTest_UShort(void) {
|
||||
return (uint16_t) McTest_UInt();
|
||||
}
|
||||
|
||||
inline static int16_t McTest_Short(void) {
|
||||
return (int16_t) McTest_UInt();
|
||||
}
|
||||
|
||||
inline static unsigned char McTest_UChar(void) {
|
||||
return (unsigned char) McTest_UInt();
|
||||
}
|
||||
|
||||
inline static char McTest_Char(void) {
|
||||
return (char) McTest_UInt();
|
||||
}
|
||||
|
||||
/* Return a symbolic value in a the range `[low_inc, high_inc]`. */
|
||||
#define MCTEST_MAKE_SYMBOLIC_RANGE(Tname, tname) \
|
||||
inline static tname McTest_ ## Tname ## InRange( \
|
||||
tname low, tname high) { \
|
||||
tname x = McTest_ ## Tname(); \
|
||||
(void) McTest_Assume(low <= x && x <= high); \
|
||||
return x; \
|
||||
}
|
||||
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(Int64, int64_t)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(UInt64, uint64_t)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(Int, int)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(UInt, uint32_t)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(Short, int16_t)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(UShort, uint16_t)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(Char, char)
|
||||
MCTEST_MAKE_SYMBOLIC_RANGE(UChar, unsigned char)
|
||||
|
||||
#undef MCTEST_MAKE_SYMBOLIC_RANGE
|
||||
|
||||
|
||||
/* Return a symbolic value of a given type. */
|
||||
extern int McTest_Bool(void);
|
||||
extern size_t McTest_Size(void);
|
||||
extern uint64_t McTest_UInt64(void);
|
||||
extern int64_t McTest_Int64(void);
|
||||
extern uint32_t McTest_UInt(void);
|
||||
extern int32_t McTest_Int(void);
|
||||
extern uint16_t McTest_UShort(void);
|
||||
extern int16_t McTest_Short(void);
|
||||
extern unsigned char McTest_UChar(void);
|
||||
extern char McTest_Char(void);
|
||||
|
||||
/* Predicates to check whether or not a particular value is symbolic */
|
||||
extern int McTest_IsSymbolicUInt(uint32_t x);
|
||||
|
||||
inline static int McTest_IsSymbolicInt(int x) {
|
||||
return McTest_IsSymbolicUInt((uint32_t) x);
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicUShort(uint16_t x) {
|
||||
return McTest_IsSymbolicUInt((uint32_t) x);
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicShort(int16_t x) {
|
||||
return McTest_IsSymbolicUInt((uint32_t) (uint16_t) x);
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicUChar(unsigned char x) {
|
||||
return McTest_IsSymbolicUInt((uint32_t) x);
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicChar(char x) {
|
||||
return McTest_IsSymbolicUInt((uint32_t) (unsigned char) x);
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicUInt64(uint64_t x) {
|
||||
return McTest_IsSymbolicUInt((uint32_t) x) ||
|
||||
McTest_IsSymbolicUInt((uint32_t) (x >> 32U));
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicInt64(int64_t x) {
|
||||
return McTest_IsSymbolicUInt64((uint64_t) x);
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicBool(int x) {
|
||||
return McTest_IsSymbolicInt(x);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wpointer-to-int-cast"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
|
||||
inline static int McTest_IsSymbolicPtr(void *x) {
|
||||
if (sizeof(void *) == 8) {
|
||||
return McTest_IsSymbolicUInt64((uint64_t) x);
|
||||
} else {
|
||||
return McTest_IsSymbolicUInt((uint32_t) x);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
inline static int McTest_IsSymbolicFloat(float x) {
|
||||
return McTest_IsSymbolicUInt(*((uint32_t *) &x));
|
||||
}
|
||||
|
||||
inline static int McTest_IsSymbolicDouble(double x) {
|
||||
return McTest_IsSymbolicUInt64(*((uint64_t *) &x));
|
||||
}
|
||||
|
||||
#define _MCTEST_TO_STR(a) __MCTEST_TO_STR(a)
|
||||
#define __MCTEST_TO_STR(a) #a
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define MCTEST_EXTERN_C extern "C"
|
||||
#else
|
||||
# define MCTEST_EXTERN_C
|
||||
#endif
|
||||
|
||||
#define McTest_EntryPoint(test_name) \
|
||||
_McTest_EntryPoint(test_name, __FILE__, __LINE__)
|
||||
|
||||
#define _McTest_EntryPoint(test_name, file, line) \
|
||||
static void McTest_Run_ ## test_name (void); \
|
||||
__attribute__((noinline, used)) \
|
||||
MCTEST_EXTERN_C void McTest_Register_ ## test_name (void) { \
|
||||
__asm__ __volatile__ ( \
|
||||
".pushsection .mctest_strtab,\"a\" \n" \
|
||||
"1: \n" \
|
||||
".asciz \"" _MCTEST_TO_STR(test_name) "\" \n" \
|
||||
"2: \n" \
|
||||
".asciz \"" file "\" \n" \
|
||||
".popsection \n" \
|
||||
".pushsection .mctest_entrypoints,\"a\" \n" \
|
||||
".balign 16 \n" \
|
||||
".quad %p0 \n" \
|
||||
".quad 1b \n" \
|
||||
".quad 2b \n" \
|
||||
".quad " _MCTEST_TO_STR(line) " \n" \
|
||||
".popsection \n" \
|
||||
: \
|
||||
: "i"(McTest_Run_ ## test_name) \
|
||||
); \
|
||||
} \
|
||||
void McTest_Run_ ## test_name(void)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif /* __cplusplus */
|
||||
#endif /* INCLUDE_MCTEST_MCTEST_H_ */
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Trail of Bits, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_MCTEST_MCTEST_HPP_
|
||||
#define INCLUDE_MCTEST_MCTEST_HPP_
|
||||
|
||||
#include <mctest/McTest.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace mctest {
|
||||
|
||||
inline static void *Malloc(size_t num_bytes) {
|
||||
return McTest_Malloc(num_bytes);
|
||||
}
|
||||
|
||||
inline static void SymbolizeData(void *begin, void *end) {
|
||||
McTest_SymbolizeData(begin, end);
|
||||
}
|
||||
|
||||
inline static bool Bool(void) {
|
||||
return static_cast<bool>(McTest_Bool());
|
||||
}
|
||||
|
||||
inline static size_t Size(void) {
|
||||
return McTest_Size();
|
||||
}
|
||||
|
||||
inline static uint64_t UInt64(void) {
|
||||
return McTest_UInt64();
|
||||
}
|
||||
|
||||
inline static int64_t Int64(void) {
|
||||
return McTest_Int64();
|
||||
}
|
||||
|
||||
inline static uint32_t UInt(void) {
|
||||
return McTest_UInt();
|
||||
}
|
||||
|
||||
inline static int32_t Int(void) {
|
||||
return McTest_Int();
|
||||
}
|
||||
|
||||
inline static uint16_t UShort(void) {
|
||||
return McTest_UShort();
|
||||
}
|
||||
|
||||
inline static int16_t Short(void) {
|
||||
return McTest_Short();
|
||||
}
|
||||
|
||||
inline static unsigned char UChar(void) {
|
||||
return McTest_UChar();
|
||||
}
|
||||
|
||||
inline static char Char(void) {
|
||||
return McTest_Char();
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(uint64_t x) {
|
||||
return McTest_IsSymbolicUInt64(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(int64_t x) {
|
||||
return McTest_IsSymbolicInt64(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(uint32_t x) {
|
||||
return McTest_IsSymbolicUInt(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(int32_t x) {
|
||||
return McTest_IsSymbolicInt(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(uint16_t x) {
|
||||
return McTest_IsSymbolicUShort(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(int16_t x) {
|
||||
return McTest_IsSymbolicShort(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(unsigned char x) {
|
||||
return McTest_IsSymbolicUChar(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(char x) {
|
||||
return McTest_IsSymbolicChar(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(float x) {
|
||||
return McTest_IsSymbolicFloat(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(double x) {
|
||||
return McTest_IsSymbolicDouble(x);
|
||||
}
|
||||
|
||||
inline static int IsSymbolic(void *x) {
|
||||
return McTest_IsSymbolicPtr(x);
|
||||
}
|
||||
|
||||
#if 199711L < __cplusplus
|
||||
|
||||
/* Returns a symbolic container (where it makes sense). Container entries
|
||||
* do not necessarily need to be contiguous. */
|
||||
template <typename ContainerT, typename... Args>
|
||||
inline static ContainerT Symbolic(Args&& ...args) {
|
||||
ContainerT cont(std::forward<Args...>(args)...);
|
||||
if (!cont.empty()) {
|
||||
for (auto &entry : cont) {
|
||||
auto entry_ptr = &entry;
|
||||
McTest_SymbolizeData(entry_ptr, &(entry_ptr[1]));
|
||||
}
|
||||
}
|
||||
return cont;
|
||||
}
|
||||
|
||||
#endif // 199711L < __cplusplus
|
||||
|
||||
// Returns a symbolic std::string of length `len`.
|
||||
inline static std::string Str(size_t len) {
|
||||
std::string str(len);
|
||||
if (len) {
|
||||
McTest_SymbolizeData(&(str.begin()), &(str.end()));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace mctest
|
||||
|
||||
#endif // INCLUDE_MCTEST_MCTEST_HPP_
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Trail of Bits, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <mctest/McTest.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
static uint32_t gPlaybookIndex = 0;
|
||||
static uint32_t gPlaybook[8192] = {};
|
||||
|
||||
void McTest_SymbolizeData(void *begin, void *end) {
|
||||
(void) begin;
|
||||
(void) end;
|
||||
}
|
||||
|
||||
/* Return a symbolic value of a given type. */
|
||||
int McTest_Bool(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t McTest_Size(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t McTest_UInt64(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t McTest_UInt(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int McTest_Assume(int expr) {
|
||||
assert(expr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int McTest_IsSymbolicUInt(uint32_t x) {
|
||||
(void) x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void McTest_DoneTestCase(void) {
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* McTest implements the `main` function so that test code can focus on tests */
|
||||
int main(void) {
|
||||
#if defined(__x86_64__) || defined(__i386__) || defined(_M_X86)
|
||||
asm("ud2; .asciz \"I'm McTest'in it\";");
|
||||
#else
|
||||
# error "Unsupported platform (for now)."
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif /* __cplusplus */
|
||||
Reference in New Issue
Block a user