Add warning for static buffer overflow

This commit is contained in:
drmortalwombat 2024-04-15 15:40:37 +02:00
parent 755c9234e1
commit 611f672b81
6 changed files with 185 additions and 111 deletions

View File

@ -40,6 +40,7 @@ enum ErrorID
EWARN_NUMERIC_0_USED_AS_NULLPTR,
EWARN_FLOAT_TO_INT,
EWARN_UNDEFINED_POINTER_ARITHMETIC,
EWARN_INVALID_VALUE_RANGE,
EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND,

View File

@ -118,6 +118,11 @@ void IntegerValueRange::LimitMaxWeak(int64 value)
}
}
bool IntegerValueRange::IsInvalid(void) const
{
return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue > mMaxValue;
}
bool IntegerValueRange::IsConstant(void) const
{
return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue == mMaxValue;
@ -8077,6 +8082,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
vr.mMaxValue <<= ins->mSrc[0].mIntConst;
vr.mMinValue <<= ins->mSrc[0].mIntConst;
if (ins->mDst.mType == IT_INT8 && vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue > 255)
{
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxState = IntegerValueRange::S_UNBOUND;
}
}
else if (ins->mSrc[0].IsUByte() && ins->mSrc[0].mRange.mMaxValue < 16)
{
@ -10519,7 +10530,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
nins->mSrc[0] = ains->mSrc[1];
nins->mDst.mTemp = spareTemps++;
nins->mDst.mType = IT_INT16;
nins->mDst.mRange = pins->mDst.mRange;
nins->mDst.mRange = ains->mSrc[1].mRange;
mInstructions.Insert(i, nins);
ins->mSrc[0] = nins->mDst;
@ -19140,6 +19151,31 @@ void InterCodeBasicBlock::CollectGlobalReferences(NumberSet& referencedGlobals,
}
}
void InterCodeBasicBlock::WarnInvalidValueRanges(void)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mInstructions.Size(); i++)
{
InterInstruction* ins = mInstructions[i];
for (int j = 0; j < ins->mNumOperands; j++)
{
if (ins->mSrc[j].mTemp >= 0 && ins->mSrc[j].mRange.IsInvalid())
{
mProc->mModule->mErrors->Error(ins->mLocation, EWARN_INVALID_VALUE_RANGE, "Invalid value range");
}
}
}
if (mTrueJump) mTrueJump->WarnInvalidValueRanges();
if (mFalseJump) mFalseJump->WarnInvalidValueRanges();
}
}
void InterCodeBasicBlock::WarnUsedUndefinedVariables(void)
{
if (!mVisited)
@ -19883,6 +19919,16 @@ void InterCodeProcedure::WarnUsedUndefinedVariables(void)
mEntryBlock->WarnUsedUndefinedVariables();
}
void InterCodeProcedure::WarnInvalidValueRanges(void)
{
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
ResetVisited();
mEntryBlock->WarnInvalidValueRanges();
}
void InterCodeProcedure::TempForwarding(bool reverse, bool checkloops)
{
@ -20503,7 +20549,7 @@ void InterCodeProcedure::Close(void)
{
GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "addGameObjectCannon");
CheckFunc = !strcmp(mIdent->mString, "opp::ostream::operator<<");
CheckCase = false;
mEntryBlock = mBlocks[0];
@ -21409,6 +21455,8 @@ void InterCodeProcedure::Close(void)
BuildTraces(false, false, true);
DisassembleDebug("Final Merged basic blocks");
WarnInvalidValueRanges();
BuildDataFlowSets();
MapCallerSavedTemps();

View File

@ -172,6 +172,7 @@ public:
void SetLimit(int64 minValue, int64 maxValue);
bool IsConstant(void) const;
bool IsInvalid(void) const;
void LimitMin(int64 value);
void LimitMax(int64 value);
@ -619,6 +620,7 @@ public:
bool SameExitCode(const InterCodeBasicBlock* block) const;
void WarnUsedUndefinedVariables(void);
void WarnInvalidValueRanges(void);
void CheckValueReturn(void);
void CheckNullptrDereference(void);
@ -732,6 +734,7 @@ protected:
void MergeBasicBlocks(void);
void CheckUsedDefinedTemps(void);
void WarnUsedUndefinedVariables(void);
void WarnInvalidValueRanges(void);
void PropagateMemoryAliasingInfo(void);
void MoveConditionsOutOfLoop(void);

View File

@ -9245,6 +9245,14 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int sreg0 = ins->mSrc[sop0].mTemp < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop0].mTemp];
if (ins->mSrc[sop1].mTemp >= 0 && ins->mSrc[sop0].mTemp >= 0 && sins1 && sins1 == sins0)
{
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitx")));
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER | NCIF_USE_ZP_32_X, BC_REG_ACCU));
}
else
{
if (ins->mSrc[sop1].mTemp < 0)
{
union { float f; unsigned int v; } cc;
@ -9326,16 +9334,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
{
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitx")));
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER | NCIF_USE_ZP_32_X, sreg0));
#if 0
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
#endif
}
}
@ -49481,25 +49480,42 @@ NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* i
return mRuntime[i];
}
static inline bool isfparam(const NativeCodeInstruction & cins, const NativeCodeInstruction & ins)
{
if (cins.mFlags & NCIF_RUNTIME)
{
if (ins.mAddress >= BC_REG_WORK && ins.mAddress < BC_REG_WORK + 8)
return true;
if (ins.mAddress >= BC_REG_ACCU && ins.mAddress < BC_REG_ACCU + 4)
return true;
}
else
{
if (ins.mAddress >= BC_REG_FPARAMS && ins.mAddress < BC_REG_FPARAMS_END)
return true;
}
return false;
}
void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int at)
{
LinkerObject* lo = block->mIns[at].mLinkerObject;
if (lo->mIdent && !(block->mIns[at].mFlags & NCIF_USE_ZP_32_X))
if (lo->mIdent)// && !(block->mIns[at].mFlags & NCIF_USE_ZP_32_X))
{
uint64 fpmask = 0;
int i = at;
while (i >= 2 &&
block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE &&
block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END &&
isfparam(block->mIns[at], block->mIns[i - 1]) &&
block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE))
{
if (block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 2].mAddress >= BC_REG_FPARAMS && block->mIns[i - 2].mAddress < BC_REG_FPARAMS_END)
{
if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_FPARAMS)))
if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_WORK)))
break;
}
fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_FPARAMS);
fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_WORK);
i -= 2;
}
@ -49508,16 +49524,18 @@ void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int
{
FunctionCall* ncp = new FunctionCall();
ncp->mLinkerObject = lo;
ncp->mOffset = block->mIns[at].mAddress;
ncp->mProxyObject = nullptr;
ncp->mCount = 1;
while (i < at)
{
ncp->mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i];
ncp->mIns[block->mIns[i + 1].mAddress - BC_REG_WORK] = block->mIns[i];
i += 2;
}
FunctionCall* cp = mFunctionCalls;
while (cp && cp->mLinkerObject != ncp->mLinkerObject)
while (cp && (cp->mLinkerObject != ncp->mLinkerObject || cp->mOffset != ncp->mOffset))
cp = cp->mNext;
if (!cp)
{
@ -49556,15 +49574,15 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
int i = at;
while (i >= 2 &&
block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE &&
block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END &&
isfparam(block->mIns[at], block->mIns[i - 1]) &&
block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE))
{
if (block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 2].mAddress >= BC_REG_FPARAMS && block->mIns[i - 2].mAddress < BC_REG_FPARAMS_END)
{
if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_FPARAMS)))
if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_WORK)))
break;
}
fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_FPARAMS);
fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_WORK);
i -= 2;
}
@ -49573,15 +49591,16 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
{
FunctionCall ncp;
ncp.mLinkerObject = lo;
ncp.mOffset = block->mIns[at].mAddress;
int j = i;
while (i < at)
{
ncp.mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i];
ncp.mIns[block->mIns[i + 1].mAddress - BC_REG_WORK] = block->mIns[i];
i += 2;
}
FunctionCall* cp = mFunctionCalls;
while (cp && cp->mLinkerObject != ncp.mLinkerObject)
while (cp && (cp->mLinkerObject != ncp.mLinkerObject || cp->mOffset != ncp.mOffset))
cp = cp->mNext;
if (cp)
{
@ -49607,7 +49626,7 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
{
while (j < at)
{
if (bcp->mIns[block->mIns[j + 1].mAddress - BC_REG_FPARAMS].mType != ASMIT_INV)
if (bcp->mIns[block->mIns[j + 1].mAddress - BC_REG_WORK].mType != ASMIT_INV)
{
block->mIns[j + 0].mType = ASMIT_NOP; block->mIns[j + 0].mMode = ASMIM_IMPLIED;
block->mIns[j + 1].mType = ASMIT_NOP; block->mIns[j + 1].mMode = ASMIM_IMPLIED;
@ -49615,6 +49634,7 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
j += 2;
}
block->mIns[j].mLinkerObject = bcp->mProxyObject;
block->mIns[j].mAddress = 0;
return true;
}
}
@ -49675,13 +49695,13 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
ocalls.Remove(besti);
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{
if (fi->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV)
if (fi->mIns[i - BC_REG_WORK].mType != ASMIT_INV)
{
if (!fi->mIns[i - BC_REG_FPARAMS].IsSame(fj->mIns[i - BC_REG_FPARAMS]))
if (!fi->mIns[i - BC_REG_WORK].IsSame(fj->mIns[i - BC_REG_WORK]))
{
fi->mIns[i - BC_REG_FPARAMS].mType = ASMIT_INV;
fi->mIns[i - BC_REG_WORK].mType = ASMIT_INV;
}
}
}
@ -49709,9 +49729,9 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
ncp->mProxyObject = mLinker->AddObject(ncp->mLinkerObject->mLocation, ncp->mLinkerObject->mIdent->Mangle("@proxy"), ncp->mLinkerObject->mSection, ncp->mLinkerObject->mType);
ExpandingArray<uint8> code;
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{
NativeCodeInstruction& ins(ncp->mIns[i - BC_REG_FPARAMS]);
NativeCodeInstruction& ins(ncp->mIns[i - BC_REG_WORK]);
if (ins.mType == ASMIT_LDA)
{
switch (ins.mMode)
@ -49792,7 +49812,7 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
rl.mObject = ncp->mProxyObject;
rl.mOffset = code.Size();
rl.mRefObject = ncp->mLinkerObject;
rl.mRefOffset = 0;
rl.mRefOffset = ncp->mOffset;
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
ncp->mProxyObject->AddReference(rl);
code.Push(0);
@ -49818,8 +49838,8 @@ void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* obje
bool NativeCodeGenerator::FunctionCall::IsSame(const FunctionCall* fc) const
{
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS]))
for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
if (!mIns[i - BC_REG_WORK].IsSame(fc->mIns[i - BC_REG_WORK]))
return false;
return true;
}
@ -49828,11 +49848,11 @@ int NativeCodeGenerator::FunctionCall::Matches(const FunctionCall* fc) const
{
int match = 0;
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{
if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV)
if (fc->mIns[i - BC_REG_WORK].mType != ASMIT_INV)
{
if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS]))
if (!mIns[i - BC_REG_WORK].IsSame(fc->mIns[i - BC_REG_WORK]))
return -1;
match++;
}
@ -49845,11 +49865,11 @@ int NativeCodeGenerator::FunctionCall::PotentialMatches(const FunctionCall* fc)
{
int match = 0;
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{
if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV)
if (fc->mIns[i - BC_REG_WORK].mType != ASMIT_INV)
{
if (mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS]))
if (mIns[i - BC_REG_WORK].IsSame(fc->mIns[i - BC_REG_WORK]))
match++;
}
}

View File

@ -840,7 +840,7 @@ public:
LinkerObject * mLinkerObject, * mProxyObject;
NativeCodeInstruction mIns[64];
FunctionCall * mNext, * mSame;
int mCount;
int mCount, mOffset;
bool IsSame(const FunctionCall* fc) const;
int Matches(const FunctionCall* fc) const;

View File

@ -212,6 +212,8 @@ int main2(int argc, const char** argv)
compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
else if (arg[2] == 'g')
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
else if (arg[2] == 'm')
compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS;
}
else if (arg[1] == 'e')
{