mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-5869 Fix for some out of bounds array indices and shift amounts
This commit is contained in:
parent
7426d4b685
commit
943ccd322d
17 changed files with 98 additions and 50 deletions
|
@ -7,7 +7,7 @@ decomp_dbg
|
||||||
decomp_opt
|
decomp_opt
|
||||||
ghidra_dbg
|
ghidra_dbg
|
||||||
ghidra_opt
|
ghidra_opt
|
||||||
ghidra_test_dbg
|
decomp_test_dbg
|
||||||
sleigh_dbg
|
sleigh_dbg
|
||||||
com_dbg
|
com_dbg
|
||||||
com_opt
|
com_opt
|
||||||
|
|
|
@ -99,7 +99,7 @@ SPECIAL=consolemain sleighexample test
|
||||||
# Any additional modules for the command line decompiler
|
# Any additional modules for the command line decompiler
|
||||||
EXTRA= $(filter-out $(CORE) $(DECCORE) $(SLEIGH) $(GHIDRA) $(SLACOMP) $(SPECIAL),$(ALL_NAMES))
|
EXTRA= $(filter-out $(CORE) $(DECCORE) $(SLEIGH) $(GHIDRA) $(SLACOMP) $(SPECIAL),$(ALL_NAMES))
|
||||||
|
|
||||||
EXECS=decomp_dbg decomp_opt ghidra_test_dbg ghidra_dbg ghidra_opt sleigh_dbg sleigh_opt libdecomp_dbg.a libdecomp.a
|
EXECS=decomp_dbg decomp_opt decomp_test_dbg ghidra_dbg ghidra_opt sleigh_dbg sleigh_opt libdecomp_dbg.a libdecomp.a
|
||||||
|
|
||||||
# Possible conditional compilation flags
|
# Possible conditional compilation flags
|
||||||
# __TERMINAL__ # Turn on terminal support for console mode
|
# __TERMINAL__ # Turn on terminal support for console mode
|
||||||
|
@ -191,7 +191,7 @@ endif
|
||||||
ifeq ($(MAKECMDGOALS),decomp_opt)
|
ifeq ($(MAKECMDGOALS),decomp_opt)
|
||||||
DEPNAMES=com_opt/depend
|
DEPNAMES=com_opt/depend
|
||||||
endif
|
endif
|
||||||
ifneq (,$(filter $(MAKECMDGOALS),ghidra_test_dbg test))
|
ifneq (,$(filter $(MAKECMDGOALS),decomp_test_dbg test))
|
||||||
DEPNAMES=test_dbg/depend
|
DEPNAMES=test_dbg/depend
|
||||||
endif
|
endif
|
||||||
ifeq ($(MAKECMDGOALS),reallyclean)
|
ifeq ($(MAKECMDGOALS),reallyclean)
|
||||||
|
@ -253,11 +253,12 @@ decomp_dbg: $(COMMANDLINE_DBG_OBJS)
|
||||||
decomp_opt: $(COMMANDLINE_OPT_OBJS)
|
decomp_opt: $(COMMANDLINE_OPT_OBJS)
|
||||||
$(CXX) $(OPT_CXXFLAGS) $(ARCH_TYPE) -o decomp_opt $(COMMANDLINE_OPT_OBJS) $(BFDLIB) $(LNK)
|
$(CXX) $(OPT_CXXFLAGS) $(ARCH_TYPE) -o decomp_opt $(COMMANDLINE_OPT_OBJS) $(BFDLIB) $(LNK)
|
||||||
|
|
||||||
ghidra_test_dbg: $(TEST_DEBUG_OBJS)
|
#decomp_test_dbg: DBG_CXXFLAGS += -D_GLIBCXX_ASSERTIONS -fsanitize=address,undefined
|
||||||
$(CXX) $(DBG_CXXFLAGS) $(ARCH_TYPE) -o ghidra_test_dbg $(TEST_DEBUG_OBJS) $(BFDLIB) $(LNK)
|
decomp_test_dbg: $(TEST_DEBUG_OBJS)
|
||||||
|
$(CXX) $(DBG_CXXFLAGS) $(ARCH_TYPE) -o decomp_test_dbg $(TEST_DEBUG_OBJS) $(BFDLIB) $(LNK)
|
||||||
|
|
||||||
test: ghidra_test_dbg
|
test: decomp_test_dbg
|
||||||
./ghidra_test_dbg
|
./decomp_test_dbg
|
||||||
|
|
||||||
ghidra_dbg: $(GHIDRA_DBG_OBJS)
|
ghidra_dbg: $(GHIDRA_DBG_OBJS)
|
||||||
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_dbg $(GHIDRA_DBG_OBJS)
|
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_dbg $(GHIDRA_DBG_OBJS)
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -666,6 +666,8 @@ uintb uintb_negate(uintb in,int4 size)
|
||||||
uintb sign_extend(uintb in,int4 sizein,int4 sizeout)
|
uintb sign_extend(uintb in,int4 sizein,int4 sizeout)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
sizein = (sizein < sizeof(uintb)) ? sizein : sizeof(uintb);
|
||||||
|
sizeout = (sizeout < sizeof(uintb)) ? sizeout : sizeof(uintb);
|
||||||
intb sval = in;
|
intb sval = in;
|
||||||
sval <<= (sizeof(intb) - sizein) * 8;
|
sval <<= (sizeof(intb) - sizein) * 8;
|
||||||
uintb res = (uintb)(sval >> (sizeout - sizein) * 8);
|
uintb res = (uintb)(sval >> (sizeout - sizein) * 8);
|
||||||
|
|
|
@ -558,7 +558,7 @@ inline intb zero_extend(intb val,int4 bit)
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 sa = sizeof(intb)*8 - (bit+1);
|
int4 sa = sizeof(intb)*8 - (bit+1);
|
||||||
return (intb)((uintb)(val << sa) >> sa);
|
return (intb)(((uintb)val << sa) >> sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool signbit_negative(uintb val,int4 size); ///< Return true if the sign-bit is set
|
extern bool signbit_negative(uintb val,int4 size); ///< Return true if the sign-bit is set
|
||||||
|
|
|
@ -2724,8 +2724,9 @@ int4 ActionSetCasts::apply(Funcdata &data)
|
||||||
if (opc == CPUI_CAST) continue;
|
if (opc == CPUI_CAST) continue;
|
||||||
if (opc == CPUI_PTRADD) { // Check for PTRADD that no longer fits its pointer
|
if (opc == CPUI_PTRADD) { // Check for PTRADD that no longer fits its pointer
|
||||||
int4 sz = (int4)op->getIn(2)->getOffset();
|
int4 sz = (int4)op->getIn(2)->getOffset();
|
||||||
TypePointer *ct = (TypePointer *)op->getIn(0)->getHighTypeReadFacing(op);
|
Datatype *ct = op->getIn(0)->getHighTypeReadFacing(op);
|
||||||
if ((ct->getMetatype() != TYPE_PTR)||(ct->getPtrTo()->getAlignSize() != AddrSpace::addressToByteInt(sz, ct->getWordSize())))
|
if (ct->getMetatype() != TYPE_PTR ||
|
||||||
|
((TypePointer *)ct)->getPtrTo()->getAlignSize() != AddrSpace::addressToByteInt(sz, ((TypePointer *)ct)->getWordSize()))
|
||||||
data.opUndoPtradd(op,true);
|
data.opUndoPtradd(op,true);
|
||||||
}
|
}
|
||||||
else if (opc == CPUI_PTRSUB) { // Check for PTRSUB that no longer fits pointer
|
else if (opc == CPUI_PTRSUB) { // Check for PTRSUB that no longer fits pointer
|
||||||
|
|
|
@ -2901,7 +2901,6 @@ void ProtoModelMerged::decode(Decoder &decoder)
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
((ParamListMerged *)input)->finalize();
|
((ParamListMerged *)input)->finalize();
|
||||||
((ParamListMerged *)output)->finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParameterBasic::setTypeLock(bool val)
|
void ParameterBasic::setTypeLock(bool val)
|
||||||
|
|
|
@ -610,11 +610,17 @@ void Funcdata::setHighLevel(void)
|
||||||
/// Properties like boolean flags and \e consume bits are copied as appropriate.
|
/// Properties like boolean flags and \e consume bits are copied as appropriate.
|
||||||
/// \param vn is the existing Varnode
|
/// \param vn is the existing Varnode
|
||||||
/// \param newVn is the new Varnode that has its properties set
|
/// \param newVn is the new Varnode that has its properties set
|
||||||
/// \param lsbOffset is the significance offset of the new Varnode within the exising
|
/// \param lsbOffset is the significance offset of the new Varnode within the existing Varnode
|
||||||
void Funcdata::transferVarnodeProperties(Varnode *vn,Varnode *newVn,int4 lsbOffset)
|
void Funcdata::transferVarnodeProperties(Varnode *vn,Varnode *newVn,int4 lsbOffset)
|
||||||
|
|
||||||
{
|
{
|
||||||
uintb newConsume = (vn->getConsume() >> 8*lsbOffset) & calc_mask(newVn->getSize());
|
uintb newConsume = ~((uintb)0); // Make sure any bits shifted in above the precision of Varnode::consume are set
|
||||||
|
if (lsbOffset < sizeof(uintb)) {
|
||||||
|
uintb fillBits = 0;
|
||||||
|
if (lsbOffset != 0)
|
||||||
|
fillBits = newConsume << 8*(sizeof(uintb) - lsbOffset);
|
||||||
|
newConsume = ((vn->getConsume() >> 8*lsbOffset) | fillBits) & calc_mask(newVn->getSize());
|
||||||
|
}
|
||||||
|
|
||||||
uint4 vnFlags = vn->getFlags() & (Varnode::directwrite|Varnode::addrforce);
|
uint4 vnFlags = vn->getFlags() & (Varnode::directwrite|Varnode::addrforce);
|
||||||
|
|
||||||
|
|
|
@ -1739,15 +1739,16 @@ void Heritage::splitByRefinement(Varnode *vn,const Address &addr,const vector<in
|
||||||
uint4 diff = (uint4)spc->wrapOffset(curaddr.getOffset() - addr.getOffset());
|
uint4 diff = (uint4)spc->wrapOffset(curaddr.getOffset() - addr.getOffset());
|
||||||
int4 cutsz = refine[diff];
|
int4 cutsz = refine[diff];
|
||||||
if (sz <= cutsz) return; // Already refined
|
if (sz <= cutsz) return; // Already refined
|
||||||
|
split.push_back(fd->newVarnode(cutsz,curaddr));
|
||||||
|
sz -= cutsz;
|
||||||
while(sz > 0) {
|
while(sz > 0) {
|
||||||
Varnode *vn2 = fd->newVarnode(cutsz,curaddr);
|
|
||||||
split.push_back(vn2);
|
|
||||||
curaddr = curaddr + cutsz;
|
curaddr = curaddr + cutsz;
|
||||||
sz -= cutsz;
|
|
||||||
diff = (uint4)spc->wrapOffset(curaddr.getOffset() - addr.getOffset());
|
diff = (uint4)spc->wrapOffset(curaddr.getOffset() - addr.getOffset());
|
||||||
cutsz = refine[diff];
|
cutsz = refine[diff];
|
||||||
if (cutsz > sz)
|
if (cutsz > sz)
|
||||||
cutsz = sz; // Final piece
|
cutsz = sz; // Final piece
|
||||||
|
split.push_back(fd->newVarnode(cutsz,curaddr));
|
||||||
|
sz -= cutsz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -721,8 +721,8 @@ Varnode *GuardRecord::quasiCopy(Varnode *vn,int4 &bitsPreserved)
|
||||||
{
|
{
|
||||||
bitsPreserved = mostsigbit_set(vn->getNZMask()) + 1;
|
bitsPreserved = mostsigbit_set(vn->getNZMask()) + 1;
|
||||||
if (bitsPreserved == 0) return vn;
|
if (bitsPreserved == 0) return vn;
|
||||||
uintb mask = 1;
|
uintb mask = 1 << 1;
|
||||||
mask <<= bitsPreserved;
|
mask <<= (bitsPreserved - 1);
|
||||||
mask -= 1;
|
mask -= 1;
|
||||||
PcodeOp *op = vn->getDef();
|
PcodeOp *op = vn->getDef();
|
||||||
Varnode *constVn;
|
Varnode *constVn;
|
||||||
|
|
|
@ -665,8 +665,9 @@ uintb PcodeOp::getNZMaskLocal(bool cliploop) const
|
||||||
resmask &= fullmask;
|
resmask &= fullmask;
|
||||||
break;
|
break;
|
||||||
case CPUI_PIECE:
|
case CPUI_PIECE:
|
||||||
|
sa = getIn(1)->getSize();
|
||||||
resmask = getIn(0)->getNZMask();
|
resmask = getIn(0)->getNZMask();
|
||||||
resmask <<= 8*getIn(1)->getSize();
|
resmask = (sa < sizeof(uintb)) ? resmask << 8*sa : 0;
|
||||||
resmask |= getIn(1)->getNZMask();
|
resmask |= getIn(1)->getNZMask();
|
||||||
break;
|
break;
|
||||||
case CPUI_INT_MULT:
|
case CPUI_INT_MULT:
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -746,6 +746,8 @@ uintb OpBehaviorPiece::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb i
|
||||||
uintb OpBehaviorSubpiece::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb in2) const
|
uintb OpBehaviorSubpiece::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb in2) const
|
||||||
|
|
||||||
{
|
{
|
||||||
|
if (in2 >= sizeof(uintb))
|
||||||
|
return 0;
|
||||||
uintb res = (in1>>(in2*8)) & calc_mask(sizeout);
|
uintb res = (in1>>(in2*8)) & calc_mask(sizeout);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -896,10 +896,15 @@ int4 RulePullsubMulti::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
Varnode *outvn = op->getOut();
|
Varnode *outvn = op->getOut();
|
||||||
if (outvn->isPrecisLo()||outvn->isPrecisHi()) return 0; // Don't pull apart a double precision object
|
if (outvn->isPrecisLo()||outvn->isPrecisHi()) return 0; // Don't pull apart a double precision object
|
||||||
|
|
||||||
// Make sure we don't new add SUBPIECE ops that aren't going to cancel in some way
|
// Make sure we don't add new SUBPIECE ops that aren't going to cancel in some way
|
||||||
int4 branches = mult->numInput();
|
if (minByte > sizeof(uintb)) return 0;
|
||||||
uintb consume = calc_mask(newSize) << 8*minByte;
|
uintb consume;
|
||||||
|
if (minByte < sizeof(uintb))
|
||||||
|
consume = calc_mask(newSize) << 8*minByte;
|
||||||
|
else
|
||||||
|
consume = 0;
|
||||||
consume = ~consume; // Check for use of bits outside of what gets truncated later
|
consume = ~consume; // Check for use of bits outside of what gets truncated later
|
||||||
|
int4 branches = mult->numInput();
|
||||||
for(int4 i=0;i<branches;++i) {
|
for(int4 i=0;i<branches;++i) {
|
||||||
Varnode *inVn = mult->getIn(i);
|
Varnode *inVn = mult->getIn(i);
|
||||||
if ((consume & inVn->getConsume()) != 0) { // Check if bits not truncated are still used
|
if ((consume & inVn->getConsume()) != 0) { // Check if bits not truncated are still used
|
||||||
|
@ -961,6 +966,7 @@ int4 RulePullsubIndirect::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
Varnode *vn = op->getIn(0);
|
Varnode *vn = op->getIn(0);
|
||||||
if (!vn->isWritten()) return 0;
|
if (!vn->isWritten()) return 0;
|
||||||
|
if (vn->getSize() > sizeof(uintb)) return 0;
|
||||||
PcodeOp *indir = vn->getDef();
|
PcodeOp *indir = vn->getDef();
|
||||||
if (indir->code()!=CPUI_INDIRECT) return 0;
|
if (indir->code()!=CPUI_INDIRECT) return 0;
|
||||||
if (indir->getIn(1)->getSpace()->getType()!=IPTR_IOP) return 0;
|
if (indir->getIn(1)->getSpace()->getType()!=IPTR_IOP) return 0;
|
||||||
|
@ -6850,19 +6856,18 @@ void RulePtraddUndo::getOpList(vector<uint4> &oplist) const
|
||||||
int4 RulePtraddUndo::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RulePtraddUndo::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
Varnode *basevn;
|
|
||||||
TypePointer *tp;
|
|
||||||
|
|
||||||
if (!data.hasTypeRecoveryStarted()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
int4 size = (int4)op->getIn(2)->getOffset(); // Size the PTRADD thinks we are pointing
|
int4 size = (int4)op->getIn(2)->getOffset(); // Size the PTRADD thinks we are pointing
|
||||||
basevn = op->getIn(0);
|
Varnode *basevn = op->getIn(0);
|
||||||
tp = (TypePointer *)basevn->getTypeReadFacing(op);
|
Datatype *dt = basevn->getTypeReadFacing(op);
|
||||||
if (tp->getMetatype() == TYPE_PTR) // Make sure we are still a pointer
|
if (dt->getMetatype() == TYPE_PTR) { // Make sure we are still a pointer
|
||||||
|
TypePointer *tp = (TypePointer *)dt;
|
||||||
if (tp->getPtrTo()->getAlignSize()==AddrSpace::addressToByteInt(size,tp->getWordSize())) { // of the correct size
|
if (tp->getPtrTo()->getAlignSize()==AddrSpace::addressToByteInt(size,tp->getWordSize())) { // of the correct size
|
||||||
Varnode *indVn = op->getIn(1);
|
Varnode *indVn = op->getIn(1);
|
||||||
if ((!indVn->isConstant()) || (indVn->getOffset() != 0)) // and that index isn't zero
|
if ((!indVn->isConstant()) || (indVn->getOffset() != 0)) // and that index isn't zero
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data.opUndoPtradd(op,false);
|
data.opUndoPtradd(op,false);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -7299,8 +7304,9 @@ int4 RulePtrsubCharConstant::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
Varnode *sb = op->getIn(0);
|
Varnode *sb = op->getIn(0);
|
||||||
Datatype *sbType = sb->getTypeReadFacing(op);
|
Datatype *sbType = sb->getTypeReadFacing(op);
|
||||||
if (sbType->getMetatype() != TYPE_PTR) return 0;
|
if (sbType->getMetatype() != TYPE_PTR) return 0;
|
||||||
TypeSpacebase *sbtype = (TypeSpacebase *)((TypePointer *)sbType)->getPtrTo();
|
Datatype *dt = ((TypePointer *)sbType)->getPtrTo();
|
||||||
if (sbtype->getMetatype() != TYPE_SPACEBASE) return 0;
|
if (dt->getMetatype() != TYPE_SPACEBASE) return 0;
|
||||||
|
TypeSpacebase *sbtype = (TypeSpacebase *)dt;
|
||||||
Varnode *vn1 = op->getIn(1);
|
Varnode *vn1 = op->getIn(1);
|
||||||
if (!vn1->isConstant()) return 0;
|
if (!vn1->isConstant()) return 0;
|
||||||
Varnode *outvn = op->getOut();
|
Varnode *outvn = op->getOut();
|
||||||
|
@ -10871,8 +10877,9 @@ int4 RuleExpandLoad::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
if (defOp->code() == CPUI_INT_ADD && defOp->getIn(1)->isConstant()) {
|
if (defOp->code() == CPUI_INT_ADD && defOp->getIn(1)->isConstant()) {
|
||||||
addOp = defOp;
|
addOp = defOp;
|
||||||
rootPtr = defOp->getIn(0);
|
rootPtr = defOp->getIn(0);
|
||||||
offset = defOp->getIn(1)->getOffset();
|
uintb off = defOp->getIn(1)->getOffset();
|
||||||
if (offset > 16) return 0; // INT_ADD offset must be small
|
if (off > 16) return 0; // INT_ADD offset must be small
|
||||||
|
offset = off;
|
||||||
if (defOp->getOut()->loneDescend() == (PcodeOp *)0) return 0; // INT_ADD must be used only once
|
if (defOp->getOut()->loneDescend() == (PcodeOp *)0) return 0; // INT_ADD must be used only once
|
||||||
elType = rootPtr->getTypeReadFacing(defOp);
|
elType = rootPtr->getTypeReadFacing(defOp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -2415,7 +2415,7 @@ void ContextOp::decode(Decoder &decoder,SleighBase *trans)
|
||||||
num = decoder.readSignedInteger(sla::ATTRIB_I);
|
num = decoder.readSignedInteger(sla::ATTRIB_I);
|
||||||
shift = decoder.readSignedInteger(sla::ATTRIB_SHIFT);
|
shift = decoder.readSignedInteger(sla::ATTRIB_SHIFT);
|
||||||
mask = decoder.readUnsignedInteger(sla::ATTRIB_MASK);
|
mask = decoder.readUnsignedInteger(sla::ATTRIB_MASK);
|
||||||
patexp = (PatternValue *)PatternExpression::decodeExpression(decoder,trans);
|
patexp = PatternExpression::decodeExpression(decoder,trans);
|
||||||
patexp->layClaim();
|
patexp->layClaim();
|
||||||
decoder.closeElement(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ void StringManager::assignStringData(StringData &data,const uint1 *buf,int4 size
|
||||||
data.byteData.reserve(newSize + 1);
|
data.byteData.reserve(newSize + 1);
|
||||||
const uint1 *ptr = (const uint1 *)resString.c_str();
|
const uint1 *ptr = (const uint1 *)resString.c_str();
|
||||||
data.byteData.assign(ptr,ptr+newSize);
|
data.byteData.assign(ptr,ptr+newSize);
|
||||||
data.byteData[newSize] = 0; // Make sure there is a null terminator
|
data.byteData.push_back(0); // Make sure there is a null terminator
|
||||||
}
|
}
|
||||||
data.isTruncated = (numChars >= maximumChars);
|
data.isTruncated = (numChars >= maximumChars);
|
||||||
}
|
}
|
||||||
|
|
|
@ -473,6 +473,7 @@ bool SubvariableFlow::traceForward(ReplaceVarnode *rvn)
|
||||||
}
|
}
|
||||||
if (!op->getIn(1)->isConstant()) return false; // Dynamic shift
|
if (!op->getIn(1)->isConstant()) return false; // Dynamic shift
|
||||||
sa = (int4)op->getIn(1)->getOffset();
|
sa = (int4)op->getIn(1)->getOffset();
|
||||||
|
if (sa >= sizeof(uintb)*8) return false; // Beyond precision of mask
|
||||||
newmask = (rvn->mask << sa) & calc_mask( outvn->getSize() );
|
newmask = (rvn->mask << sa) & calc_mask( outvn->getSize() );
|
||||||
if (newmask == 0) break; // Subvar is cleared, truncate flow
|
if (newmask == 0) break; // Subvar is cleared, truncate flow
|
||||||
if (rvn->mask != (newmask >> sa)) return false; // subvar is clipped
|
if (rvn->mask != (newmask >> sa)) return false; // subvar is clipped
|
||||||
|
@ -498,9 +499,12 @@ bool SubvariableFlow::traceForward(ReplaceVarnode *rvn)
|
||||||
}
|
}
|
||||||
if (!op->getIn(1)->isConstant()) return false;
|
if (!op->getIn(1)->isConstant()) return false;
|
||||||
sa = (int4)op->getIn(1)->getOffset();
|
sa = (int4)op->getIn(1)->getOffset();
|
||||||
newmask = rvn->mask >> sa;
|
if (sa >= sizeof(uintb)*8)
|
||||||
|
newmask = 0;
|
||||||
|
else
|
||||||
|
newmask = rvn->mask >> sa;
|
||||||
if (newmask == 0) {
|
if (newmask == 0) {
|
||||||
if (op->code()==CPUI_INT_RIGHT) break; // subvar is set to zero, truncate flow
|
if (op->code()==CPUI_INT_RIGHT) break; // subvar does not pass thru, truncate flow
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (rvn->mask != (newmask << sa)) return false;
|
if (rvn->mask != (newmask << sa)) return false;
|
||||||
|
@ -523,6 +527,7 @@ bool SubvariableFlow::traceForward(ReplaceVarnode *rvn)
|
||||||
break;
|
break;
|
||||||
case CPUI_SUBPIECE:
|
case CPUI_SUBPIECE:
|
||||||
sa = (int4)op->getIn(1)->getOffset() * 8;
|
sa = (int4)op->getIn(1)->getOffset() * 8;
|
||||||
|
if (sa >= sizeof(uintb)*8) break;
|
||||||
newmask = (rvn->mask >> sa) & calc_mask(outvn->getSize());
|
newmask = (rvn->mask >> sa) & calc_mask(outvn->getSize());
|
||||||
if (newmask == 0) break; // subvar is set to zero, truncate flow
|
if (newmask == 0) break; // subvar is set to zero, truncate flow
|
||||||
if (rvn->mask != (newmask << sa)) { // Some kind of truncation of the logical value
|
if (rvn->mask != (newmask << sa)) { // Some kind of truncation of the logical value
|
||||||
|
@ -725,7 +730,10 @@ bool SubvariableFlow::traceBackward(ReplaceVarnode *rvn)
|
||||||
case CPUI_INT_LEFT:
|
case CPUI_INT_LEFT:
|
||||||
if (!op->getIn(1)->isConstant()) break; // Dynamic shift
|
if (!op->getIn(1)->isConstant()) break; // Dynamic shift
|
||||||
sa = (int4)op->getIn(1)->getOffset();
|
sa = (int4)op->getIn(1)->getOffset();
|
||||||
newmask = rvn->mask >> sa; // What mask looks like before shift
|
if (sa >= sizeof(uintb)*8)
|
||||||
|
newmask = 0;
|
||||||
|
else
|
||||||
|
newmask = rvn->mask >> sa; // What mask looks like before shift
|
||||||
if (newmask == 0) { // Subvariable filled with shifted zero
|
if (newmask == 0) { // Subvariable filled with shifted zero
|
||||||
rop = createOp(CPUI_COPY,1,rvn);
|
rop = createOp(CPUI_COPY,1,rvn);
|
||||||
addNewConstant(rop,0,(uintb)0);
|
addNewConstant(rop,0,(uintb)0);
|
||||||
|
@ -744,6 +752,8 @@ bool SubvariableFlow::traceBackward(ReplaceVarnode *rvn)
|
||||||
case CPUI_INT_RIGHT:
|
case CPUI_INT_RIGHT:
|
||||||
if (!op->getIn(1)->isConstant()) break; // Dynamic shift
|
if (!op->getIn(1)->isConstant()) break; // Dynamic shift
|
||||||
sa = (int4)op->getIn(1)->getOffset();
|
sa = (int4)op->getIn(1)->getOffset();
|
||||||
|
if (sa >= sizeof(uintb)*8)
|
||||||
|
break; // Beyond precision of mask
|
||||||
newmask = (rvn->mask << sa) & calc_mask(op->getIn(0)->getSize());
|
newmask = (rvn->mask << sa) & calc_mask(op->getIn(0)->getSize());
|
||||||
if (newmask == 0) { // Subvariable filled with shifted zero
|
if (newmask == 0) { // Subvariable filled with shifted zero
|
||||||
rop = createOp(CPUI_COPY,1,rvn);
|
rop = createOp(CPUI_COPY,1,rvn);
|
||||||
|
@ -758,6 +768,8 @@ bool SubvariableFlow::traceBackward(ReplaceVarnode *rvn)
|
||||||
case CPUI_INT_SRIGHT:
|
case CPUI_INT_SRIGHT:
|
||||||
if (!op->getIn(1)->isConstant()) break; // Dynamic shift
|
if (!op->getIn(1)->isConstant()) break; // Dynamic shift
|
||||||
sa = (int4)op->getIn(1)->getOffset();
|
sa = (int4)op->getIn(1)->getOffset();
|
||||||
|
if (sa >= sizeof(uintb)*8)
|
||||||
|
break; // Beyond precision of mask
|
||||||
newmask = (rvn->mask << sa) & calc_mask(op->getIn(0)->getSize());
|
newmask = (rvn->mask << sa) & calc_mask(op->getIn(0)->getSize());
|
||||||
if ((newmask>>sa) != rvn->mask)
|
if ((newmask>>sa) != rvn->mask)
|
||||||
break; // subvariable is truncated by shift
|
break; // subvariable is truncated by shift
|
||||||
|
@ -1581,8 +1593,11 @@ int4 RuleSubvarSubpiece::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
Varnode *vn = op->getIn(0);
|
Varnode *vn = op->getIn(0);
|
||||||
Varnode *outvn = op->getOut();
|
Varnode *outvn = op->getOut();
|
||||||
int4 flowsize = outvn->getSize();
|
int4 flowsize = outvn->getSize();
|
||||||
|
int4 sa = op->getIn(1)->getOffset();
|
||||||
|
if (flowsize + sa > sizeof(uintb)) // Mask must fit in precision
|
||||||
|
return 0;
|
||||||
uintb mask = calc_mask( flowsize );
|
uintb mask = calc_mask( flowsize );
|
||||||
mask <<= 8*((int4)op->getIn(1)->getOffset());
|
mask <<= 8*sa;
|
||||||
bool aggressive = outvn->isPtrFlow();
|
bool aggressive = outvn->isPtrFlow();
|
||||||
if (!aggressive) {
|
if (!aggressive) {
|
||||||
if ((vn->getConsume() & mask) != vn->getConsume()) return 0;
|
if ((vn->getConsume() & mask) != vn->getConsume()) return 0;
|
||||||
|
|
|
@ -452,8 +452,14 @@ TransformVar *TransformManager::newSplit(Varnode *vn,const LaneDescription &desc
|
||||||
int4 bitpos = description.getPosition(i) * 8;
|
int4 bitpos = description.getPosition(i) * 8;
|
||||||
TransformVar *newVar = &res[i];
|
TransformVar *newVar = &res[i];
|
||||||
int4 byteSize = description.getSize(i);
|
int4 byteSize = description.getSize(i);
|
||||||
if (vn->isConstant())
|
if (vn->isConstant()) {
|
||||||
newVar->initialize(TransformVar::constant,vn,byteSize * 8,byteSize, (vn->getOffset() >> bitpos) & calc_mask(byteSize));
|
uintb val;
|
||||||
|
if (bitpos < sizeof(uintb)*8)
|
||||||
|
val = (vn->getOffset() >> bitpos) & calc_mask(byteSize);
|
||||||
|
else
|
||||||
|
val = 0; // Assume bits beyond precision are 0
|
||||||
|
newVar->initialize(TransformVar::constant,vn,byteSize * 8,byteSize, val);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
uint4 type = preserveAddress(vn, byteSize * 8, bitpos) ? TransformVar::piece : TransformVar::piece_temp;
|
uint4 type = preserveAddress(vn, byteSize * 8, bitpos) ? TransformVar::piece : TransformVar::piece_temp;
|
||||||
newVar->initialize(type,vn,byteSize * 8, byteSize, bitpos);
|
newVar->initialize(type,vn,byteSize * 8, byteSize, bitpos);
|
||||||
|
@ -482,8 +488,14 @@ TransformVar *TransformManager::newSplit(Varnode *vn,const LaneDescription &desc
|
||||||
int4 bitpos = description.getPosition(startLane + i) * 8 - baseBitPos;
|
int4 bitpos = description.getPosition(startLane + i) * 8 - baseBitPos;
|
||||||
int4 byteSize = description.getSize(startLane + i);
|
int4 byteSize = description.getSize(startLane + i);
|
||||||
TransformVar *newVar = &res[i];
|
TransformVar *newVar = &res[i];
|
||||||
if (vn->isConstant())
|
if (vn->isConstant()) {
|
||||||
newVar->initialize(TransformVar::constant,vn,byteSize * 8, byteSize, (vn->getOffset() >> bitpos) & calc_mask(byteSize));
|
uintb val;
|
||||||
|
if (bitpos < sizeof(uintb)*8)
|
||||||
|
val = (vn->getOffset() >> bitpos) & calc_mask(byteSize);
|
||||||
|
else
|
||||||
|
val = 0; // Assume bits beyond precision are 0
|
||||||
|
newVar->initialize(TransformVar::constant,vn,byteSize * 8, byteSize, val);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
uint4 type = preserveAddress(vn, byteSize * 8, bitpos) ? TransformVar::piece : TransformVar::piece_temp;
|
uint4 type = preserveAddress(vn, byteSize * 8, bitpos) ? TransformVar::piece : TransformVar::piece_temp;
|
||||||
newVar->initialize(type,vn,byteSize * 8, byteSize, bitpos);
|
newVar->initialize(type,vn,byteSize * 8, byteSize, bitpos);
|
||||||
|
|
|
@ -3731,8 +3731,9 @@ void TypeFactory::recalcPointerSubmeta(Datatype *base,sub_metatype sub)
|
||||||
top.submeta = sub; // Search on the incorrect submeta
|
top.submeta = sub; // Search on the incorrect submeta
|
||||||
iter = tree.lower_bound(&top);
|
iter = tree.lower_bound(&top);
|
||||||
while(iter != tree.end()) {
|
while(iter != tree.end()) {
|
||||||
TypePointer *ptr = (TypePointer *)*iter;
|
Datatype *dt = *iter;
|
||||||
if (ptr->getMetatype() != TYPE_PTR) break;
|
if (dt->getMetatype() != TYPE_PTR) break;
|
||||||
|
TypePointer *ptr = (TypePointer *)dt;
|
||||||
if (ptr->ptrto != base) break;
|
if (ptr->ptrto != base) break;
|
||||||
++iter;
|
++iter;
|
||||||
if (ptr->submeta == sub) {
|
if (ptr->submeta == sub) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue