def test_simple_declarations(self): code = """ int foo(int (*)(void *, int[1])); int a, b = 1, c = 5 + 5; """ decs = translation_unit(preprocess(tokenize(source(code)))) int_type = IntegerType('') exp_decls = [ Declaration( 'foo', FunctionType(int_type, [AbstractDeclarator(PointerType(FunctionType( int_type, [ AbstractDeclarator(PointerType(VoidType(''), ''), ''), AbstractDeclarator(ArrayType(int_type, 1, ''), ''), ], '', ), ''), '')], ''), '', ), Declaration('a', int_type, ''), Definition('b', int_type, ConstantExpression(1, int_type, ''), '', None), Definition('c', int_type, ConstantExpression(10, int_type, ''), '', None) ] for got_dec, exp_dec in izip(decs, exp_decls): self.assertEqual(got_dec, exp_dec)
def test_var_arg_function(self): code = """ #include <stdarg.h> struct temp {int i; struct {int v[10]; char c;} s;}; int foo(int initial, ...) { va_list values; va_start(values, initial); int a = va_arg(values, int); char c = va_arg(values, char); double d = va_arg(values, double); struct temp s = va_arg(values, struct temp); int last = va_arg(values, int); int *ptr = va_arg(values, int *); return a == -1 && c == 'c'&& d == 12.5 && s.i == 1 && s.s.c == 'f' && last == 10 && ptr == 10; } int main() { struct temp s = {1, .s = {.c = 'f'}}; return foo(0, -1, 'c', 12.5, s, 10, (int *)10); } """ self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_memcpy(self): code = """ #include <string.h> #define TEST_SIZE {test_size} int main() {{ int guard_0 = 0; int *src[TEST_SIZE] = {{[0 ... TEST_SIZE - 1] = -1}}; int guard_1 = 0; int *dest[TEST_SIZE] = {{[0 ... TEST_SIZE - 1] = 1}}; int guard_2 = 0; if (memcpy(dest, src, sizeof(src)) != dest) return -1; int index = TEST_SIZE; while (index--) if (dest[index] != src[index]) return -1; return !(guard_0 || guard_1 || guard_2); }} """.format(test_size=TestString.test_size) self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_strcpy(self): code = """ #include <string.h> int main() { int guard_0 = 0; char src[19] = "this is a test ..."; int guard_1 = 0; char dest[19] = {[0 ... 18] = 'g'}; int guard_2 = 0; strcpy(dest, ""); if (dest[0] != '\0') return -1; if (strcpy(dest, src) != dest) return -1; size_t index = 0; while (index < sizeof(src)/sizeof(src[0])) if (src[index] != dest[index++]) return -1; return !(guard_0 || guard_1 || guard_2); } """ self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_exit_nested(self): code = """ #include <stdlib.h> int foo_2(int value) { exit(value); } void foo(int value) { if (value < 100) foo(value + 1); else foo_2(value); } int main() { foo(0); return 0; } """ self.evaluate(code) self.assert_base_element(ConstantExpression(100, LongType()))
def test_strcat(self): code = """ #include <string.h> int main() { int guard_0 = 0; char initial[12] = "hello"; int guard_1 = 0; char rest[7] = " there"; int guard_2 = 0; char result[12] = "hello there"; strcat(initial, ""); if (initial[0] != result[0]) return -1; if (strcat(initial, rest) != initial) return -1; size_t index = 0; while (index < sizeof(result)/sizeof(result[0])) if (initial[index] != result[index++]) return -1; return !(guard_0 || guard_1 || guard_2); } """ self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_strncat(self): code = """ #include <string.h> int main() { int guard_0 = 0; char initial[20] = "hello"; int guard_1 = 0; strncat(initial, NULL, 0); if (initial[0] != 'h') return -1; if (strncat(initial, " there", strlen(" there")) != initial) return -1; char result[12] = "hello there"; size_t index = 0; while (index < strlen("hello there")) if ("hello there"[index] != initial[index++]) return -index; return !(guard_0 || guard_1); } """ self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_strlen(self): code = """ #include <string.h> int main() { char temp[50] = "this is a test ..."; if (strlen("a") != 1) return -1; if (strlen("")) return -2; if (strlen(temp) != ((sizeof("this is a test ...")/sizeof('0')) - sizeof('\0'))) // subtract '\0' return -3; if (strlen("\0asdasd")) return -4; return 1; } """ self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType())) # self.assertEqual(int(self.mem[self.cpu.stack_pointer]), 1)
def test_switch_statement(self): source = """ { int a = 10, sum = 0; switch (10) { case 0: sum = -1; case 1: sum += 1; break; case 10: sum += 10; case 11: { sum += 1; case 15: sum += 1; } break; case 12: sum += 1; default: sum += 1; } a = sum; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(12, IntegerType()))
def test_malloc_simple(self): source = """ #include <stdlib.h> #define TEST_SIZE 10 int main() { void *heap_ptr = sbrk(0); unsigned char *value = malloc(sizeof(unsigned char) * TEST_SIZE); unsigned int index = TEST_SIZE; unsigned char *temp = value; while (index--) *temp++ = 1 - TEST_SIZE; index = TEST_SIZE; temp = value; while (index--) if (*temp++ != (unsigned char)(1 - TEST_SIZE)) return -2; free(value); if (heap_ptr != sbrk(0)) return -1; return 0; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def cast_exp(expr): if c_type(expr) == c_type(exp(expr)): return exp(expr) if isinstance(exp(expr), ConstantExpression) and not isinstance( c_type(exp(expr)), ArrayType): to_type = c_type(expr) expr = exp(expr) location = loc(expr) if isinstance(expr, EmptyExpression): return EmptyExpression(to_type, loc(expr)) if isinstance(to_type, IntegralType): return ConstantExpression(int(exp(expr)), to_type(location), location) if isinstance(to_type, FloatType): return ConstantExpression(float(exp(expr)), to_type(location), location) return expr
def test_bitwise_not(self): source = """ { int a = -10; a = ~a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(9, IntegerType()))
def test_plus(self): source = """ { int a = 10; a = +a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(10, IntegerType()))
def test_array_assignment(self): code = """ { char values[2]; values[1] = 127; } """ self.evaluate(code) self.assert_base_element(ConstantExpression(127, CharType()))
def test_true_for_loop(self): source = """ { int index; for (index = 0; index < 10; index += 1); } """ self.evaluate(source) self.assert_base_element(ConstantExpression(10, IntegerType()))
def test_compound_addition(self): code = """ { int a = 10, b = 1; a += b; } """ self.evaluate(code) self.assert_base_element(ConstantExpression(11, IntegerType()))
def test_malloc_complex(self): source = """ #include <stdlib.h> #include <string.h> #include <stdio.h> #define TEST_SIZE 20 #define MAX_BLOCK_SIZE 256 struct __block_type__ {int size; char value; unsigned char *address;}; void randomly_initialize_block(struct __block_type__ *block) { block->size = (rand() & (MAX_BLOCK_SIZE - 1)); block->value = (char)rand(); block->address = malloc(block->size * sizeof(unsigned char)); memset(block->address, block->value, block->size * sizeof(unsigned char)); } int main() { void *initial_heap_pointer = sbrk(0); // record initial heap pointer ... struct __block_type__ allocated_blocks[TEST_SIZE]; int test_size = TEST_SIZE; size_t total_allocation_size = 0; while (test_size--) // randomly initialize all the blocks ... { randomly_initialize_block(&allocated_blocks[test_size]); total_allocation_size += allocated_blocks[test_size].size; } test_size = 2 * TEST_SIZE; int index; while (test_size--) // randomly deallocate some of the blocks ... { index = rand() % TEST_SIZE; // randomly pick a block ... free(allocated_blocks[index].address); // deallocate its content ... randomly_initialize_block(&allocated_blocks[index]); // randomly re-initialize its content ... } test_size = TEST_SIZE; while (test_size--) { // check that free/malloc haven't corrupted any other blocks ... for (index = 0; index < allocated_blocks[test_size].size; index++) if (allocated_blocks[test_size].address[index] != allocated_blocks[test_size].value) return -1; free(allocated_blocks[test_size].address); // check was ok, so deallocate it ... } return sbrk(0) - initial_heap_pointer; // check that deallocating everything has reset the heap pointer... } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType())) # self.assertEqual(self.mem[self.cpu.stack_pointer], 0)
def test_increment(self): source = """ { int a = 10; int b = ++a; a = a - b; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_dereference(self): source = """ { int a = 10; int *b = &a; *b = 9; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(9, IntegerType()))
def test_false_while_loop(self): source = """ { int sum = 0; while (0) sum += 1; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_decrement(self): source = """ { int a = 10; int b = a--; a = b - a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(1, IntegerType()))
def inc_dec(value, expr, symbol_table): return symbol_table['__ expression __']( CompoundAssignmentExpression( exp(expr), TOKENS.PLUS_EQUAL, ConstantExpression( value, IntegerType(loc(expr), unsigned=unsigned(c_type(expr))), loc(expr)), c_type(expr)(loc(expr)), loc(expr)), symbol_table, )
def test_ternary(self): code = ''' { int b = 11; int foo = b ? b += 2 : (foo += 3); b = b - foo; } ''' self.evaluate(code) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_true_while_loop(self): source = """ { int sum = 0, index = 10; while (sum < index) sum += 1; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(10, IntegerType()))
def test_address_of(self): source = """ { int a = 10; int *b = &a; a = (unsigned long long)&a - (unsigned long long)b; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_if_statement(self): source = """ { int a = 10; if (1) a = 0; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_pointer_subtraction_zero(self): code = """ { unsigned int size = -1; struct foo {double a; int b[10];} *a = (void *)sizeof(struct foo); size = a - 1; } """ self.evaluate(code) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_global_initializer_and_postfix_increment(self): code = """ int values[2] = {0}; int main() { ++values[0]; return values[0]; } """ self.evaluate(code) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_function_pointer(self): source = """ int foo(int value){ return value + 1; } int main() { int (*foo_fp)(int) = &foo; return foo_fp(10); } """ self.evaluate(source) self.assert_base_element(ConstantExpression(11, IntegerType()))
def test_two_d_array(self): source = """ { int b; int a[5][3]; a[2][2] = 5; b = a[2][2]; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(5, IntegerType()))