GP-2566 Check for output varnode on CALL ops

This commit is contained in:
caheckman 2022-09-16 19:18:41 -04:00
parent 742e69eb31
commit 54525fcbf8

View file

@ -1481,15 +1481,29 @@ void ActionFuncLink::funcLinkInput(FuncCallSpecs *fc,Funcdata &data)
void ActionFuncLink::funcLinkOutput(FuncCallSpecs *fc,Funcdata &data)
{
PcodeOp *callop = fc->getOp();
if (callop->getOut() != (Varnode *)0) {
// CALL ops are expected to have no output, but its possible an override has produced one
if (callop->getOut()->getSpace()->getType() == IPTR_INTERNAL) {
// Removing a varnode in the unique space will likely produce an input varnode in the unique space
ostringstream s;
s << "CALL op at ";
callop->getAddr().printRaw(s);
s << " has an unexpected output varnode";
throw LowlevelError(s.str());
}
// Otherwise just remove the Varnode and assume return recovery will reintroduce it if necessary
data.opUnsetOutput(callop);
}
if (fc->isOutputLocked()) {
ProtoParameter *outparam = fc->getOutput();
Datatype *outtype = outparam->getType();
if (outtype->getMetatype() != TYPE_VOID) {
int4 sz = outparam->getSize();
if (sz == 1 && outtype->getMetatype() == TYPE_BOOL)
data.opMarkCalculatedBool(fc->getOp());
data.opMarkCalculatedBool(callop);
Address addr = outparam->getAddress();
data.newVarnodeOut(sz,addr,fc->getOp());
data.newVarnodeOut(sz,addr,callop);
VarnodeData vdata;
OpCode res = fc->assumedOutputExtension(addr,sz,vdata);
if (res == CPUI_PIECE) { // Pick an extension based on type
@ -1499,7 +1513,6 @@ void ActionFuncLink::funcLinkOutput(FuncCallSpecs *fc,Funcdata &data)
res = CPUI_INT_ZEXT;
}
if (res != CPUI_COPY) { // We assume the (smallsize) output is extended to a full register
PcodeOp *callop = fc->getOp();
// Create the extension operation to eliminate artifact
PcodeOp *op = data.newOp(1,callop->getAddr());
data.newVarnodeOut(vdata.size,vdata.getAddr(),op);