Commit 759e3bd7 authored by Sergio Costas's avatar Sergio Costas

Now doesn't allow freed global variables at the end of a function

parent 4c63d373
......@@ -1302,6 +1302,7 @@ class crust(object):
if self.verbose:
print(" " * total_len + "\r", end = "")
def _process_block(self, function_name, tree, thread_status):
thread_status["debug_level"] = 0
......@@ -1336,6 +1337,19 @@ class crust(object):
print("\n\n")
def _check_global_vars(self, thread_status, line):
# check that there are no global vars with the same block,
# neither global vars in FREED state
for variable in thread_status["variables"][-1]:
data = thread_status["variables"][-1][variable]
if not data["crust"]:
continue
if not data["global"]:
continue
if data["value"] == self.VALUE_FREED:
self._add_error(thread_status, self.MSG_ERROR, "At exit point in line {:d}, global variable '{:s}' points to a block freed at line {:d}.", line, variable, data["init_line"])
def _check_blocks_in_use(self, thread_status, vars, line):
# check if there are memory blocks in use
for variable in vars:
......@@ -1355,9 +1369,9 @@ class crust(object):
if not found:
init_line = data["init_line"]
if init_line is None:
self._add_error(thread_status, self.MSG_ERROR, "Memory block '{:s}' is still in use at exit point at line {:d}", variable, line)
self._add_error(thread_status, self.MSG_ERROR, "Memory block '{:s}' is still in use at exit point in line {:d}", variable, line)
else:
self._add_error(thread_status, self.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", variable, init_line, line)
self._add_error(thread_status, self.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", variable, init_line, line)
def _process_block2(self, tree, thread_status):
......@@ -1396,6 +1410,7 @@ class crust(object):
if node.type == "END_BLOCK":
# check if there are blocks in use at the end of the block
self._check_blocks_in_use(thread_status, thread_status["variables"][0], node.line)
self._check_global_vars(thread_status, node.line)
# remove the last block of variables
thread_status["variables"] = thread_status["variables"][1:]
return self._check_return_block(tree[1:], thread_status)
......@@ -1482,6 +1497,7 @@ class crust(object):
while(len(tmp_status["variables"]) > 1):
self._check_blocks_in_use(tmp_status, tmp_status["variables"][0], node.line)
tmp_status["variables"] = tmp_status["variables"][1:]
self._check_global_vars(thread_status, node.line)
if tmp_status["returned_something"] == True:
if (thread["type"] == self.TYPE_CRUST) and (tmp_status["return_is_crust"] == False):
......
......@@ -300,16 +300,16 @@ class Test(unittest.TestCase):
self._all_fine_test("unitest/test62.c")
def test063BlockInUseAtEnd(self):
self._generic_test("unitest/test63.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 5, 8) ])
self._generic_test("unitest/test63.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param", 5, 8) ])
def test064BlockInUseAtEnd2(self):
self._generic_test("unitest/test64.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 5, 7) ])
self._generic_test("unitest/test64.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param", 5, 7) ])
def test065BlockInUseWithReturn(self):
self._generic_test("unitest/test65.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "var2", 8, 9) ])
self._generic_test("unitest/test65.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "var2", 8, 9) ])
def test066BlockInUseWithReturn2(self):
self._generic_test("unitest/test66.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "var2", 9, 12) ])
self._generic_test("unitest/test66.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "var2", 9, 12) ])
def test067BlockInUseWithReturn3(self):
self._all_fine_test("unitest/test67.c")
......@@ -613,7 +613,7 @@ class Test(unittest.TestCase):
self._check_var_status(lib, "alias2", crust.crust.VALUE_NOT_NULL, 3)
def test133GotoJumpsOverAll(self):
self._generic_test("unitest/test133.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 12, 21) ])
self._generic_test("unitest/test133.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param", 12, 21) ])
def test134ReturnCrustExpectCrust(self):
self._all_fine_test("unitest/test134.c")
......@@ -628,13 +628,13 @@ class Test(unittest.TestCase):
self._generic_test("unitest/test137.c", [ (crust.crust.MSG_ERROR, "Return statement at line {:d} is returning a non-crust value, but is must return a crust one", 7) ])
def test138OddBreakInFor(self):
self._generic_test("unitest/test138.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param1", 7, 15) ])
self._generic_test("unitest/test138.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param1", 7, 15) ])
def test139BreakInNestedFor(self):
self._generic_test("unitest/test139.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param2", 7, 22), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param1", 7, 22) ])
self._generic_test("unitest/test139.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param2", 7, 22), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param1", 7, 22) ])
def test140Switch1(self):
self._generic_test("unitest/test140.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param1", 7, 27), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param2", 7, 27), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param3", 7, 27) ])
self._generic_test("unitest/test140.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param1", 7, 27), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param2", 7, 27), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param3", 7, 27) ])
def test141Switch2(self):
self._generic_test("unitest/test141.c", [ (crust.crust.MSG_ERROR, "Argument {:d} when calling function '{:s}' at line {:d} was freed at line {:d}", 1, "function", 25, 13), (crust.crust.MSG_ERROR, "Argument {:d} when calling function '{:s}' at line {:d} was freed at line {:d}", 1, "function", 25, 16), (crust.crust.MSG_ERROR, "Argument {:d} when calling function '{:s}' at line {:d} was freed at line {:d}", 1, "function", 25, 19), (crust.crust.MSG_ERROR, "Argument {:d} when calling function '{:s}' at line {:d} was freed at line {:d}", 1, "function", 25, 22) ])
......@@ -661,13 +661,13 @@ class Test(unittest.TestCase):
self._all_fine_test("unitest/test148.c")
def test149TestWhileContinue(self):
self._generic_test("unitest/test149.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 12, 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
self._generic_test("unitest/test149.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param", 12, 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
def test150TestDoWhileContinue(self):
self._generic_test("unitest/test150.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 12, 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
self._generic_test("unitest/test150.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param", 12, 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
def test151TestForContinue(self):
self._generic_test("unitest/test151.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param", 12, 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
self._generic_test("unitest/test151.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param", 12, 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
def test152TestWhileContinue2(self):
self._generic_test("unitest/test152.c", [ (crust.crust.MSG_ERROR, "Argument {:d} when calling function '{:s}' at line {:d} isn't initialized", 1, "function", 16), (crust.crust.MSG_ERROR, "Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param", 12, 12) ])
......@@ -694,10 +694,10 @@ class Test(unittest.TestCase):
self._generic_test("unitest/test159.c", [ (crust.crust.MSG_ERROR, "Assigning the non-borrowed block '{:s}' to the borrowed variable '{:s}' at line {:d}", "param2", "var2", 12), (crust.crust.MSG_ERROR, "Assigning a value to the borrowed variable '{:s}' at line {:d}", "var4", 14) ])
def test160AssignRetBorrowToNonBorrow(self):
self._generic_test("unitest/test160.c", [ (crust.crust.MSG_ERROR, "Assigning the borrowed result value of function '{:s}' to the non-borrowed variable '{:s}' at line {:d}", "function1", "var1", 11), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "var1", 11, 12) ])
self._generic_test("unitest/test160.c", [ (crust.crust.MSG_ERROR, "Assigning the borrowed result value of function '{:s}' to the non-borrowed variable '{:s}' at line {:d}", "function1", "var1", 11), (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "var1", 11, 12) ])
def test161AssignRetNonBorrowToNonBorrow(self):
self._generic_test("unitest/test161.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "var1", 11, 12) ])
self._generic_test("unitest/test161.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "var1", 11, 12) ])
def test162AssignRetBorrowToBorrow(self):
self._all_fine_test("unitest/test162.c")
......@@ -763,7 +763,7 @@ class Test(unittest.TestCase):
self._all_fine_test("unitest/test182.c")
def test183CheckIfWithUninitializedVariable(self):
self._generic_test("unitest/test183.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "param3", 5, 9) ])
self._generic_test("unitest/test183.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "param3", 5, 9) ])
def test184CheckAssignToSeveralGlobalVars(self):
lib = self._all_fine_test("unitest/test184.c")
......@@ -776,7 +776,7 @@ class Test(unittest.TestCase):
self._check_block_id_is_the_same(lib, "param1", "global_var2")
def test186CheckIfWithUninitializedVariable(self):
self._generic_test("unitest/test186.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point at line {:d}", "data", 7, 11) ])
self._generic_test("unitest/test186.c", [ (crust.crust.MSG_ERROR, "Memory block '{:s}', initialized at line {:d}, is still in use at exit point in line {:d}", "data", 7, 11) ])
def test187GlobalVarsAlwaysNotNull(self):
self._all_fine_test("unitest/test187.c")
......@@ -797,6 +797,11 @@ class Test(unittest.TestCase):
self._check_block_id_is_the_same(lib, "arg1", "var1", 0)
self._check_block_id_is_not_same(lib, "arg1", "var1", 1)
def test192GlobalVariableFreedAtExit(self):
self._generic_test("unitest/test192.c", [ (crust.crust.MSG_ERROR, "At exit point in line {:d}, global variable '{:s}' points to a block freed at line {:d}.", 16, "var1", 14) ])
if __name__ == '__main__':
try:
os.remove("error_list.txt")
......
typedef __crust_t__ unsigned char *crust_t;
typedef void (*test)(void);
crust_t var1;
void function(crust_t);
void main(crust_t __crust_not_null__ arg1) {
if (var1 == NULL) {
var1 = arg1;
}
function(arg1);
// ERROR: there is a global variable with FREED status at exit
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment