Fannt Bugs am LLVM 8 mam PVS-Studio Analyser

Fannt Bugs am LLVM 8 mam PVS-Studio Analyser
Méi wéi zwee Joer sinn zënter der leschter Codecheck vum LLVM-Projet vergaangen mat eisem PVS-Studio Analyser. Loosst eis sécher sinn datt de PVS-Studio Analyser nach ëmmer e féierende Tool ass fir Feeler a potenziell Schwachstelle z'identifizéieren. Fir dëst ze maachen, wäerte mir iwwerpréiwen an nei Feeler an der LLVM 8.0.0 Verëffentlechung fannen.

Artikel ze schreiwen

Fir éierlech ze sinn, wollt ech dësen Artikel net schreiwen. Et ass net interessant iwwer e Projet ze schreiwen dee mir scho e puer Mol gepréift hunn (1, 2, 3). Et ass besser iwwer eppes Neies ze schreiwen, awer ech hu keng Wiel.

All Kéier wann eng nei Versioun vum LLVM verëffentlecht oder aktualiséiert gëtt Clang Static Analyzer, mir kréien Froen vun der folgender Zort an eiser Mail:

Kuckt, déi nei Versioun vum Clang Static Analyzer huet geléiert nei Feeler ze fannen! Et schéngt mir datt d'Relevanz vum PVS-Studio ze benotzen erofgeet. Clang fënnt méi Feeler wéi virdrun an hëlt d'Fäegkeete vum PVS-Studio op. Wat haalt Dir dovunner?

Dorop wëll ech ëmmer eppes äntweren wéi:

Mir sëtze jo och net lass! Mir hunn d'Fäegkeete vum PVS-Studio Analyser wesentlech verbessert. Also maach der keng Suergen, mir féieren weider wéi virdrun.

Leider ass dëst eng schlecht Äntwert. Et gi keng Beweiser dran. An dofir schreiwen ech elo dësen Artikel. Also de LLVM-Projet gouf nach eng Kéier iwwerpréift an et goufe vill Feeler dran fonnt. Ech wäert elo déi weisen, déi mir interessant ausgesinn hunn. Clang Static Analyzer kann dës Feeler net fannen (oder et ass extrem onbequem et mat senger Hëllef ze maachen). Mee mir kënnen. Ausserdeem hunn ech all dës Feeler an engem Owend fonnt an opgeschriwwen.

Awer den Artikel schreiwen huet e puer Wochen gedauert. Ech konnt mech einfach net bréngen dëst alles an Text ze setzen :).

Iwwregens, wann Dir interesséiert sidd a wéi eng Technologien am PVS-Studio Analyser benotzt ginn fir Feeler a potenziell Schwachstelle z'identifizéieren, da proposéiere ech Iech mat dësem kennenzeléieren Note.

Nei an al Diagnostik

Wéi scho gesot, viru ronn zwee Joer gouf de Projet LLVM nach eng Kéier iwwerpréift an déi fonnte Feeler korrigéiert. Elo wäert dësen Artikel eng nei Partie vu Feeler presentéieren. Firwat goufen nei Bugs fonnt? Et ginn 3 Grënn dofir:

  1. De LLVM Projet entwéckelt sech, ännert alen Code an setzt neie Code derbäi. Natierlech ginn et nei Feeler am geännerten a schrëftleche Code. Dëst weist kloer datt statesch Analyse regelméisseg benotzt soll ginn, an net heiansdo. Eis Artikelen weisen gutt d'Fähigkeiten vum PVS-Studio Analyser, awer dëst huet näischt mat der Verbesserung vun der Codequalitéit an d'Reduktioun vun de Käschte fir Feeler ze fixéieren. Benotzt e statesche Code Analyser regelméisseg!
  2. Mir finaliséieren a verbesseren existent Diagnostik. Dofir kann den Analysator Feeler identifizéieren déi hien net während de fréiere Scans gemierkt huet.
  3. Nei Diagnostik sinn am PVS-Studio opgetaucht déi virun 2 Joer net existéiert huet. Ech hu beschloss se an enger separater Sektioun ze markéieren fir d'Entwécklung vum PVS-Studio kloer ze weisen.

Mängel identifizéiert duerch Diagnostik déi virun 2 Joer existéiert

Fragment N1: Copy-Paste

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
  ....
}

PVS-Studio Warnung: V501 [CWE-570] Et gi identesch Ënnerausdréck 'Name.startswith ("avx512.mask.permvar.")' lénks a riets vum '||' Bedreiwer. AutoUpgrade.cpp 73

Et gëtt duebel kontrolléiert datt den Numm mat der Ënnerstring "avx512.mask.permvar." ufänkt. Am zweete Scheck wollte se selbstverständlech nach eppes schreiwen, awer hu vergiess de kopéierten Text ze korrigéieren.

Fragment N2: Tippfeeler

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;
  ....
}

Warnung PVS-Studio: V501 Et gi identesch Ënnerausdréck 'CXNameRange_WantQualifier' lénks a riets vum '|' Bedreiwer. CIndex.cpp 7245

Wéinst engem Tippfeeler gëtt déi selwecht genannte Konstant zweemol benotzt CXNameRange_WantQualifier.

Fragment N3: Duercherneen mat Bedreiwer Virsprong

int PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
  ....
  if (ISD == ISD::EXTRACT_VECTOR_ELT && Index == ST->isLittleEndian() ? 1 : 0)
    return 0;
  ....
}

PVS-Studio Warnung: V502 [CWE-783] Vläicht funktionnéiert den '?:' Bedreiwer op eng aner Manéier wéi et erwaart gouf. Den '?:' Bedreiwer huet eng méi niddereg Prioritéit wéi den '==' Bedreiwer. PPCTargetTransformInfo.cpp 404

Menger Meenung no ass dat e ganz schéine Feeler. Jo, ech weess, ech hunn komesch Iddien iwwer Schéinheet :).

Elo, laut Operateur Prioritéit, gëtt den Ausdrock wéi follegt bewäert:

(ISD == ISD::EXTRACT_VECTOR_ELT && (Index == ST->isLittleEndian())) ? 1 : 0

Aus enger praktescher Siicht mécht sou eng Bedingung kee Sënn, well et ka reduzéiert ginn op:

(ISD == ISD::EXTRACT_VECTOR_ELT && Index == ST->isLittleEndian())

Dëst ass e kloere Feeler. Wahrscheinlech wollte se 0/1 mat enger Variabel vergläichen Index. Fir de Code ze fixéieren musst Dir Klammeren ronderëm den ternäre Bedreiwer addéieren:

if (ISD == ISD::EXTRACT_VECTOR_ELT && Index == (ST->isLittleEndian() ? 1 : 0))

Iwwregens, ass den ternäre Bedreiwer ganz geféierlech a provozéiert logesch Feeler. Sidd ganz virsiichteg domatter a sidd net gourmandseg mat Klammern. Ech hunn dëst Thema méi detailléiert gekuckt hei, am Kapitel "Opgepasst virum ?: Bedreiwer a schléisst et an Klammern."

Fragment N4, N5: Nullpointer

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;
  }
  ....
}

PVS-Studio Warnung: V522 [CWE-476] D'Dereferenzéierung vum Nullpointer 'LHS' ka stattfannen. TGParser.cpp 2152

Wann de Pointer LHS ass null, eng Warnung soll ausgestallt ginn. Wéi och ëmmer, amplaz gëtt dee selwechte Null-Zeiger ofgeleent: LHS->getAsString().

Dëst ass eng ganz typesch Situatioun wann e Feeler an engem Feeler Handler verstoppt ass, well keen se testt. Statesch Analysatoren kontrolléieren all erreechbar Code, egal wéi dacks et benotzt gëtt. Dëst ass e ganz gutt Beispill vu wéi statesch Analyse aner Tester a Feelerschutztechniken ergänzt.

Ähnlech Zeigefangerfehler RHS erlaabt am Code just drënner: V522 [CWE-476] D'Dereferenzéierung vum Nullpointer 'RHS' ka stattfannen. TGParser.cpp 2186

Fragment N6: Benotzt de Pointer no der Bewegung

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);
  }
  ....
}

PVS-Studio Warnung: V522 [CWE-476] D'Dereferenzéierung vum Nullpointer 'ProgClone' ka stattfannen. Miscompilation.cpp 601

Am Ufank e Smart Pointer ProgClone hält op den Objet ze besëtzen:

BD.setNewProgram(std::move(ProgClone));

Tatsächlech, elo ProgClone ass en null Zeechner. Dofir sollt eng Null-Zeiger-Dereferenz just ënnert geschéien:

Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);

Awer a Wierklechkeet wäert dëst net geschéien! Notéiert datt d'Loop net tatsächlech ausgefouert gëtt.

Am Ufank vum Container Miskompiléiert Funktiounen geläscht:

MiscompiledFunctions.clear();

Als nächst gëtt d'Gréisst vun dësem Container am Loopbedingung benotzt:

for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {

Et ass einfach ze gesinn datt d'Loop net ufänkt. Ech mengen dat ass och e Feeler an de Code soll anescht geschriwwe ginn.

Et schéngt, datt mir déi berühmt Paritéit vu Feeler begéint hunn! Ee Feeler maskéiert en aneren :).

Fragment N7: Benotzt de Pointer no der Bewegung

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;
  }
  ....
}

PVS-Studio Warnung: V522 [CWE-476] D'Dereferenzéierung vum Nullpointer 'Test' kéint stattfannen. Miscompilation.cpp 709

Déi selwecht Situatioun erëm. Fir d'éischt gëtt den Inhalt vum Objet geréckelt, an duerno gëtt et benotzt wéi wann näischt geschitt wier. Ech gesinn dës Situatioun ëmmer méi dacks am Programmcode nodeems d'Bewegungssemantik am C ++ opgetaucht ass. Dofir hunn ech d'C++ Sprooch gär! Et gi méi a méi nei Weeër fir Äert eegent Been of ze schéissen. De PVS-Studio Analyser wäert ëmmer Aarbecht hunn :).

Fragment N8: Null Pointer

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);
}

PVS-Studio Warnung: V522 [CWE-476] D'Dereferenzéierung vum Nullpointer 'Typ' ka stattfannen. PrettyFunctionDumper.cpp 233

Zousätzlech zu Fehlerhandterer ginn d'Debugging-Drockfunktiounen normalerweis net getest. Mir hu grad esou e Fall virun eis. D'Funktioun waart op de Benotzer, deen amplaz seng Probleemer ze léisen gezwongen ass et ze fixéieren.

Richteg:

if (Type)
  Type->dump(*this);
else
  Printer << "<unknown-type>";

Fragment N9: Null Pointer

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());
   ....
}

PVS-Studio Warnung: V522 [CWE-476] D'Dereferenzéierung vum Null-Zeiger 'Ty' ka stattfannen. SearchableTableEmitter.cpp 614

Ech mengen alles ass kloer a brauch keng Erklärung.

Fragment N10: Tippfeeler

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;
}

PVS-Studio Warnung: V570 D'Variabel 'Identifier->Typ' gëtt u sech selwer zougewisen. FormatTokenLexer.cpp 249

Et ass kee Sënn fir eng Variabel fir sech selwer ze ginn. Wahrscheinlech wollte se schreiwen:

Identifier->Type = Question->Type;

Fragment N11: Verdächteg Paus

void SystemZOperand::print(raw_ostream &OS) const {
  switch (Kind) {
    break;
  case KindToken:
    OS << "Token:" << getToken();
    break;
  case KindReg:
    OS << "Reg:" << SystemZInstPrinter::getRegisterName(getReg());
    break;
  ....
}

PVS-Studio Warnung: V622 [CWE-478] Betruecht d''Switch' Ausso ze inspizeéieren. Et ass méiglech datt den éischte "Fall" Bedreiwer fehlt. SystemZAsmParser.cpp 652

Et gëtt e ganz verdächtege Bedreiwer am Ufank briechen. Hutt Dir vergiess eppes anescht hei ze schreiwen?

Fragment N12: Iwwerpréift vun engem Zeigefanger no der dereferencing

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");
  ....
}

PVS-Studio Warnung: V595 [CWE-476] De 'Callee' Pointer gouf benotzt ier et géint nullptr verifizéiert gouf. Kontrolllinnen: 172, 174. AMDGPUInline.cpp 172

Den Index Callee am Ufank gëtt derreferenzéiert zur Zäit wou d'Funktioun genannt gëtt getTTI.

An da stellt sech eraus, datt dëse Pointer op Gläichheet kontrolléiert soll ginn nullptr:

if (!Callee || Callee->isDeclaration())

Awer et ass ze spéit ...

Fragment N13 - N...: Iwwerpréift vun engem Zeigefanger nom Oflehnung

D'Situatioun, déi am virege Codefragment diskutéiert gouf, ass net eenzegaarteg. Et erschéngt hei:

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()) {               // <=
  ....
}

PVS-Studio Warnung: V595 [CWE-476] De 'CalleeFn' Zeiger gouf benotzt ier et géint nullptr verifizéiert gouf. Check Linnen: 1079, 1081. SimplifyLibCalls.cpp 1079

An hei:

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());     // <=
  ....
}

PVS-Studio Warnung: V595 [CWE-476] Den 'ND' Zeiger gouf benotzt ier et géint nullptr verifizéiert gouf. Kontrolllinnen: 532, 534. SemaTemplateInstantiateDecl.cpp 532

An hei:

  • V595 [CWE-476] Den 'U' Zeiger gouf benotzt ier et géint nullptr verifizéiert gouf. Kontroll Linnen: 404, 407. DWARFormValue.cpp 404
  • V595 [CWE-476] Den 'ND' Pointer gouf benotzt ier et géint nullptr verifizéiert gouf. Kontrolllinnen: 2149, 2151. SemaTemplateInstantiate.cpp 2149

An dunn hunn ech mech net interesséiert fir d'Warnungen mat der Nummer V595 ze studéieren. Also ech weess net ob et méi ähnlech Feeler nieft deenen hei opgelëscht sinn. Wahrscheinlech gëtt et.

Fragment N17, N18: Verdächteg Verréckelung

static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize,
                                           uint64_t &Encoding) {
  ....
  unsigned Size = RegSize;
  ....
  uint64_t NImms = ~(Size-1) << 1;
  ....
}

PVS-Studio Warnung: V629 [CWE-190] Betruecht den '~(Gréisst - 1) << 1' Ausdrock z'inspektéieren. Bit Verréckelung vum 32-Bit Wäert mat enger spéider Expansioun op den 64-Bit Typ. AArch64AddressingModes.h 260

Et kann net e Feeler sinn an de Code funktionnéiert genau wéi virgesinn. Awer dëst ass kloer eng ganz verdächteg Plaz a muss iwwerpréift ginn.

Loosst eis d'Variabel soen Gréisst ass gläich wéi 16, an dann huet den Auteur vum Code geplangt et an enger Variabel ze kréien NImms Wert:

1111111111111111111111111111111111111111111111111111111111100000

Wéi och ëmmer, a Wierklechkeet wäert d'Resultat sinn:

0000000000000000000000000000000011111111111111111111111111100000

D'Tatsaach ass datt all Berechnunge mat dem 32-Bit net ënnerschriwwenen Typ geschéien. An nëmmen dann gëtt dësen 32-Bit net ënnerschriwwenen Typ implizit erweidert op uint64_t. An dësem Fall sinn déi bedeitendst Stécker null.

Dir kënnt d'Situatioun esou fixéieren:

uint64_t NImms = ~static_cast<uint64_t>(Size-1) << 1;

Ähnlech Situatioun: V629 [CWE-190] Betruecht den 'Immr << 6' Ausdrock ze kontrolléieren. Bit Verréckelung vum 32-Bit Wäert mat enger spéider Expansioun op den 64-Bit Typ. AArch64AdressingModes.h 269

Fragment N19: Vermësst Schlësselwuert aneren?

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");
  }
  ....
}

PVS-Studio Warnung: V646 [CWE-670] Betruecht d'Logik vun der Applikatioun z'inspektéieren. Et ass méiglech datt d'Schlësselwuert "aner" fehlt. AMDGPPUAsmParser.cpp 5655

Et gëtt kee Feeler hei. Zënter dem deemolegen Block vun der éischter if endet mat weider, dann ass et egal, et gëtt e Schlësselwuert aneren oder nët. Egal wéi de Code funktionnéiert d'selwecht. Nach ëmmer verpasst aneren mécht de Code méi onkloer a geféierlech. Wann an Zukunft weider verschwënnt, fänkt de Code komplett anescht ze schaffen. Menger Meenung no ass et besser ze addéieren aneren.

Fragment N20: Véier Tippfehler vum selwechten Typ

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;
}

PVS-Studio Warnungen:

  • V655 [CWE-480] D'Saiten goufen zesummegefaasst awer ginn net benotzt. Betruecht d'Inspektioun vum 'Resultat + Name.str()' Ausdrock. Symbol.cpp 32
  • V655 [CWE-480] D'Saiten goufen zesummegefaasst awer ginn net benotzt. Betruecht d'Inspektioun vum 'Resultat + "(ObjC Class)" + Name.str()' Ausdrock. Symbol.cpp 35
  • V655 [CWE-480] D'Saiten goufen zesummegefaasst awer ginn net benotzt. Betruecht d'Inspektioun vum 'Resultat + "(ObjC Class EH) " + Name.str()' Ausdrock. Symbol.cpp 38
  • V655 [CWE-480] D'Saiten goufen zesummegefaasst awer ginn net benotzt. Betruecht d'Inspektioun vum 'Resultat + "(ObjC IVar)" + Name.str()' Ausdrock. Symbol.cpp 41

Duerch Zoufall gëtt den + Bedreiwer benotzt amplaz vum += Bedreiwer. D'Resultat ass Designen déi ouni Bedeitung sinn.

Fragment N21: Ondefinéiert Verhalen

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();
    }
  }
}

Probéiert de geféierleche Code selwer ze fannen. An dëst ass e Bild fir d'Opmierksamkeet ze distractéieren fir net direkt d'Äntwert ze kucken:

Fannt Bugs am LLVM 8 mam PVS-Studio Analyser

PVS-Studio Warnung: V708 [CWE-758] Geféierlech Konstruktioun gëtt benotzt: 'FeaturesMap[Op] = FeaturesMap.size()', wou 'FeaturesMap' vun der 'Kaart' Klass ass. Dëst kann zu ondefinéiert Verhalen féieren. RISCVCompressInstEmitter.cpp 490

Problem Linn:

FeaturesMap[Op] = FeaturesMap.size();

Wann Element Op net fonnt gëtt, da gëtt en neit Element op der Kaart erstallt an d'Zuel vun den Elementer op dëser Kaart gëtt do geschriwwen. Et ass just onbekannt ob d'Funktioun genannt gëtt Gréisst virun oder no engem neien Element derbäigesat.

Fragment N22-N24: Widderholl Aufgaben

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;
  }
  ....
}

PVS-Studio Warnung: V519 [CWE-563] D'NType Variabel gëtt zweemol successiv Wäerter zougewisen. Vläicht ass dëst e Feeler. Check Linnen: 1663, 1664. MachOObjectFile.cpp 1664

Ech mengen net, datt hei e richtege Feeler ass. Just eng onnéideg widderholl Aufgab. Awer nach ëmmer e Feeler.

Zerfall:

  • V519 [CWE-563] D'B.NDesc Variabel gëtt zweemol successiv Wäerter zougewisen. Vläicht ass dëst e Feeler. Check Linnen: 1488, 1489. llvm-nm.cpp 1489
  • V519 [CWE-563] D'Variabel gëtt zweemol successiv Wäerter zougewisen. Vläicht ass dëst e Feeler. Kontroll Linnen: 59, 61. coff2yaml.cpp 61

Fragment N25-N27: Méi reassignment

Loosst eis elo eng liicht aner Versioun vun der Ëmsetzung kucken.

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;
  ....
}

PVS-Studio Warnung: V519 [CWE-563] D'Alignment Variabel gëtt zweemol successiv Wäerter zougewisen. Vläicht ass dëst e Feeler. Check Linnen: 1158, 1160. LoadStoreVectorizer.cpp 1160

Dëst ass ganz komesch Code deen anscheinend e logesche Feeler enthält. Am Ufank, variabel Formatioun e Wäert gëtt jee no der Bedingung zougewisen. An da kënnt d'Aufgab erëm, awer elo ouni Scheck.

Ähnlech Situatioune kënnen hei gesi ginn:

  • V519 [CWE-563] D''Effekter' Variabel gëtt zweemol successiv Wäerter zougewisen. Vläicht ass dëst e Feeler. Kontrolllinnen: 152, 165. WebAssemblyRegStackify.cpp 165
  • V519 [CWE-563] D'Variabel 'ExpectNoDerefChunk' gëtt zweemol successiv Wäerter zougewisen. Vläicht ass dëst e Feeler. Kontroll Linnen: 4970, 4973. SemaType.cpp 4973

Fragment N28: Ëmmer richteg Zoustand

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;
  }
  ....
}

PVS-Studio Warnung: V547 [CWE-571] Ausdrock 'nextByte != 0x90' ass ëmmer wouer. X86DisassemblerDecoder.cpp 379

Iwwerpréift mécht kee Sënn. Variabel nächstByte ëmmer net gläich mam Wäert 0x90, déi aus der viregter Scheck kënnt. Dëst ass eng Aart vu logesche Feeler.

Fragment N29 - N...: Ëmmer wouer/falsch Konditiounen

Den Analysator gëtt vill Warnungen eraus datt de ganzen Zoustand (V547) oder en Deel dovun (V560) ass ëmmer richteg oder falsch. Dacks sinn dat keng richteg Feeler, mee einfach sloppy Code, d'Resultat vun Makro Expansioun, an dergläiche. Wéi och ëmmer, et mécht Sënn fir all dës Warnungen ze kucken, well echt logesch Feeler vun Zäit zu Zäit optrieden. Zum Beispill ass dës Sektioun vum Code verdächteg:

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;
  ....
}

PVS-Studio Warnung: V560 [CWE-570] En Deel vum bedingten Ausdrock ass ëmmer falsch: RegNo == 0xe. ARMDisassembler.cpp 939

De konstante 0xE ass de Wäert 14 an Dezimal. Examen RegNo == 0xe mécht kee Sënn well wann RegNo > 13, da wäert d'Funktioun seng Ausféierung fäerdeg maachen.

Et waren vill aner Warnungen mat IDen V547 an V560, mee wéi mat V595, Ech war net interesséiert dës Warnungen ze studéieren. Et war scho kloer datt ech genuch Material hat fir en Artikel ze schreiwen :). Dofir ass et onbekannt wéi vill Feeler vun dësem Typ am LLVM mat PVS-Studio identifizéiert kënne ginn.

Ech ginn Iech e Beispill firwat dës Ausléiser studéieren langweileg ass. Den Analyser ass absolut richteg fir eng Warnung fir de folgende Code auszeginn. Awer dëst ass kee Feeler.

bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
                                          tok::TokenKind ClosingBraceKind) {
  bool HasError = false;
  ....
  HasError = true;
  if (!ContinueOnSemicolons)
    return !HasError;
  ....
}

PVS-Studio Warnung: V547 [CWE-570] Ausdrock '!HasError' ass ëmmer falsch. UnwrappedLineParser.cpp 1635

Fragment N30: ​​Verdächteg zréck

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();
  }
  ....
}

PVS-Studio Warnung: V612 [CWE-670] En bedingungslosen 'Retour' bannent enger Loop. R600OptimizeVectorRegisters.cpp 63

Dëst ass entweder e Feeler oder eng spezifesch Technik déi geduecht ass fir Programméierer eppes z'erklären, déi de Code liesen. Dësen Design erklärt mir näischt a gesäit ganz verdächteg aus. Et ass besser net esou ze schreiwen :).

Midd? Dann ass et Zäit fir Téi oder Kaffi ze maachen.

Fannt Bugs am LLVM 8 mam PVS-Studio Analyser

Mängel identifizéiert duerch nei Diagnostik

Ech mengen 30 Aktivatioune vun aler Diagnostik ass genuch. Loosst eis elo kucken wat interessant Saache kënne mat der neier Diagnostik fonnt ginn, déi duerno am Analyser opgetaucht ass virdrun Schecken. Wärend dëser Zäit goufen am Ganzen 66 allgemeng Zweck Diagnostik an den C ++ Analyser bäigefüügt.

Fragment N31: Unreachable Code

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();
}

PVS-Studio Warnung: V779 [CWE-561] Onerreechbare Code entdeckt. Et ass méiglech datt e Feeler präsent ass. ExecutionUtils.cpp 146

Wéi Dir gesitt, béid Secteuren vum Bedreiwer if endet mat engem Opruff un den Bedreiwer zréck. Deementspriechend de Container CtorDtorsByPriority wäert ni geläscht ginn.

Fragment N32: Unreachable Code

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;
}

PVS-Studio Warnung: V779 [CWE-561] Unreachable Code entdeckt. Et ass méiglech datt e Feeler präsent ass. LLParser.cpp 835

Interessant Situatioun. Loosst eis dës Plaz als éischt kucken:

return ParseTypeIdEntry(SummaryID);
break;

Op den éischte Bléck schéngt et datt hei kee Feeler ass. Et gesäit aus wéi de Bedreiwer briechen et gëtt eng extra hei, an Dir kënnt et einfach läschen. Wéi och ëmmer, net all sou einfach.

Den Analyser gëtt eng Warnung op de Linnen:

Lex.setIgnoreColonInIdentifiers(false);
return false;

An tatsächlech ass dëse Code net erreechbar. All Fäll an Wiesselen endet mat engem Uruff vum Bedreiwer zréck. An elo sënnlos alleng briechen gesäit net sou harmlos aus! Vläicht sollt ee vun de Branchen mat ophalen briechen, net un zréck?

Fragment N33: Zoufälleg zréckgesat héich Stécker

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);
  ....
}

PVS-Studio Warnung: V784 D'Gréisst vun der Bit Mask ass manner wéi d'Gréisst vum éischten Operand. Dëst wäert de Verloscht vu méi héije Bits verursaachen. RuntimeDyld.cpp 815

Maacht weg datt d'Funktioun getStubAlignment zréck Typ net ënnerschriwwen. Loosst eis de Wäert vum Ausdrock berechnen, unzehuelen datt d'Funktioun de Wäert 8 zréckkënnt:

~(getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

Elo bemierkt datt d'Variabel Daten Gréisst huet e 64-Bit net ënnerschriwwenen Typ. Et stellt sech eraus datt wann Dir d'DataSize & 0xFFFFFFF8u Operatioun ausféiert, all zweedrësseg High-Order Bits op Null zréckgesat ginn. Wahrscheinlech ass dat net wat de Programméierer wollt. Ech de Verdacht, datt hie wollt berechnen: DataSize & 0xFFFFFFFFFFFFFFFFF8u.

Fir de Feeler ze fixéieren, sollt Dir dëst schreiwen:

DataSize &= ~(static_cast<uint64_t>(getStubAlignment()) - 1);

Oder sou:

DataSize &= ~(getStubAlignment() - 1ULL);

Fragment N34: Ausgefall explizit Typ Goss

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);
  ....
}

PVS-Studio Warnung: V1028 [CWE-190] Méiglech Iwwerschwemmung. Betruecht Casting Operander vum 'NumElts * Skala' Bedreiwer op den Typ 'size_t', net d'Resultat. X86ISelLowering.h 1577

Explizit Typ Casting gëtt benotzt fir Iwwerschwemmung ze vermeiden wann Dir Typvariablen multiplizéiert INT. Wéi och ëmmer, explizit Typ Casting hei schützt net géint Iwwerschwemmung. Als éischt ginn d'Variabelen multiplizéiert, a nëmmen dann gëtt d'32-Bit Resultat vun der Multiplikatioun op d'Typ erweidert Gréisst_t.

Fragment N35: Ausgefall Copy-Paste

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;
  }
  ....
}

V778 [CWE-682] Zwee ähnlech Code Fragmenter goufen fonnt. Vläicht ass dëst en Tippfeeler an 'Op1' Variabel soll amplaz vun 'Op0' benotzt ginn. InstCombineCompares.cpp 5507

Dës nei interessant Diagnostik identifizéiert Situatiounen wou e Stéck Code kopéiert gouf an e puer Nimm dran ugefaang hunn ze änneren, awer op enger Plaz hunn se et net korrigéiert.

Maacht weg datt se am zweete Block geännert hunn op 0 op op 1. Awer op enger Plaz hunn se et net fixéiert. Wahrscheinlech sollt et esou geschriwwe ginn:

if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
  I.setOperand(1, ConstantFP::getNullValue(Op1->getType()));
  return &I;
}

Fragment N36: Variabel Duercherneen

struct Status {
  unsigned Mask;
  unsigned Mode;

  Status() : Mask(0), Mode(0){};

  Status(unsigned Mask, unsigned Mode) : Mask(Mask), Mode(Mode) {
    Mode &= Mask;
  };
  ....
};

PVS-Studio Warnung: V1001 [CWE-563] D'Modus Variabel ass zougewisen awer gëtt net um Enn vun der Funktioun benotzt. SIModeRegister.cpp 48

Et ass ganz geféierlech fir Funktiounsargumenter déiselwecht Nimm ze ginn wéi Klassememberen. Et ass ganz einfach duercherneen ze ginn. Mir hu grad esou e Fall virun eis. Dësen Ausdrock mécht kee Sënn:

Mode &= Mask;

D'Funktioun Argument Ännerungen. Dat ass alles. Dëst Argument gëtt net méi benotzt. Wahrscheinlech hätt Dir et esou geschriwwen:

Status(unsigned Mask, unsigned Mode) : Mask(Mask), Mode(Mode) {
  this->Mode &= Mask;
};

Fragment N37: Variabel Duercherneen

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;
}

Warnung PVS-Studio: V1001 [CWE-563] D''Gréisst' Variabel ass zougewisen awer gëtt net um Enn vun der Funktioun benotzt. Object.cpp 424

D'Situatioun ass ähnlech wéi déi virdrun. Et soll geschriwwe ginn:

this->Size += this->EntrySize;

Fragment N38-N47: Si hu vergiess den Index ze kontrolléieren

Virdrun hu mir Beispiller vu diagnostesche Ausléiser gekuckt V595. Seng Essenz ass datt de Pointer am Ufank dereferenzéiert gëtt, an nëmmen dann iwwerpréift. Jonk Diagnostik V1004 ass de Géigendeel am Sënn, awer weist och vill Feeler. Et identifizéiert Situatiounen wou de Pointer am Ufank gepréift gouf an duerno vergiess huet dat ze maachen. Loosst eis esou Fäll kucken, déi am LLVM fonnt goufen.

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());  // <=
  ....
}

PVS-Studio Warnung: V1004 [CWE-476] De 'Ptr' Zeiger gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Check Linnen: 729, 738. TargetTransformInfoImpl.h 738

Variabel Ptr kann gläich sinn nullptr, wéi de Scheck beweist:

if (Ptr != nullptr)

Wéi och ëmmer, ënner dësem Zeeche gëtt ouni virleefeg Kontroll ofgeleent:

auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType());

Loosst eis en aneren ähnleche Fall betruechten.

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(); // <=
  ....
}

PVS-Studio Warnung: V1004 [CWE-476] De 'FD' Zeiger gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Check Linnen: 3228, 3231. CGDebugInfo.cpp 3231

Opgepasst op d'Schëld FD. Ech si sécher datt de Problem kloer sichtbar ass a keng speziell Erklärung erfuerderlech ass.

A weider:

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());     // <=
  ....
}

PVS-Studio Warnung: V1004 [CWE-476] De 'PtrTy' Zeiger gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Kontroll Linnen: 960, 965. InterleavedLoadCombinePass.cpp 965

Wéi schützt Dir Iech vu sou Feeler? Sidd méi opmierksam op Code-Review a benotzt den PVS-Studio statesche Analyser fir regelméisseg Äre Code z'iwwerpréiwen.

Et gëtt kee Sënn aner Code Fragmenter mat Feeler vun dësem Typ ze zitéieren. Ech verloossen nëmmen eng Lëscht vun Warnungen am Artikel:

  • V1004 [CWE-476] Den 'Expr' Pointer gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Kontroll Linnen: 1049, 1078. DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] De 'PI' Pointer gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Kontroll Linnen: 733, 753. LegacyPassManager.cpp 753
  • V1004 [CWE-476] Den 'StatepointCall' Zeiger gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Kontroll Linnen: 4371, 4379. Verifier.cpp 4379
  • V1004 [CWE-476] Den 'RV' Zeiger gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Check Linnen: 2263, 2268. TGParser.cpp 2268
  • V1004 [CWE-476] De 'CalleeFn' Pointer gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Check Linnen: 1081, 1096. SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] Den 'TC' Pointer gouf onsécher benotzt nodeems et géint nullptr verifizéiert gouf. Kontroll Linnen: 1819, 1824. Driver.cpp 1824

Fragment N48-N60: Net kritesch, awer e Defekt (méiglecher Erënnerungslek)

std::unique_ptr<IRMutator> createISelMutator() {
  ....
  std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
  Strategies.emplace_back(
      new InjectorIRStrategy(InjectorIRStrategy::getDefaultOps()));
  ....
}

PVS-Studio Warnung: V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an de 'Strategien' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-isel-fuzzer.cpp 58

Fir en Element um Enn vun engem Container ze addéieren wéi std :: vektor > du kanns net einfach schreiwen xxx.push_back(nei X), well et keng implizit Konversioun vun X* в std::unique_ptr.

Eng gemeinsam Léisung ass ze schreiwen xxx.emplace_back(nei X)well et kompiléiert: Method emplace_back konstruéiert en Element direkt aus sengen Argumenter a kann dofir explizit Konstruktoren benotzen.

Et ass net sécher. Wann de Vektor voll ass, da gëtt d'Erënnerung nei zougewisen. D'Erënnerung Ëmverdeelungsoperatioun kann ausfalen, wat zu enger Ausnahm gefouert gëtt std::bad_alloc. An dësem Fall gëtt de Pointer verluer an de geschafenen Objet gëtt ni geläscht.

Eng sécher Léisung ass ze schafen eenzegaarteg_ptrdeen de Pointer besëtzt ier de Vektor probéiert d'Erënnerung ëmzegoen:

xxx.push_back(std::unique_ptr<X>(new X))

Zënter C++14 kënnt Dir 'std::make_unique' benotzen:

xxx.push_back(std::make_unique<X>())

Dës Zort Defekt ass net kritesch fir LLVM. Wann d'Erënnerung net zougewisen ka ginn, stoppt de Compiler einfach. Wéi och ëmmer, fir Uwendungen mat laanger uptime, déi net nëmmen ophalen kann wann d'Erënnerungsallokatioun feelt, dëst kann e richtege béise Feeler sinn.

Also, obwuel dëse Code keng praktesch Bedrohung fir LLVM duerstellt, hunn ech et nëtzlech fonnt iwwer dëst Feelermuster ze schwätzen an datt de PVS-Studio Analyser geléiert huet et z'identifizéieren.

Aner Warnungen vun dësem Typ:

  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an de 'Passes' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. PassManager.h 546
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'AAs' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. AliasAnalysis.h 324
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Entries' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'AllEdges' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. CFGMST.h 268
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'VMaps' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. SimpleLoopUswitch.cpp 2012
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Records' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. FDRLogBuilder.h 30
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'PendingSubmodules' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. ModuleMap.cpp 810
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Objekte' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. DebugMap.cpp 88
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Strategien' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 685
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 686
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 688
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 689
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 690
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 691
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 692
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 693
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Modifiers' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. llvm-stress.cpp 694
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Operands' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an den 'Stash' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] E Pointer ouni Besëtzer gëtt an de 'Matcher' Container mat der 'emplace_back' Method bäigefüügt. E Gedächtnisleck wäert am Fall vun enger Ausnam optrieden. GlobalISelEmitter.cpp 2702

Konklusioun

Ech hunn am Ganzen 60 Warnungen erausginn an dunn opgehalen. Ginn et aner Mängel déi de PVS-Studio Analyser am LLVM erkennt? Jo ech hunn. Wéi och ëmmer, wann ech Code Fragmenter fir den Artikel geschriwwen hunn, war et spéiden Owend, oder éischter souguer Nuecht, an ech hunn decidéiert datt et Zäit wier et en Dag ze nennen.

Ech hoffen Dir hutt et interessant fonnt a wëllt de PVS-Studio Analyser probéieren.

Dir kënnt den Analyser eroflueden an de Minesweeper Schlëssel op dës Säit.

Virun allem, benotzt regelméisseg statesch Analyse. Eemol Schecken, vun eis duerchgefouert fir d'Methodologie vun der statescher Analyse ze populariséieren an PVS-Studio sinn net en normale Szenario.

Vill Gléck fir d'Qualitéit an Zouverlässegkeet vun Ärem Code ze verbesseren!

Fannt Bugs am LLVM 8 mam PVS-Studio Analyser

Wann Dir dësen Artikel mat engem engleschsproochege Publikum wëllt deelen, benotzt w.e.g. den Iwwersetzungslink: Andrey Karpov. Fannen Bugs am LLVM 8 mat PVS-Studio.

Source: will.com

Setzt e Commentaire