mirror of
https://github.com/angr/angr
synced 2026-08-17 12:23:11 -04:00
SimConstantVariable: Fix overflows and value out of range errors. (#6738)
* SimConstantVariable: Fix overflows and value out of range errors. * Fix usages of SimConstantVariable. * Mask the value. * Fix negative values.
This commit is contained in:
parent
d38cc5a019
commit
61bac8ffd0
4 changed files with 47 additions and 9 deletions
|
|
@ -1156,9 +1156,11 @@ class DDG(Analysis):
|
|||
if not action.reg_deps and not action.tmp_deps:
|
||||
# moving a constant into the register
|
||||
# try to parse out the constant from statement
|
||||
const_variable = SimConstantVariable(size=1)
|
||||
if statement is not None and isinstance(statement.data, pyvex.IRExpr.Const):
|
||||
const_variable = SimConstantVariable(value=statement.data.con.value, size=statement.data.con.size)
|
||||
else:
|
||||
# use a default value of 0 if we cannot find the constant
|
||||
const_variable = SimConstantVariable(1, value=0)
|
||||
const_pv = ProgramVariable(const_variable, location, arch=self.project.arch)
|
||||
self._data_graph_add_edge(const_pv, pv)
|
||||
|
||||
|
|
@ -1229,7 +1231,7 @@ class DDG(Analysis):
|
|||
if not action.tmp_deps and not self._variables_per_statement and not ast:
|
||||
# read in a constant
|
||||
# try to parse out the constant from statement
|
||||
const_variable = SimConstantVariable(size=1)
|
||||
const_variable = SimConstantVariable(size=1, value=0) # default value if we can't find the constant
|
||||
if statement is not None:
|
||||
if isinstance(statement, pyvex.IRStmt.Dirty):
|
||||
l.warning("Dirty statements are not supported in DDG for now.")
|
||||
|
|
|
|||
|
|
@ -23,8 +23,9 @@ message TemporaryVariable {
|
|||
message ConstantVariable {
|
||||
VariableBase base = 1;
|
||||
uint32 size = 2;
|
||||
uint64 value = 3;
|
||||
uint64 value = 3; // the absolute value
|
||||
optional bytes long_value = 4; // for large constants over 64 bits
|
||||
bool is_negative = 5;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -116,9 +116,12 @@ class SimConstantVariable(SimVariable):
|
|||
|
||||
__slots__ = ["value"]
|
||||
|
||||
def __init__(self, size: int, ident=None, value=None, region=None):
|
||||
def __init__(self, size: int, *, value: int | float, region: int | None = None, ident=None):
|
||||
super().__init__(ident=ident, region=region, size=size)
|
||||
self.value = value
|
||||
is_negative = value < 0
|
||||
abs_value = -value if is_negative else value
|
||||
abs_value = abs_value & ((1 << (size * 8)) - 1) if isinstance(abs_value, int) else abs_value
|
||||
self.value = -abs_value if is_negative else abs_value
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.region}|const {self.value}>"
|
||||
|
|
@ -148,7 +151,7 @@ class SimConstantVariable(SimVariable):
|
|||
|
||||
@property
|
||||
def key(self) -> tuple[str | int | None, ...]:
|
||||
return ("const", self.value, self.size, self.ident)
|
||||
return "const", self.value, self.size, self.ident
|
||||
|
||||
@classmethod
|
||||
def _get_cmsg(cls):
|
||||
|
|
@ -158,17 +161,21 @@ class SimConstantVariable(SimVariable):
|
|||
obj = self._get_cmsg()
|
||||
self._set_base(obj)
|
||||
obj.size = self.size
|
||||
abs_value = self.value if self.value >= 0 else -self.value
|
||||
if self.bits > 64:
|
||||
assert isinstance(self.value, int)
|
||||
# TODO: Handle float
|
||||
obj.long_value = int.to_bytes(self.value, byteorder="little")
|
||||
num_bytes = (self.bits + 7) // 8
|
||||
obj.long_value = self.value.to_bytes(num_bytes, byteorder="little")
|
||||
else:
|
||||
obj.value = self.value
|
||||
obj.value = abs_value
|
||||
obj.is_negative = self.value is not None and self.value < 0
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def parse_from_cmessage(cls, cmsg, **kwargs):
|
||||
value = int.from_bytes(cmsg.long_value, byteorder="little") if cmsg.size > 64 else cmsg.value
|
||||
value = -value if cmsg.is_negative else value
|
||||
obj = cls(cmsg.size, value=value)
|
||||
obj._from_base(cmsg)
|
||||
return obj
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import tempfile
|
|||
import unittest
|
||||
|
||||
import angr
|
||||
from angr.sim_variable import SimStackVariable
|
||||
from angr.sim_variable import SimConstantVariable, SimStackVariable
|
||||
from tests.common import bin_location
|
||||
|
||||
test_location = os.path.join(bin_location, "tests")
|
||||
|
|
@ -135,6 +135,34 @@ class TestSerialization(unittest.TestCase):
|
|||
cmsg = v1.serialize_to_cmessage()
|
||||
assert cmsg.offset == 0x7FFF_DEAD
|
||||
|
||||
def test_simconstantvariable_value_overflow(self):
|
||||
v0 = SimConstantVariable(16, value=0x8000_0000_0000_0000_0000_0001, ident="c_0")
|
||||
cmsg = v0.serialize_to_cmessage()
|
||||
assert cmsg.size == 16
|
||||
assert cmsg.long_value == (0x8000_0000_0000_0000_0000_0001).to_bytes(16, byteorder="little")
|
||||
assert cmsg.is_negative is False
|
||||
|
||||
def test_simconstantvariable_value_out_of_range(self):
|
||||
v1 = SimConstantVariable(8, value=-0x8000_0000_0000_0000, ident="c_1")
|
||||
cmsg = v1.serialize_to_cmessage()
|
||||
assert cmsg.size == 8
|
||||
assert cmsg.value == 0x8000_0000_0000_0000
|
||||
assert cmsg.is_negative is True
|
||||
|
||||
def test_simconstantvariable_value_too_long(self):
|
||||
v2 = SimConstantVariable(8, value=0x1_FFFF_FFFF_FFFF_FFF0, ident="c_2")
|
||||
cmsg = v2.serialize_to_cmessage()
|
||||
assert cmsg.size == 8
|
||||
assert cmsg.value == 0xFFFF_FFFF_FFFF_FFF0
|
||||
assert cmsg.is_negative is False
|
||||
|
||||
def test_simconstantvariable_negative_value(self):
|
||||
v1 = SimConstantVariable(8, value=-1, ident="c_1")
|
||||
cmsg = v1.serialize_to_cmessage()
|
||||
assert cmsg.size == 8
|
||||
assert cmsg.value == 1
|
||||
assert cmsg.is_negative is True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue