Plis pase de ane pase depi dènye chèk kòd pwojè LLVM a lè l sèvi avèk analizè PVS-Studio nou an. Ann asire w ke analizeur PVS-Studio la toujou yon zouti dirijan pou idantifye erè ak frajilite potansyèl yo. Pou fè sa, nou pral tcheke epi jwenn nouvo erè nan lage LLVM 8.0.0.
Atik pou ekri
Pou m onèt, mwen pa t vle ekri atik sa a. Li pa enteresan pou ekri sou yon pwojè ke nou te deja tcheke plizyè fwa (
Chak fwa yo pibliye oswa mete ajou yon nouvo vèsyon LLVM
Gade, nouvo vèsyon Clang Static Analyzer te aprann jwenn nouvo erè! Li sanble ke enpòtans pou itilize PVS-Studio ap diminye. Clang jwenn plis erè pase anvan ak kenbe ak kapasite PVS-Studio. Kisa ou panse de sa?
Pou sa mwen toujou vle reponn yon bagay tankou:
Nou pa chita san fè anyen konsa tou! Nou te siyifikativman amelyore kapasite yo nan analizeur PVS-Studio la. Donk pa enkyete w, nou kontinye dirije tankou anvan.
Malerezman, sa a se yon move repons. Pa gen okenn prèv ladan l. Se poutèt sa mwen ekri atik sa a kounye a. Se konsa, pwojè LLVM la te tcheke yon lòt fwa ankò epi yo te jwenn yon varyete erè ladan l. Kounye a mwen pral montre sa ki te sanble enteresan pou mwen. Clang Static Analyzer pa ka jwenn erè sa yo (oswa li trè enkonvenyan pou fè sa avèk èd li). Men nou kapab. Anplis, mwen te jwenn ak ekri tout erè sa yo nan yon aswè.
Men, ekri atik la te pran plizyè semèn. Mwen jis pa t 'kapab mennen tèt mwen mete tout bagay sa yo nan tèks :).
By wout la, si w enterese nan ki teknoloji yo itilize nan analizè PVS-Studio pou idantifye erè ak frajilite potansyèl, Lè sa a, mwen sijere pou w fè konesans ak sa a.
Nouvo ak ansyen dyagnostik
Kòm deja note, sa gen anviwon dezan pwojè LLVM la te tcheke yon lòt fwa ankò, epi yo te korije erè yo jwenn. Koulye a, atik sa a pral prezante yon nouvo pakèt erè. Poukisa yo te jwenn nouvo pinèz? Gen 3 rezon pou sa:
- Pwojè LLVM ap evolye, chanje ansyen kòd epi ajoute nouvo kòd. Natirèlman, gen nouvo erè nan kòd la modifye ak ekri. Sa a montre klèman ke analiz estatik ta dwe itilize regilyèman, epi yo pa detanzantan. Atik nou yo montre byen kapasite PVS-Studio analyser la, men sa pa gen anyen fè ak amelyore kalite kòd ak diminye pri pou repare erè. Sèvi ak yon analizè kòd estatik regilyèman!
- Nou ap finalize ak amelyore dyagnostik ki deja egziste. Se poutèt sa, analizè a ka idantifye erè ke li pa t remake pandan analiz anvan yo.
- Nouvo dyagnostik te parèt nan PVS-Studio ki pa t egziste 2 zan de sa. Mwen deside mete aksan sou yo nan yon seksyon separe pou montre klèman devlopman PVS-Studio.
Defo idantifye pa dyagnostik ki te egziste 2 zan de sa
Fragman N1: Kopi-Kole
static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
if (Name == "addcarryx.u32" || // Added in 8.0
....
Name == "avx512.mask.cvtps2pd.128" || // Added in 7.0
Name == "avx512.mask.cvtps2pd.256" || // Added in 7.0
Name == "avx512.cvtusi2sd" || // Added in 7.0
Name.startswith("avx512.mask.permvar.") || // Added in 7.0 // <=
Name.startswith("avx512.mask.permvar.") || // Added in 7.0 // <=
Name == "sse2.pmulu.dq" || // Added in 7.0
Name == "sse41.pmuldq" || // Added in 7.0
Name == "avx2.pmulu.dq" || // Added in 7.0
....
}
Avètisman PVS-Studio:
Li se doub tcheke ke non an kòmanse ak substring "avx512.mask.permvar.". Nan dezyèm chèk la, yo evidamman te vle ekri yon lòt bagay, men yo bliye korije tèks la kopye.
Fragman N2: Typo
enum CXNameRefFlags {
CXNameRange_WantQualifier = 0x1,
CXNameRange_WantTemplateArgs = 0x2,
CXNameRange_WantSinglePiece = 0x4
};
void AnnotateTokensWorker::HandlePostPonedChildCursor(
CXCursor Cursor, unsigned StartTokenIndex) {
const auto flags = CXNameRange_WantQualifier | CXNameRange_WantQualifier;
....
}
Avètisman PVS-Studio: V501 Gen sub-ekspresyon ki idantik 'CXNameRange_WantQualifier' sou bò gòch la ak sou bò dwat la nan '|' operatè. CIndex.cpp 7245
Akòz yon typo, yo itilize menm konstan yo rele de fwa CXNameRange_WantQualifier.
Fragman N3: Konfizyon ak priyorite operatè
int PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
....
if (ISD == ISD::EXTRACT_VECTOR_ELT && Index == ST->isLittleEndian() ? 1 : 0)
return 0;
....
}
Avètisman PVS-Studio:
Dapre mwen, sa a se yon trè bèl erè. Wi, mwen konnen mwen gen lide etranj sou bote :).
Koulye a, dapre
(ISD == ISD::EXTRACT_VECTOR_ELT && (Index == ST->isLittleEndian())) ? 1 : 0
Soti nan yon pwen de vi pratik, kondisyon sa a pa fè sans, paske li ka redwi a:
(ISD == ISD::EXTRACT_VECTOR_ELT && Index == ST->isLittleEndian())
Sa a se yon erè klè. Gen plis chans, yo te vle konpare 0/1 ak yon varyab endèks. Pou ranje kòd la ou bezwen ajoute parantèz alantou operatè a ternary:
if (ISD == ISD::EXTRACT_VECTOR_ELT && Index == (ST->isLittleEndian() ? 1 : 0))
By wout la, operatè a ternary trè danjere ak pwovoke erè lojik. Fè anpil atansyon ak li epi pa dwe visye ak parantèz. Mwen te gade sijè sa a an plis detay
Fragman N4, N5: Pointeur nil
Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
....
TypedInit *LHS = dyn_cast<TypedInit>(Result);
....
LHS = dyn_cast<TypedInit>(
UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get())
->Fold(CurRec));
if (!LHS) {
Error(PasteLoc, Twine("can't cast '") + LHS->getAsString() +
"' to string");
return nullptr;
}
....
}
Avètisman PVS-Studio:
Si konsèy la LHS se nil, yo ta dwe bay yon avètisman. Sepandan, olye de sa, yo pral dereferans menm pwent nil sa a: LHS->getAsString().
Sa a se yon sitiyasyon trè tipik lè yon erè kache nan yon moun ki okipe erè, paske pa gen moun ki teste yo. Analizè estatik tcheke tout kòd ki ka jwenn, kèlkeswa konbyen fwa yo itilize yo. Sa a se yon trè bon egzanp sou fason analiz estatik konplete lòt tès ak teknik pwoteksyon erè.
Erè manyen konsèy menm jan an HRH pèmèt nan kòd la jis anba a: V522 [CWE-476] Dereferencing nan pointeur nil 'RHS' ka pran plas. TGParser.cpp 2186
Fragman N6: Sèvi ak konsèy la apre w fin deplase
static Expected<bool>
ExtractBlocks(....)
{
....
std::unique_ptr<Module> ProgClone = CloneModule(BD.getProgram(), VMap);
....
BD.setNewProgram(std::move(ProgClone)); // <=
MiscompiledFunctions.clear();
for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first); // <=
assert(NewF && "Function not found??");
MiscompiledFunctions.push_back(NewF);
}
....
}
Avètisman PVS-Studio: V522 [CWE-476] Dereferencing nan pointeur nil 'ProgClone' ta ka pran plas. Miscompilation.cpp 601
Nan kòmansman an yon konsèy entelijan ProgClone sispann posede objè a:
BD.setNewProgram(std::move(ProgClone));
An reyalite, kounye a ProgClone se yon konsèy nil. Se poutèt sa, yon dereference pointeur nil ta dwe rive jis anba a:
Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
Men, an reyalite, sa a pa pral rive! Remake byen ke bouk la pa aktyèlman egzekite.
Nan kòmansman veso a MiscompiledFunctions otorize:
MiscompiledFunctions.clear();
Apre sa, yo itilize gwosè veso sa a nan kondisyon bouk la:
for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
Li fasil pou wè ke bouk la pa kòmanse. Mwen panse ke sa a se tou yon ensèk epi kòd la ta dwe ekri yon fason diferan.
Li sanble ke nou te rankontre ke parite pi popilè nan erè! Yon erè maske yon lòt :).
Fragman N7: Sèvi ak konsèy la apre w fin deplase
static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
std::unique_ptr<Module> Safe) {
outs() << " Optimizing functions being tested: ";
std::unique_ptr<Module> Optimized =
BD.runPassesOn(Test.get(), BD.getPassesToRun());
if (!Optimized) {
errs() << " Error running this sequence of passes"
<< " on the input program!n";
BD.setNewProgram(std::move(Test)); // <=
BD.EmitProgressBitcode(*Test, "pass-error", false); // <=
if (Error E = BD.debugOptimizerCrash())
return std::move(E);
return false;
}
....
}
Avètisman PVS-Studio: V522 [CWE-476] Dereferencing nan "Tès" pointeur nil la ka pran plas. Miscompilation.cpp 709
Menm sitiyasyon an ankò. Okòmansman, sa ki nan objè a deplase, epi Lè sa a, li itilize kòm si pa gen anyen ki te rive. Mwen wè sitiyasyon sa a pi plis ak pi souvan nan kòd pwogram apre semantik mouvman parèt nan C++. Se poutèt sa mwen renmen lang C++ la! Gen plis ak plis nouvo fason yo tire pwòp janm ou koupe. Analizatè PVS-Studio ap toujou gen travay :).
Fragman N8: Pointeur nil
void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
uint32_t TypeId = Symbol.getTypeId();
auto Type = Symbol.getSession().getSymbolById(TypeId);
if (Type)
Printer << "<unknown-type>";
else
Type->dump(*this);
}
Avètisman PVS-Studio: V522 [CWE-476] Dereferencing nan 'Type' pointeur nil la ka pran plas. PrettyFunctionDumper.cpp 233
Anplis moun kap okipe erè, fonksyon enprime debogaj yo anjeneral pa teste. Nou gen jis yon ka konsa devan nou. Fonksyon an ap tann itilizatè a, ki, olye pou yo rezoud pwoblèm li yo, yo pral fòse yo ranje li.
Kòrèkteman:
if (Type)
Type->dump(*this);
else
Printer << "<unknown-type>";
Fragman N9: Pointeur nil
void SearchableTableEmitter::collectTableEntries(
GenericTable &Table, const std::vector<Record *> &Items) {
....
RecTy *Ty = resolveTypes(Field.RecType, TI->getType());
if (!Ty) // <=
PrintFatalError(Twine("Field '") + Field.Name + "' of table '" +
Table.Name + "' has incompatible type: " +
Ty->getAsString() + " vs. " + // <=
TI->getType()->getAsString());
....
}
Avètisman PVS-Studio: V522 [CWE-476] Dereferencing nan pointeur nil 'Ty' ta ka pran plas. SearchableTableEmitter.cpp 614
Mwen panse ke tout bagay klè epi yo pa mande pou eksplikasyon.
Fragman N10: Typo
bool FormatTokenLexer::tryMergeCSharpNullConditionals() {
....
auto &Identifier = *(Tokens.end() - 2);
auto &Question = *(Tokens.end() - 1);
....
Identifier->ColumnWidth += Question->ColumnWidth;
Identifier->Type = Identifier->Type; // <=
Tokens.erase(Tokens.end() - 1);
return true;
}
Avètisman PVS-Studio:
Pa gen okenn pwen nan plase yon varyab nan tèt li. Gen plis chans yo te vle ekri:
Identifier->Type = Question->Type;
Fragman N11: kraze sispèk
void SystemZOperand::print(raw_ostream &OS) const {
switch (Kind) {
break;
case KindToken:
OS << "Token:" << getToken();
break;
case KindReg:
OS << "Reg:" << SystemZInstPrinter::getRegisterName(getReg());
break;
....
}
Avètisman PVS-Studio:
Gen yon operatè trè sispèk nan kòmansman an kraze. Èske ou bliye ekri yon lòt bagay isit la?
Fragman N12: Tcheke yon konsèy apre dereferancing
InlineCost AMDGPUInliner::getInlineCost(CallSite CS) {
Function *Callee = CS.getCalledFunction();
Function *Caller = CS.getCaller();
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
if (!Callee || Callee->isDeclaration())
return llvm::InlineCost::getNever("undefined callee");
....
}
Avètisman PVS-Studio:
Pointer Callee nan kòmansman an se dereferans nan moman an yo rele fonksyon an getTTI.
Lè sa a, li sanble ke konsèy sa a ta dwe tcheke pou egalite nullptr:
if (!Callee || Callee->isDeclaration())
Men li twò ta...
Fragman N13 - N...: Tcheke yon konsèy apre dereferancing
Sitiyasyon an te diskite nan fragman kòd anvan an pa inik. Li parèt isit la:
static Value *optimizeDoubleFP(CallInst *CI, IRBuilder<> &B,
bool isBinary, bool isPrecise = false) {
....
Function *CalleeFn = CI->getCalledFunction();
StringRef CalleeNm = CalleeFn->getName(); // <=
AttributeList CalleeAt = CalleeFn->getAttributes();
if (CalleeFn && !CalleeFn->isIntrinsic()) { // <=
....
}
Avètisman PVS-Studio: V595 [CWE-476] Yo te itilize pointeur 'CalleeFn' la anvan yo te verifye li kont nullptr. Tcheke liy yo: 1079, 1081. SimplifyLibCalls.cpp 1079
Ak isit la:
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *OuterMostScope) {
....
NamedDecl *ND = dyn_cast<NamedDecl>(New);
CXXRecordDecl *ThisContext =
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); // <=
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
ND && ND->isCXXInstanceMember()); // <=
....
}
Avètisman PVS-Studio: V595 [CWE-476] Yo te itilize pointeur 'ND' anvan li te verifye kont nullptr. Tcheke liy yo: 532, 534. SemaTemplateInstantiateDecl.cpp 532
Ak isit la:
- V595 [CWE-476] Yo te itilize pointeur 'U' a anvan yo te verifye li kont nullptr. Tcheke liy yo: 404, 407. DWARFormValue.cpp 404
- V595 [CWE-476] Yo te itilize pointeur 'ND' anvan li te verifye kont nullptr. Tcheke liy yo: 2149, 2151. SemaTemplateInstantiate.cpp 2149
Apre sa, mwen te vin pa enterese nan etidye avètisman yo ak nimewo V595. Se konsa, mwen pa konnen si gen plis erè ki sanble san konte sa yo ki nan lis isit la. Gen plis chans genyen.
Fragman N17, N18: Chanjman sispèk
static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize,
uint64_t &Encoding) {
....
unsigned Size = RegSize;
....
uint64_t NImms = ~(Size-1) << 1;
....
}
Avètisman PVS-Studio:
Li ka pa yon ensèk epi kòd la ap travay egzakteman jan sa vle di. Men, sa a se klèman yon kote ki trè sispèk epi li bezwen tcheke.
Ann di varyab la Kantite moun ki se egal a 16, ak Lè sa a, otè a nan kòd la te planifye jwenn li nan yon varyab NImms valè:
1111111111111111111111111111111111111111111111111111111111100000
Sepandan, an reyalite rezilta a pral:
0000000000000000000000000000000011111111111111111111111111100000
Reyalite a se ke tout kalkil fèt lè l sèvi avèk kalite a 32-bit ki pa siyen. Epi sèlman lè sa a, kalite 32-bit sa a san siyen yo pral implicite elaji nan uint64_t. Nan ka sa a, moso ki pi enpòtan yo pral zewo.
Ou ka ranje sitiyasyon an tankou sa a:
uint64_t NImms = ~static_cast<uint64_t>(Size-1) << 1;
Sitiyasyon menm jan an: V629 [CWE-190] Konsidere enspekte ekspresyon 'Immr << 6' la. Deplasman ti jan nan valè a 32-ti jan ak yon ekspansyon ki vin apre nan kalite a 64-ti jan. AArch64AddressingModes.h 269
Fragman N19: Mo kle ki manke Lòt Bagay?
void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
....
if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
// VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
// Skip it.
continue;
} if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { // <=
Op.addRegWithFPInputModsOperands(Inst, 2);
} else if (Op.isDPPCtrl()) {
Op.addImmOperands(Inst, 1);
} else if (Op.isImm()) {
// Handle optional arguments
OptionalIdx[Op.getImmTy()] = I;
} else {
llvm_unreachable("Invalid operand type");
}
....
}
Avètisman PVS-Studio:
Pa gen okenn erè isit la. Depi lè sa a-blòk premye a if fini ak kontinye, Lè sa a, li pa enpòtan, gen yon mo kle Lòt Bagay oswa ou pa. Nenpòt fason kòd la ap travay menm jan an. Toujou rate Lòt Bagay fè kòd la pi klè ak danjere. Si nan tan kap vini an kontinye disparèt, kòd la ap kòmanse travay yon fason diferan. Dapre mwen, li pi bon ajoute Lòt Bagay.
Fragman N20: Kat typo nan menm kalite a
LLVM_DUMP_METHOD void Symbol::dump(raw_ostream &OS) const {
std::string Result;
if (isUndefined())
Result += "(undef) ";
if (isWeakDefined())
Result += "(weak-def) ";
if (isWeakReferenced())
Result += "(weak-ref) ";
if (isThreadLocalValue())
Result += "(tlv) ";
switch (Kind) {
case SymbolKind::GlobalSymbol:
Result + Name.str(); // <=
break;
case SymbolKind::ObjectiveCClass:
Result + "(ObjC Class) " + Name.str(); // <=
break;
case SymbolKind::ObjectiveCClassEHType:
Result + "(ObjC Class EH) " + Name.str(); // <=
break;
case SymbolKind::ObjectiveCInstanceVariable:
Result + "(ObjC IVar) " + Name.str(); // <=
break;
}
OS << Result;
}
Avètisman PVS-Studio:
- V655 [CWE-480] Fisèl yo te konkatenasyon men yo pa itilize. Konsidere enspekte ekspresyon 'Rezilta + Name.str()'. Senbòl.cpp 32
- V655 [CWE-480] Fisèl yo te konkatenasyon men yo pa itilize. Konsidere enspekte ekspresyon 'Rezilta + "(Klas ObjC)" + Name.str()'. Senbòl.cpp 35
- V655 [CWE-480] Fisèl yo te konkatenasyon men yo pa itilize. Konsidere enspekte ekspresyon 'Rezilta + "(ObjC Klas EH)" + Name.str()'. Senbòl.cpp 38
- V655 [CWE-480] Fisèl yo te konkatenasyon men yo pa itilize. Konsidere enspekte ekspresyon 'Rezilta + "(ObjC IVar)" + Name.str()'. Senbòl.cpp 41
Pa aksidan, yo itilize + operatè olye de += operatè a. Rezilta a se desen ki san sans.
Fragman N21: Konpòtman pa defini
static void getReqFeatures(std::map<StringRef, int> &FeaturesMap,
const std::vector<Record *> &ReqFeatures) {
for (auto &R : ReqFeatures) {
StringRef AsmCondString = R->getValueAsString("AssemblerCondString");
SmallVector<StringRef, 4> Ops;
SplitString(AsmCondString, Ops, ",");
assert(!Ops.empty() && "AssemblerCondString cannot be empty");
for (auto &Op : Ops) {
assert(!Op.empty() && "Empty operator");
if (FeaturesMap.find(Op) == FeaturesMap.end())
FeaturesMap[Op] = FeaturesMap.size();
}
}
}
Eseye jwenn kòd danjere tèt ou. Ak sa a se yon foto distrè atansyon pou yo pa imedyatman gade repons lan:
Avètisman PVS-Studio:
Liy pwoblèm:
FeaturesMap[Op] = FeaturesMap.size();
Si eleman Op pa jwenn, Lè sa a, yon nouvo eleman kreye nan kat la epi kantite eleman nan kat sa a ekri la. Li jis enkoni si yo pral rele fonksyon an gwosè anvan oswa apre ajoute yon nouvo eleman.
Fragman N22-N24: Devwa repete
Error MachOObjectFile::checkSymbolTable() const {
....
} else {
MachO::nlist STE = getSymbolTableEntry(SymDRI);
NType = STE.n_type; // <=
NType = STE.n_type; // <=
NSect = STE.n_sect;
NDesc = STE.n_desc;
NStrx = STE.n_strx;
NValue = STE.n_value;
}
....
}
Avètisman PVS-Studio:
Mwen pa panse ke gen yon erè reyèl isit la. Jis yon devwa repete ki pa nesesè. Men, toujou yon erè.
Menm jan an tou:
- V519 [CWE-563] Varyab 'B.NDesc' yo bay valè de fwa youn apre lòt. Petèt sa a se yon erè. Tcheke liy yo: 1488, 1489. llvm-nm.cpp 1489
- V519 [CWE-563] Varyab la bay valè de fwa youn apre lòt. Petèt sa a se yon erè. Tcheke liy yo: 59, 61. coff2yaml.cpp 61
Fragman N25-N27: Plis transfè
Koulye a, kite a gade nan yon vèsyon yon ti kras diferan nan reassignment.
bool Vectorizer::vectorizeLoadChain(
ArrayRef<Instruction *> Chain,
SmallPtrSet<Instruction *, 16> *InstructionsProcessed) {
....
unsigned Alignment = getAlignment(L0);
....
unsigned NewAlign = getOrEnforceKnownAlignment(L0->getPointerOperand(),
StackAdjustedAlignment,
DL, L0, nullptr, &DT);
if (NewAlign != 0)
Alignment = NewAlign;
Alignment = NewAlign;
....
}
Avètisman PVS-Studio: V519 [CWE-563] Varyab "Aliyman" yo bay valè de fwa youn apre lòt. Petèt sa a se yon erè. Tcheke liy yo: 1158, 1160. LoadStoreVectorizer.cpp 1160
Sa a se kòd trè etranj ki aparamman gen yon erè lojik. Nan kòmansman an, varyab Aliyman yo bay yon valè depann sou kondisyon an. Lè sa a, plasman an rive ankò, men kounye a san okenn chèk.
Sitiyasyon menm jan an ka wè isit la:
- V519 [CWE-563] Varyab 'Efè' yo bay valè de fwa youn apre lòt. Petèt sa a se yon erè. Tcheke liy yo: 152, 165. WebAssemblyRegStackify.cpp 165
- V519 [CWE-563] Varyab 'ExpectNoDerefChunk' yo bay valè de fwa youn apre lòt. Petèt sa a se yon erè. Tcheke liy yo: 4970, 4973. SemaType.cpp 4973
Fragman N28: Toujou vre kondisyon
static int readPrefixes(struct InternalInstruction* insn) {
....
uint8_t byte = 0;
uint8_t nextByte;
....
if (byte == 0xf3 && (nextByte == 0x88 || nextByte == 0x89 ||
nextByte == 0xc6 || nextByte == 0xc7)) {
insn->xAcquireRelease = true;
if (nextByte != 0x90) // PAUSE instruction support // <=
break;
}
....
}
Avètisman PVS-Studio:
Tcheke pa fè sans. Varyab nextByte toujou pa egal a valè a 0x90, ki swiv nan chèk anvan an. Sa a se yon kalite erè lojik.
Fragman N29 - N...: Kondisyon toujou vre/fo
Analizè a bay anpil avètisman ke tout kondisyon an (
static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
if (RegNo > 13)
return MCDisassembler::Fail;
if ((RegNo & 1) || RegNo == 0xe)
S = MCDisassembler::SoftFail;
....
}
Avètisman PVS-Studio:
Konstan 0xE a se valè 14 an desimal. Egzaminasyon RegNo == 0xe pa fè sans paske si RegNo > 13, Lè sa a, fonksyon an pral konplete ekzekisyon li.
Te gen anpil lòt avètisman ak ID V547 ak V560, men menm jan ak
Mwen pral ba ou yon egzanp poukisa etidye deklannche sa yo se raz. Analizè a se absoliman dwa nan bay yon avètisman pou kòd sa a. Men, sa a se pa yon erè.
bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
tok::TokenKind ClosingBraceKind) {
bool HasError = false;
....
HasError = true;
if (!ContinueOnSemicolons)
return !HasError;
....
}
Avètisman PVS-Studio: V547 [CWE-570] Ekspresyon '!HasError' toujou fo. UnwrappedLineParser.cpp 1635
Fragman N30: Retounen sispèk
static bool
isImplicitlyDef(MachineRegisterInfo &MRI, unsigned Reg) {
for (MachineRegisterInfo::def_instr_iterator It = MRI.def_instr_begin(Reg),
E = MRI.def_instr_end(); It != E; ++It) {
return (*It).isImplicitDef();
}
....
}
Avètisman PVS-Studio:
Sa a se swa yon erè oswa yon teknik espesifik ki gen entansyon eksplike yon bagay bay pwogramasyon li kòd la. Konsepsyon sa a pa esplike m anyen e li sanble anpil sispèk. Li pi bon pa ekri konsa :).
Fatige? Lè sa a, li lè yo fè te oswa kafe.
Defo idantifye pa nouvo dyagnostik
Mwen panse ke 30 aktivasyon nan dyagnostik fin vye granmoun se ase. Ann wè kounye a ki bagay enteresan yo ka jwenn ak nouvo dyagnostik ki te parèt nan analizeur a apre
Fragman N31: Kòd inaccessible
Error CtorDtorRunner::run() {
....
if (auto CtorDtorMap =
ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names),
NoDependenciesToRegister, true))
{
....
return Error::success();
} else
return CtorDtorMap.takeError();
CtorDtorsByPriority.clear();
return Error::success();
}
Avètisman PVS-Studio:
Kòm ou ka wè, tou de branch nan operatè a if fini ak yon apèl bay operatè a retounen. An konsekans, veso a CtorDtorsByPriority p'ap janm netwaye.
Fragman N32: Kòd inaccessible
bool LLParser::ParseSummaryEntry() {
....
switch (Lex.getKind()) {
case lltok::kw_gv:
return ParseGVEntry(SummaryID);
case lltok::kw_module:
return ParseModuleEntry(SummaryID);
case lltok::kw_typeid:
return ParseTypeIdEntry(SummaryID); // <=
break; // <=
default:
return Error(Lex.getLoc(), "unexpected summary kind");
}
Lex.setIgnoreColonInIdentifiers(false); // <=
return false;
}
Avètisman PVS-Studio: V779 [CWE-561] Kòd inaccessible detekte. Li posib ke gen yon erè prezan. LLParser.cpp 835
Sitiyasyon enteresan. Ann gade kote sa a an premye:
return ParseTypeIdEntry(SummaryID);
break;
Nan premye gade, li sanble ke pa gen okenn erè isit la. Li sanble ak operatè a kraze gen yon lòt isit la, epi ou ka tou senpleman efase li. Sepandan, se pa tout konsa senp.
Analizè a bay yon avètisman sou liy yo:
Lex.setIgnoreColonInIdentifiers(false);
return false;
Ak tout bon, kòd sa a se inaccessible. Tout ka nan chanje fini ak yon apèl nan men operatè a retounen. Epi kounye a san sans pou kont li kraze pa sanble konsa inofansif! Petèt youn nan branch yo ta dwe fini ak kraze, pa sou retounen?
Fragman N33: Reyajiste o aza nan Bits segondè
unsigned getStubAlignment() override {
if (Arch == Triple::systemz)
return 8;
else
return 1;
}
Expected<unsigned>
RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
const SectionRef &Section,
bool IsCode) {
....
uint64_t DataSize = Section.getSize();
....
if (StubBufSize > 0)
DataSize &= ~(getStubAlignment() - 1);
....
}
Avètisman PVS-Studio:
Tanpri sonje ke fonksyon an getStubAlignment kalite retounen siyen. Ann kalkile valè ekspresyon an, sipoze fonksyon an retounen valè 8:
~(getStubAlignment() - 1)
~(8u-1)
0xFFFFFFFF8u
Koulye a, remake ke varyab la DataSize gen yon kalite 64-bit ki pa siyen. Li sanble ke lè w ap fè operasyon DataSize & 0xFFFFFFF8u, tout trant-de gwo lòd yo pral reset a zewo. Gen plis chans, sa a se pa sa pwogramè a te vle. Mwen sispèk ke li te vle kalkile: DataSize & 0xFFFFFFFFFFFFFFF8u.
Pou korije erè a, ou ta dwe ekri sa a:
DataSize &= ~(static_cast<uint64_t>(getStubAlignment()) - 1);
Oswa konsa:
DataSize &= ~(getStubAlignment() - 1ULL);
Fragman N34: Echwe kalite eksplisit jete
template <typename T>
void scaleShuffleMask(int Scale, ArrayRef<T> Mask,
SmallVectorImpl<T> &ScaledMask) {
assert(0 < Scale && "Unexpected scaling factor");
int NumElts = Mask.size();
ScaledMask.assign(static_cast<size_t>(NumElts * Scale), -1);
....
}
Avètisman PVS-Studio:
Distribisyon kalite eksplisit yo itilize pou fè pou evite debòde lè miltipliye varyab kalite int. Sepandan, depoze kalite eksplisit isit la pa pwoteje kont debòde. Premyèman, varyab yo pral miltipliye, epi sèlman Lè sa a, rezilta miltiplikasyon an 32-bit yo pral elaji nan kalite a.
Fragman N35: Echwe Kopi-Kole
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
....
if (!match(Op0, m_PosZeroFP()) && isKnownNeverNaN(Op0, &TLI)) {
I.setOperand(0, ConstantFP::getNullValue(Op0->getType()));
return &I;
}
if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
I.setOperand(1, ConstantFP::getNullValue(Op0->getType())); // <=
return &I;
}
....
}
Nouvo dyagnostik enteresan sa a idantifye sitiyasyon kote yon moso kòd te kopye ak kèk non ladan l te kòmanse chanje, men nan yon sèl kote yo pa korije li.
Tanpri sonje ke nan dezyèm blòk la yo chanje Op0 sou Op1. Men, nan yon sèl kote yo pa t 'ranje li. Gen plis chans li ta dwe ekri tankou sa a:
if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
I.setOperand(1, ConstantFP::getNullValue(Op1->getType()));
return &I;
}
Fragman N36: Konfizyon Varyab
struct Status {
unsigned Mask;
unsigned Mode;
Status() : Mask(0), Mode(0){};
Status(unsigned Mask, unsigned Mode) : Mask(Mask), Mode(Mode) {
Mode &= Mask;
};
....
};
Avètisman PVS-Studio:
Li trè danjere pou bay agiman fonksyon menm non ak manm klas yo. Li trè fasil jwenn konfonn. Nou gen jis yon ka konsa devan nou. Ekspresyon sa a pa fè sans:
Mode &= Mask;
Agiman fonksyon an chanje. Se tout. Agiman sa a pa sèvi ankò. Gen plis chans ou ta dwe ekri li konsa:
Status(unsigned Mask, unsigned Mode) : Mask(Mask), Mode(Mode) {
this->Mode &= Mask;
};
Fragman N37: Konfizyon Varyab
class SectionBase {
....
uint64_t Size = 0;
....
};
class SymbolTableSection : public SectionBase {
....
};
void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
SectionBase *DefinedIn, uint64_t Value,
uint8_t Visibility, uint16_t Shndx,
uint64_t Size) {
....
Sym.Value = Value;
Sym.Visibility = Visibility;
Sym.Size = Size;
Sym.Index = Symbols.size();
Symbols.emplace_back(llvm::make_unique<Symbol>(Sym));
Size += this->EntrySize;
}
Avètisman PVS-Studio: V1001 [CWE-563] Yo bay varyab 'Gwosè' men yo pa itilize nan fen fonksyon an. Object.cpp 424
Sitiyasyon an sanble ak sa anvan an. Li ta dwe ekri:
this->Size += this->EntrySize;
Fragman N38-N47: Yo bliye tcheke endèks la
Précédemment, nou te gade egzanp deklanchman dyagnostik
int getGEPCost(Type *PointeeType, const Value *Ptr,
ArrayRef<const Value *> Operands) {
....
if (Ptr != nullptr) { // <=
assert(....);
BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts());
}
bool HasBaseReg = (BaseGV == nullptr);
auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType()); // <=
....
}
Avètisman PVS-Studio: V1004 [CWE-476] Yo te itilize pointeur 'Ptr' a san danje apre li te verifye kont nullptr. Tcheke liy yo: 729, 738. TargetTransformInfoImpl.h 738
Varyab ptr ka egal nullptr, jan chèk la montre:
if (Ptr != nullptr)
Sepandan, anba a konsèy sa a dereferans san yo pa tcheke preliminè:
auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType());
Ann konsidere yon lòt ka menm jan an.
llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
bool Stub) {
....
auto *FD = dyn_cast<FunctionDecl>(GD.getDecl());
SmallVector<QualType, 16> ArgTypes;
if (FD) // <=
for (const ParmVarDecl *Parm : FD->parameters())
ArgTypes.push_back(Parm->getType());
CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv(); // <=
....
}
Avètisman PVS-Studio: V1004 [CWE-476] Yo te itilize pwent 'FD' a san danje apre li te verifye kont nullptr. Tcheke liy yo: 3228, 3231. CGDebugInfo.cpp 3231
Peye atansyon sou siy la FD. Mwen sèten pwoblèm nan vizib klèman e pa gen okenn eksplikasyon espesyal ki nesesè.
Ak pi lwen:
static void computePolynomialFromPointer(Value &Ptr, Polynomial &Result,
Value *&BasePtr,
const DataLayout &DL) {
PointerType *PtrTy = dyn_cast<PointerType>(Ptr.getType());
if (!PtrTy) { // <=
Result = Polynomial();
BasePtr = nullptr;
}
unsigned PointerBits =
DL.getIndexSizeInBits(PtrTy->getPointerAddressSpace()); // <=
....
}
Avètisman PVS-Studio: V1004 [CWE-476] Yo te itilize pointeur 'PtrTy' a san danje apre li te verifye kont nullptr. Tcheke liy yo: 960, 965. InterleavedLoadCombinePass.cpp 965
Ki jan yo pwoteje tèt ou kont erè sa yo? Fè plis atansyon sou Code-Review epi sèvi ak analizè estatik PVS-Studio pou tcheke kòd ou regilyèman.
Pa gen okenn pwen nan site lòt fragman kòd ak erè nan kalite sa a. Mwen pral kite sèlman yon lis avètisman nan atik la:
- V1004 [CWE-476] Yo te itilize pwent 'Expr' la san danje apre li te verifye kont nullptr. Tcheke liy yo: 1049, 1078. DebugInfoMetadata.cpp 1078
- V1004 [CWE-476] Pointeur 'PI' a te itilize san danje apre li te verifye kont nullptr. Tcheke liy yo: 733, 753. LegacyPassManager.cpp 753
- V1004 [CWE-476] Yo te itilize pwent 'StatepointCall' an san danje apre li te verifye kont nullptr. Tcheke liy yo: 4371, 4379. Verifier.cpp 4379
- V1004 [CWE-476] Yo te itilize pwent 'RV' a san danje apre li te verifye kont nullptr. Tcheke liy yo: 2263, 2268. TGParser.cpp 2268
- V1004 [CWE-476] Pointeur 'CalleeFn' a te itilize san danje apre li te verifye kont nullptr. Tcheke liy yo: 1081, 1096. SimplifyLibCalls.cpp 1096
- V1004 [CWE-476] Yo te itilize pwent 'TC' a san danje apre li te verifye kont nullptr. Tcheke liy yo: 1819, 1824. Driver.cpp 1824
Fragman N48-N60: Pa kritik, men yon domaj (posib fuit memwa)
std::unique_ptr<IRMutator> createISelMutator() {
....
std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
Strategies.emplace_back(
new InjectorIRStrategy(InjectorIRStrategy::getDefaultOps()));
....
}
Avètisman PVS-Studio:
Pou ajoute yon eleman nan fen yon veso tankou std::vektè > ou pa ka jis ekri xxx.push_back (nouvo X), depi pa gen okenn konvèsyon implicite soti nan X* в std::unique_ptr.
Yon solisyon komen se ekri xxx.emplace_back(nouvo X)depi li konpile: metòd plase_tounen konstwi yon eleman ki soti dirèkteman nan agiman li yo epi li ka sèvi ak konstrukteur eksplisit.
Li pa an sekirite. Si vektè a plen, Lè sa a, memwa re-atribye. Operasyon reyallocation memwa a ka echwe, sa ki lakòz yon eksepsyon yo te jete std::bad_alloc. Nan ka sa a, konsèy la pral pèdi ak objè a kreye pa janm pral efase.
Yon solisyon san danje se kreye unique_ptrki pral posede konsèy la anvan vektè a eseye re-afèkte memwa:
xxx.push_back(std::unique_ptr<X>(new X))
Depi C++ 14, ou ka itilize 'std::make_unique':
xxx.push_back(std::make_unique<X>())
Kalite defo sa a pa kritik pou LLVM. Si memwa pa ka asiyen, du a ap tou senpleman sispann. Sepandan, pou aplikasyon ki gen lontan
Kidonk, byenke kòd sa a pa reprezante yon menas pratik pou LLVM, mwen te jwenn li itil pou m pale sou modèl erè sa a epi analizè PVS-Studio te aprann idantifye li.
Lòt avètisman nan kalite sa a:
- V1023 [CWE-460] Metòd 'emplace_back' yo ajoute yon pwent san pwopriyetè nan veso 'Passes' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. PassManager.h 546
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'AAs' pa metòd 'emplace_back' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. AliasAnalysis.h 324
- V1023 [CWE-460] Yo ajoute yon endikasyon san pwopriyetè nan veso 'Entries' pa metòd 'emplace_back' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. DWARFDebugFrame.cpp 519
- V1023 [CWE-460] Yo ajoute yon pointeur san pwopriyetè nan veso 'AllEdges' pa metòd 'emplace_back' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. CFGMST.h 268
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'VMaps' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. SimpleLoopUnswitch.cpp 2012
- V1023 [CWE-460] Yo ajoute yon endikasyon san pwopriyetè nan veso 'Dosye' yo pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. FDRLogBuilder.h 30
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'PendingSubmodules' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. ModuleMap.cpp 810
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Objè' pa metòd 'emplace_back' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. DebugMap.cpp 88
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Strategies' pa metòd 'emplace_back' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-isel-fuzzer.cpp 60
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 685
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 686
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 688
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 689
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 690
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 691
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 692
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 693
- V1023 [CWE-460] Yo ajoute yon konsèy san pwopriyetè nan veso 'Modifiers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. llvm-stress.cpp 694
- V1023 [CWE-460] Metòd 'emplace_back' yo ajoute yon konsèy san pwopriyetè nan veso 'Operands' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. GlobalISelEmitter.cpp 1911
- V1023 [CWE-460] Yo ajoute yon endikasyon san pwopriyetè nan veso 'Stash' pa metòd 'emplace_back' la. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. GlobalISelEmitter.cpp 2100
- V1023 [CWE-460] Yo ajoute yon pointeur san pwopriyetè nan veso 'Matchers' pa metòd 'emplace_back'. Yon flit memwa pral rive nan ka ta gen yon eksepsyon. GlobalISelEmitter.cpp 2702
Konklizyon
Mwen te bay 60 avètisman an total epi mwen te sispann. Èske gen lòt defo ke analizeur PVS-Studio la detekte nan LLVM? Wi mwen genyen. Sepandan, lè mwen t ap ekri fragman kòd pou atik la, li te byen ta nan aswè, oswa pito menm lannwit, epi mwen te deside ke li te tan yo rele li yon jou.
Mwen espere ou jwenn li enteresan epi ou pral vle eseye analizeur PVS-Studio la.
Ou ka telechaje analizeur a epi jwenn kle Minesweeper la nan
Sa ki pi enpòtan, sèvi ak analiz estatik regilyèman. Chèk yon sèl fwa, te pote soti nan nou yo nan lòd yo popilarize metodoloji nan analiz estatik ak PVS-Studio yo pa yon senaryo nòmal.
Bon chans nan amelyore kalite ak fyab nan kòd ou a!
Si ou vle pataje atik sa a ak yon odyans ki pale angle, tanpri itilize lyen tradiksyon an: Andrey Karpov.
Sous: www.habr.com