Fix for "PTRSUB off of" errors

This commit is contained in:
caheckman 2020-07-12 14:54:43 -04:00
parent 2ea73a65a0
commit 4382d043f1
4 changed files with 42 additions and 24 deletions

View file

@ -2289,6 +2289,16 @@ int4 ActionSetCasts::apply(Funcdata &data)
if ((ct->getMetatype() != TYPE_PTR)||(ct->getPtrTo()->getSize() != AddrSpace::addressToByteInt(sz, ct->getWordSize())))
data.opUndoPtradd(op,true);
}
else if (opc == CPUI_PTRSUB) { // Check for PTRSUB that no longer fits pointer
if (!op->getIn(0)->getHigh()->getType()->isPtrsubMatching(op->getIn(1)->getOffset())) {
if (op->getIn(1)->getOffset() == 0) {
data.opRemoveInput(op, 1);
data.opSetOpcode(op, CPUI_COPY);
}
else
data.opSetOpcode(op, CPUI_INT_ADD);
}
}
for(int4 i=0;i<op->numInput();++i) // Do input casts first, as output may depend on input
count += castInput(op,i,data,castStrategy);
if (opc == CPUI_LOAD) {

View file

@ -6363,30 +6363,8 @@ int4 RulePtrsubUndo::applyOp(PcodeOp *op,Funcdata &data)
if (!data.isTypeRecoveryOn()) return 0;
Varnode *basevn = op->getIn(0);
TypePointer *ct = (TypePointer *)basevn->getType();
bool undo = false;
if (ct->getMetatype()!=TYPE_PTR)
undo = true;
else {
Datatype *basetype = ct->getPtrTo();
if (basetype->getMetatype()==TYPE_SPACEBASE) {
uintb newoff = AddrSpace::addressToByte(op->getIn(1)->getOffset(),ct->getWordSize());
basetype->getSubType(newoff,&newoff);
if (newoff != 0)
undo = true;
}
else {
int4 size = op->getIn(1)->getOffset();
int4 typesize = basetype->getSize();
if ((basetype->getMetatype()!=TYPE_ARRAY)&&(basetype->getMetatype()!=TYPE_STRUCT))
undo = true; // Not a pointer to a structured type
else if ((typesize <= AddrSpace::addressToByteInt(size,ct->getWordSize()))&&(typesize!=0))
undo = true;
}
}
if (!undo) return 0;
if (basevn->getType()->isPtrsubMatching(op->getIn(1)->getOffset()))
return 0;
data.opSetOpcode(op,CPUI_INT_ADD);
return 1;

View file

@ -316,6 +316,35 @@ void Datatype::saveXmlRef(ostream &s) const
saveXml(s);
}
/// A CPUI_PTRSUB must act on a pointer data-type where the given offset addresses a component.
/// Perform this check.
/// \param is the given offset
/// \return \b true if \b this is a suitable PTRSUB data-type
bool Datatype::isPtrsubMatching(uintb offset) const
{
if (metatype != TYPE_PTR)
return false;
Datatype *basetype = ((TypePointer *)this)->getPtrTo();
uint4 wordsize = ((TypePointer *)this)->getWordSize();
if (basetype->metatype==TYPE_SPACEBASE) {
uintb newoff = AddrSpace::addressToByte(offset,wordsize);
basetype->getSubType(newoff,&newoff);
if (newoff != 0)
return false;
}
else {
int4 size = offset;
int4 typesize = basetype->getSize();
if ((basetype->metatype != TYPE_ARRAY)&&(basetype->metatype != TYPE_STRUCT))
return false; // Not a pointer to a structured type
else if ((typesize <= AddrSpace::addressToByteInt(size,wordsize))&&(typesize!=0))
return false;
}
return true;
}
/// Restore the basic properties (name,size,id) of a data-type from an XML element
/// Properties are read from the attributes of the element
/// \param el is the XML element

View file

@ -126,6 +126,7 @@ public:
int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special
void saveXmlBasic(ostream &s) const; ///< Save basic data-type properties
void saveXmlRef(ostream &s) const; ///< Write an XML reference of \b this to stream
bool isPtrsubMatching(uintb offset) const; ///< Is this data-type suitable as input to a CPUI_PTRSUB op
};
/// \brief Specifies subfields of a structure or what a pointer points to