Commit 8f78aa9e authored by Sergio Costas's avatar Sergio Costas

Now doesn't fail when comparing a freed pointer

parent 10f87b45
......@@ -421,7 +421,7 @@ class crust(object):
return self.CONDITION_FALSE_TRUE
def _check_can_be_used(self, thread_status, variable, line_number):
def _check_can_be_used(self, thread_status, variable, line_number, comparison):
if (variable.type != "IDENTIFIER"):
return
varname = self._find_variable(thread_status, variable.name, line_number)
......@@ -430,7 +430,7 @@ class crust(object):
if varname["value"] == crust.VALUE_UNINITIALIZED:
self._add_error(thread_status, self.MSG_ERROR, "Using uninitialized variable '{:s}' at line {:d}", variable.name, line_number)
return
if (varname["value"] == crust.VALUE_FREED) or (varname["value"] == crust.VALUE_FREED_OR_NULL):
if (not comparison) and ((varname["value"] == crust.VALUE_FREED) or (varname["value"] == crust.VALUE_FREED_OR_NULL)):
self._add_error(thread_status, self.MSG_ERROR, "Using variable '{:s}' at line {:d}, after being freed at line {:d}", variable.name, line_number, varname["init_line"])
return
......@@ -528,17 +528,23 @@ class crust(object):
if self._check_statement_is_crust(statement, vardata):
valuetype = self.TYPE_CRUST
pure = True
if is_conditional:
self._check_can_be_used(thread_status, statement, statement.line)
if (valuedata == self.VALUE_NOT_NULL_OR_NULL) and is_conditional:
var1 = self._copy_status(thread_status)
var2 = thread_status
self._set_var_value(var1, vardata["name"], crust.VALUE_NOT_NULL, 0, True)
self._set_var_value(var2, vardata["name"], crust.VALUE_NULL, 0, True)
return [ {"thread_status":var1, "value":self.VALUE_NOT_NULL, "type":valuetype, "condition":self.CONDITION_TRUE, "node":statement, "pure": True}, {"thread_status":var2, "value":self.VALUE_NULL, "type":valuetype, "condition":self.CONDITION_FALSE, "node":statement, "pure": True}]
else:
valuetype = self.TYPE_NO_CRUST
pure = True
if is_conditional:
self._check_can_be_used(thread_status, statement, statement.line, True)
if (valuedata == self.VALUE_NOT_NULL_OR_NULL) and is_conditional:
var1 = self._copy_status(thread_status)
var2 = thread_status
self._set_var_value(var1, vardata["name"], crust.VALUE_NOT_NULL, 0, True)
self._set_var_value(var2, vardata["name"], crust.VALUE_NULL, 0, True)
return [ {"thread_status":var1, "value":self.VALUE_NOT_NULL, "type":valuetype, "condition":self.CONDITION_TRUE, "node":statement, "pure": True}, {"thread_status":var2, "value":self.VALUE_NULL, "type":valuetype, "condition":self.CONDITION_FALSE, "node":statement, "pure": True}]
if (valuedata == self.VALUE_FREED_OR_NULL) and is_conditional:
var1 = self._copy_status(thread_status)
var2 = thread_status
self._set_var_value(var1, vardata["name"], crust.VALUE_FREED, 0, True)
self._set_var_value(var2, vardata["name"], crust.VALUE_NULL, 0, True)
return [ {"thread_status":var1, "value":self.VALUE_FREED, "type":valuetype, "condition":self.CONDITION_TRUE, "node":statement, "pure": True}, {"thread_status":var2, "value":self.VALUE_NULL, "type":valuetype, "condition":self.CONDITION_FALSE, "node":statement, "pure": True}]
return [ {"thread_status":thread_status, "value":valuedata, "type":valuetype, "condition":self._status_to_condition(valuedata), "node":statement, "pure": pure} ]
if statement.type == "TYPECAST":
......@@ -688,7 +694,7 @@ class crust(object):
#if old_block is None:
# print("Es none {:d} {:s}".format(statement.line, str(orig_data)))
# only check and modify if the origin variable IS really a crust one, and is being managed as a crust one
self._check_can_be_used(orig_eval["thread_status"], orig_var, statement.line)
self._check_can_be_used(orig_eval["thread_status"], orig_var, statement.line, False)
if (orig_eval["pure"] and (not dest_data["alias"]) and (not dest_data["global"])) or (dest_data["alias"] and (not dest_eval["pure"])) or (dest_data["global"] and (not dest_eval["pure"])):
self._free_block(orig_eval["thread_status"], orig_var.name, statement.line)
......@@ -885,7 +891,6 @@ class crust(object):
if (statement.type == "EQ_OP") or (statement.type == "NE_OP"):
# this block manages the cases different to CRUST_VARIABLE == NULL and CRUST_VARIABLE != NULL
self._check_is_freed(thread_status, statement.child1[0])
self._check_is_freed(thread_status, statement.child2[0])
retvals = []
......@@ -909,9 +914,9 @@ class crust(object):
else:
variables = thread2["thread_status"]
var_used = True
if (thread1["value"] == self.VALUE_NULL) and (thread2["value"] == self.VALUE_NULL):
if (thread1["condition"] == self.CONDITION_FALSE) and (thread2["condition"] == self.CONDITION_FALSE):
retvals.append( {"thread_status":variables, "value":sts1, "type":self.TYPE_NO_CRUST, "condition":cnd1, "node":None, "pure": True} )
elif (((thread1["value"] == self.VALUE_NULL) and (thread2["value"] == self.VALUE_NOT_NULL)) or
elif (((thread1["condition"] == self.CONDITION_FALSE) and (thread2["condition"] == self.CONDITION_TRUE)) or
((thread1["value"] == self.VALUE_NOT_NULL) and (thread2["value"] == self.VALUE_NULL))):
retvals.append( {"thread_status":variables, "value":sts2, "type":self.TYPE_NO_CRUST, "condition":cnd2, "node":None, "pure": True} )
else:
......
......@@ -987,11 +987,14 @@ class Test(unittest.TestCase):
self._generic_test("unitest/test237.c", [ (crust.crust.MSG_ERROR, "Using uninitialized variable '{:s}' at line {:d}", "p", 7) ])
def test238CompareWithCrustPointerAloneFreed(self):
self._generic_test("unitest/test238.c", [ (crust.crust.MSG_ERROR, "Using variable '{:s}' at line {:d}, after being freed at line {:d}", "p", 9, 7) ])
self._all_fine_test("unitest/test238.c")
def test239NullCrustPointerIsNotFreed(self):
self._all_fine_test("unitest/test239.c")
def test238CompareWithCrustPointerAloneFreed2(self):
self._all_fine_test("unitest/test240.c")
if __name__ == '__main__':
try:
os.remove("error_list.txt")
......
......@@ -4,9 +4,11 @@ void function(crust_t);
void main(crust_t p) {
// Here, p in in NOT_NULL_OR_NULL state
function(p);
// Now, p is in FREED_OR_NULL state
if (!p) { // ERROR; p has already been freed
if (!p) { // NO ERROR, because we are just comparing
p = NULL;
}
}
typedef __crust__ unsigned char *crust_t;
void function(crust_t);
void main() {
crust_t p = NULL;
function(p);
if (!p) { // NO ERROR; p is NULL
p = NULL;
}
}
typedef __crust__ unsigned char *crust_t;
void function(crust_t);
void main(crust_t __crust_not_null__ p) {
// Here, p in in NOT_NULL state
function(p);
// Now, p is in FREED state
if (!p) { // NO ERROR, because we are just comparing
p = NULL;
}
}
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