Bi karanîna analîzera PVS-Studio di LLVM 8 de xeletiyan bibînin

Bi karanîna analîzera PVS-Studio di LLVM 8 de xeletiyan bibînin
Zêdetirî du sal di ser kontrolkirina kodê ya paşîn a projeya LLVM re bi karanîna analîzera meya PVS-Studio re derbas bûne. Ka em pê ewle bin ku analyzera PVS-Studio hîn jî amûrek pêşeng e ji bo tespîtkirina xeletî û qelsiyên potansiyel. Ji bo vê yekê, em ê di berdana LLVM 8.0.0 de xeletiyên nû kontrol bikin û bibînin.

Gotar bê nivîsandin

Bi rastî, min nexwest vê gotarê binivîsim. Ne balkêş e ku meriv li ser projeyek ku me berê çend caran kontrol kiriye binivîse (1, 2, 3). Çêtir e ku meriv li ser tiştek nû binivîsîne, lê bijartina min tune.

Her carê ku guhertoyek nû ya LLVM tê berdan an nûvekirin Clang Static Analyzer, em di nameya xwe de pirsên bi vî rengî distînin:

Binêrin, guhertoya nû ya Clang Static Analyzer fêr bûye ku xeletiyên nû bibîne! Ji min re xuya dike ku têkiliya karanîna PVS-Studio kêm dibe. Clang ji berê bêtir xeletiyan dibîne û bi kapasîteyên PVS-Studio digire. Hûn li ser vê yekê çi difikirin?

Li ser vê yekê ez her gav dixwazim bersivek weha bidim:

Em jî bêkar rûnin! Me kapasîteyên analîzkerê PVS-Studio bi girîngî çêtir kiriye. Ji ber vê yekê xem neke, em wekî berê pêşengiyê dikin.

Mixabin, ev bersivek xirab e. Di wê de tu delîl tune. Û ji ber vê yekê ez niha vê gotarê dinivîsim. Ji ber vê yekê, projeya LLVM careke din hate kontrol kirin û cûrbecûr xeletî tê de hatine dîtin. Ez ê niha yên ku ji min re balkêş xuya bûn destnîşan bikim. Clang Static Analyzer nikare van xeletiyan bibîne (an jî pir nerehet e ku meriv wiya bi alîkariya wê bike). Lê em dikarin. Wekî din, min ev hemû xeletî di yek êvarê de dîtin û nivîsandin.

Lê nivîsandina gotarê çend hefte girt. Min tenê nikarîbû xwe ragirim ku ez van hemîyan binivîsim :).

Bi awayê, heke hûn bala we dikişînin ku çi teknolojiyên di analîzera PVS-Studio de têne bikar anîn da ku xeletî û qelsiyên potansiyel nas bikin, wê hingê ez pêşniyar dikim ku hûn bi vê yekê re nas bikin. not.

Teşhîsên nû û kevn

Wekî ku berê hate destnîşan kirin, nêzî du sal berê projeya LLVM careke din hate kontrol kirin, û xeletiyên hatine dîtin hatine rast kirin. Naha ev gotar dê komek nû ya xeletiyan pêşkêşî bike. Çima xeletiyên nû hatin dîtin? 3 sedemên vê hene:

  1. Projeya LLVM pêşve diçe, koda kevn diguhezîne û koda nû lê zêde dike. Bi xwezayî, di koda guherandin û nivîsandinê de xeletiyên nû hene. Ev bi zelalî destnîşan dike ku analîza statîk divê bi rêkûpêk were bikar anîn, û ne carinan. Gotarên me kapasîteyên analîzkerê PVS-Studio baş destnîşan dikin, lê ti têkiliya vê bi baştirkirina kalîteya kodê û kêmkirina lêçûna rastkirina xeletiyan re tune. Bi rêkûpêk analîzkerek koda statîk bikar bînin!
  2. Em teşhîsên heyî bi dawî dikin û baştir dikin. Ji ber vê yekê, analîzer dikare xeletiyên ku di dema şopandinên berê de nedîtine nas bike.
  3. Di PVS-Studio de tespîtên nû yên ku 2 sal berê tunebûn derketin. Min biryar da ku wan di beşek cûda de ronî bikim da ku pêşkeftina PVS-Studio bi zelalî nîşan bidim.

Kêmasiyên ku bi tespîtên ku 2 sal berê hebûn hatine tespît kirin

Fragment N1: Kopî-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
  ....
}

Hişyariya PVS-Studio: V501 [CWE-570] Li milê çepê û li milê rastê yê '||', jêr-biwêjên wekhev 'Name.startswith("avx512.mask.permvar.")' hene. makînevan. AutoUpgrade.cpp 73

Dubare tê kontrol kirin ku nav bi jêrxala "avx512.mask.permvar." dest pê dike. Di kontrola duyemîn de, wan eşkere dixwest ku tiştek din binivîsin, lê ji bîr kir ku nivîsa kopî rast bikin.

Fragment N2: Tîpa

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

Hişyarî PVS-Studio: V501 Li milê çepê û li rastê ya '|'-ê jêr-îfade 'CXNameRange_WantQualifier' yek in hene. makînevan. CIndex.cpp 7245

Ji ber xeletiya tîpê, heman navî du caran tê bikaranîn CXNameRange_WantQualifier.

Fragment N3: Tevliheviya bi pêşengiya operatorê

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

Hişyariya PVS-Studio: V502 [CWE-783] Dibe ku operatorê '?:' ji ya ku dihat hêvîkirin bi rengek cûda dixebite. Operatora '?:' ji operatora '==' kêmtir e. PPCTargetTransformInfo.cpp 404

Bi dîtina min ev xeletiyek pir xweş e. Erê, ez dizanim di derbarê bedewiyê de fikrên min ên xerîb hene :).

Niha, li gorî pêşengên operator, îfade wiha tê nirxandin:

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

Ji nêrînek pratîkî ve, rewşek weha ne wate ye, ji ber ku ew dikare were kêm kirin:

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

Ev xeletiyek eşkere ye. Bi îhtîmaleke mezin, wan dixwest ku 0/1 bi guhêrbarekê bidin ber hev Naverok. Ji bo rastkirina kodê hûn hewce ne ku li dora operatora sêalî parantezê zêde bikin:

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

Bi awayê, operatorê sêalî pir xeternak e û xeletiyên mantiqî provoke dike. Pir hay ji xwe hebin û bi parantezê nexebitin. Min bi berfirehî li vê mijarê mêze kir vir, di beşa "Hay ji ?: Operator û Têxe nav Parantezê."

Fragment N4, N5: Nîşana Null

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

Hişyariya PVS-Studio: V522 [CWE-476] Dibe ku jêbirina nîşana betal 'LHS' pêk were. TGParser.cpp 2152

Heke nîşanker LHS betal e, divê hişyarî bê dayîn. Lêbelê, li şûna wê, ev heman nîşana null dê were jêbirin: LHS->getAsString().

Ev rewşek pir tîpîk e dema ku xeletiyek di hilberek xeletiyê de veşêre, ji ber ku kes wan naceribîne. Analîzatorên statîk hemî kodên gihîştî kontrol dikin, her çend ew çend caran tê bikar anîn. Ev mînakek pir baş e ku çawa analîza statîk teknîkên din ên ceribandin û parastina xeletiyê temam dike.

Çewtiyek bişixuşiya nîşanderê ya bi heman rengî RHS di koda jêrîn de destûr tê dayîn: V522 [CWE-476] Dibe ku veqetandina nîşana null 'RHS' pêk were. TGParser.cpp 2186

Fragment N6: Bikaranîna nîşanderê piştî tevgerê

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

Hişyarî PVS-Studio: V522 [CWE-476] Dibe ku veqetandina nîşana null 'ProgClone' pêk were. Miscompilation.cpp 601

Di destpêkê de nîşanek jîr ProgClone dev ji xwedîkirina objeyê berdide:

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

Bi rastî, niha ProgClone nîşanek betal e. Ji ber vê yekê, dereferansek nîşana betal divê tenê li jêr çêbibe:

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

Lê, di rastiyê de, ev ê nebe! Bala xwe bidinê ku loop bi rastî nayê darve kirin.

Di destpêka konteynerê de MiscompiledFunctions paqij kirin:

MiscompiledFunctions.clear();

Dûv re, mezinahiya vê konteynerê di rewşa lûkê de tê bikar anîn:

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

Hêsan e ku meriv bibîne ku lûp dest pê nake. Ez difikirim ku ev jî xeletiyek e û kod divê cûda were nivîsandin.

Wusa dixuye ku em rastî wê pariya xeletiyên navdar hatine! Yek xeletiyek din mask dike :).

Fragment N7: Bikaranîna nîşanderê piştî tevgerê

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

Hişyarî ya PVS-Studio: V522 [CWE-476] Dibe ku jinavbirina nîşana betal 'Test' pêk were. Miscompilation.cpp 709

Dîsa heman rewş. Di destpêkê de, naveroka objeyê tê guheztin, û paşê wekî ku tiştek nebûbe tê bikar anîn. Piştî ku semantîka tevgerê di C++ de xuya bû, ez vê rewşê pir caran di koda bernameyê de dibînim. Ji ber vê yekê ez ji zimanê C++ hez dikim! Zêdetir û bêtir awayên nû hene ku hûn lingê xwe biavêjin. Analîzatora PVS-Studio dê her gav bixebite :).

Fragment N8: Nîşana Null

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

Hişyarî ya PVS-Studio: V522 [CWE-476] Dibe ku jinavbirina nîşana betal 'Cûre' pêk were. PrettyFunctionDumper.cpp 233

Ji bilî hilgirên çewtiyê, fonksiyonên çapkirinê yên xeletkirinê bi gelemperî nayên ceribandin. Li pêşberî me tenê dozek wiha heye. Fonksiyon li benda bikarhêner e, ku li şûna ku pirsgirêkên xwe çareser bike, dê neçar bimîne ku wê rast bike.

Rastîn

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

Fragment N9: Nîşana Null

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

Hişyarî ya PVS-Studio: V522 [CWE-476] Dibe ku veqetandina nîşana betal 'Ty' pêk were. SearchableTableEmitter.cpp 614

Ez difikirim ku her tişt zelal e û ne hewceyê ravekirinê ye.

Fragment N10: Tîpa

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

Hişyariya PVS-Studio: V570 Guherbara 'Identifier->Type' ji xwe re tê veqetandin. FormatTokenLexer.cpp 249

Ti wateya ku guhêrbarek ji xwe re diyar bike tune ye. Bi îhtîmaleke mezin wan dixwest binivîsin:

Identifier->Type = Question->Type;

Fragment N11: Şikandina gumanbar

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

Hişyariya PVS-Studio: V622 [CWE-478] Bifikirin ku daxuyaniya 'veguhertinê' kontrol bikin. Mimkun e ku operatorê yekem 'doz' winda bibe. SystemZAsmParser.cpp 652

Di destpêkê de operatorek pir bi guman heye şikesta. We ji bîr kir ku hûn li vir tiştek din binivîsin?

Fragment N12: Kontrolkirina nîşankerek piştî veqetandinê

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

Hişyariya PVS-Studio: V595 [CWE-476] Nîşaneya 'Callee' berî ku ew li dijî nullptr were piştrast kirin hate bikar anîn. Rêzan kontrol bikin: 172, 174. AMDGPUInline.cpp 172

Pointer Callee di destpêkê de dema ku fonksiyona tê gotin tê dereferans kirin getTTI.

Û paşê derdikeve holê ku divê ev nîşanker ji bo wekheviyê were kontrol kirin nullptr:

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

Lê pir dereng e…

Fragment N13 - N...: Kontrolkirina nîşanek piştî jêderxistinê

Rewşa ku di beşa koda berê de hatî nîqaş kirin ne yekta ye. Li vir xuya dike:

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

Hişyariya PVS-Studio: V595 [CWE-476] Nîşaneya 'CalleeFn' beriya ku li dijî nullptr were pejirandin hate bikar anîn. Rêzan kontrol bikin: 1079, 1081. SimplifyLibCalls.cpp 1079

Û li vir:

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

Hişyariya PVS-Studio: V595 [CWE-476] Nîşaneya 'ND' beriya ku li dijî nullptr were piştrast kirin hate bikar anîn. Rêzan kontrol bikin: 532, 534. SemaTemplateInstantiateDecl.cpp 532

Û li vir:

  • V595 [CWE-476] Nîşaneya 'U' berî ku ew li dijî nullptr were piştrast kirin hate bikar anîn. Rêzan kontrol bikin: 404, 407. DWARFormValue.cpp 404
  • V595 [CWE-476] Nîşaneya 'ND' beriya ku li dijî nullptr were piştrast kirin hate bikar anîn. Rêzan kontrol bikin: 2149, 2151. SemaTemplateInstantiate.cpp 2149

Û dûv re ez ji xwendina hişyariyên bi hejmara V595 re bê eleqe bûm. Ji ber vê yekê ez nizanim gelo ji xeynî yên ku li vir têne navnîş kirin, xeletiyên wekhev hene. Bi îhtîmaleke mezin heye.

Fragment N17, N18: Guhertina gumanbar

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

Hişyariya PVS-Studio: V629 [CWE-190] Binêrin ku hûn îfadeya '~(Mezinahî - 1) << 1' kontrol bikin. Bit guheztina nirxa 32-bit bi berfirehkirina dûv re berbi celebê 64-bit. AArch64AddressingModes.h 260

Dibe ku ew ne xeletiyek be û kod tam wekî ku tê xwestin dixebite. Lê ev eşkere cihekî pir bi guman e û pêdivî ye ku were kontrol kirin.

Em guhêrbar bibêjin Mezinayî 16-ê wekhev e, û paşê nivîskarê kodê plan kir ku wê di guhêrbarek de bigire NImms mane:

1111111111111111111111111111111111111111111111111111111111100000

Lêbelê, di rastiyê de encam dê bibe:

0000000000000000000000000000000011111111111111111111111111100000

Rastî ev e ku hemî hesabên bi karanîna celebê 32-bit bê îmze têne kirin. Û tenê wê gavê, ev celebê 32-bitî yê bê îmza dê bi nepenî were berfireh kirin uint64_t. Di vê rewşê de, bitsên herî girîng dê sifir bin.

Hûn dikarin vê rewşê rast bikin:

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

Rewşa bi vî rengî: V629 [CWE-190] Binêrin ku îfadeya 'Immr << 6' kontrol bikin. Bit guheztina nirxa 32-bit bi berfirehkirina dûv re berbi celebê 64-bit. AArch64AddressingModes.h 269

Fragment N19: Peyva sereke winda ye wekîdi?

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

Hişyariya PVS-Studio: V646 [CWE-670] Bifikirin ku mantiqa serîlêdanê kontrol bikin. Mimkun e ku peyva sereke ya 'din' winda bibe. AMDGPUAsmParser.cpp 5655

Li vir xeletiyek tune. Ji ber ku wê demê-bloka yekem if bi dawî dibe berdewamkirin, wê demê ferq nake, keywordek heye wekîdi an na. Bi her awayî kod dê bi heman rengî bixebite. Dîsa jî bêriya wekîdi kodê bêtir nezelal û xeternak dike. Ger di pêşerojê de berdewamkirin winda dibe, kod dê bi tevahî cûda dest bi xebatê bike. Li gorî min çêtir e ku meriv lê zêde bike wekîdi.

Fragment N20: Çar tîpên heman tîpê

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

Hişyariyên PVS-Studio:

  • V655 [CWE-480] Têl hatin girêdan lê nayên bikaranîn. Binêrin ku hûn îfadeya 'Encam + Name.str()' kontrol bikin. Symbol.cpp 32
  • V655 [CWE-480] Têl hatin girêdan lê nayên bikaranîn. Binêrin ku hûn îfadeya 'Encam + "(ObjC Class)" + Name.str()' kontrol bikin. Symbol.cpp 35
  • V655 [CWE-480] Têl hatin girêdan lê nayên bikaranîn. Binêrin ku hûn îfadeya 'Encam + "(ObjC Class EH)" + Name.str()' kontrol bikin. Symbol.cpp 38
  • V655 [CWE-480] Têl hatin girêdan lê nayên bikaranîn. Binêrin ku hûn îfadeya 'Encam + "(ObjC IVar)" + Name.str()' kontrol bikin. Symbol.cpp 41

Bi tesadufî, li şûna += operatora + tê bikaranîn. Encam sêwiranên ku bê wate ne.

Parçeya N21: Tevgera nediyar

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

Biceribînin ku hûn bi xwe koda xeternak bibînin. Û ev wêneyek e ku balê bikişîne da ku tavilê li bersivê nenihêre:

Bi karanîna analîzera PVS-Studio di LLVM 8 de xeletiyan bibînin

Hişyariya PVS-Studio: V708 [CWE-758] Avakirina xeternak tê bikar anîn: 'FeaturesMap[Op] = FeaturesMap.size()', ku 'FeaturesMap' ji çîna 'nexşeyê' ye. Ev dibe ku bibe sedema tevgerek nediyar. RISCVCompressInstEmitter.cpp 490

Rêza pirsgirêkê:

FeaturesMap[Op] = FeaturesMap.size();

Ger element Op nayê dîtin, paşê hêmaneke nû di nexşeyê de tê çêkirin û hejmara hêmanên vê nexşeyê li wir tê nivîsandin. Tenê nayê zanîn ka fonksiyon dê were bang kirin mezinayî berî an piştî lê zêdekirina hêmanek nû.

Fragment N22-N24: Karên dubare kirin

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

Hişyariya PVS-Studio: V519 [CWE-563] Guherbara 'NType' du caran li pey hev nirxan tê veqetandin. Dibe ku ev xeletiyek e. Rêzan kontrol bikin: 1663, 1664. MachOObjectFile.cpp 1664

Ez bawer nakim ku li vir xeletiyek rast hebe. Tenê peywirek dubare ya nepêwîst. Lê dîsa jî xeletiyek.

Her wiha:

  • V519 [CWE-563] Guherbara 'B.NDesc' du caran li pey hev nirxan têne destnîşan kirin. Dibe ku ev xeletiyek e. Rêzan kontrol bikin: 1488, 1489. llvm-nm.cpp 1489
  • V519 [CWE-563] Guherbar du caran li pey hev nirxan têne destnîşan kirin. Dibe ku ev xeletiyek e. Rêzan kontrol bikin: 59, 61. coff2yaml.cpp 61

Fragment N25-N27: Zêdetir vesazkirin

Naha em li guhertoyek nûvekirinê hinekî cûda binêrin.

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

Hişyariya PVS-Studio: V519 [CWE-563] Guherbara 'Alignment' du caran li pey hev nirxan têne destnîşan kirin. Dibe ku ev xeletiyek e. Rêzan kontrol bikin: 1158, 1160. LoadStoreVectorizer.cpp 1160

Ev kodek pir ecêb e ku eşkere xeletiyek mentiqî heye. Di destpêkê de, guherbar Entegrasyona nirxek li gorî şertê tê destnîşankirin. Û paşê peywir dîsa pêk tê, lê naha bêyî kontrol.

Li vir rewşên weha têne dîtin:

  • V519 [CWE-563] Guherbara 'Effects' du caran li pey hev nirxan têne destnîşan kirin. Dibe ku ev xeletiyek e. Rêzan kontrol bikin: 152, 165. WebAssemblyRegStackify.cpp 165
  • V519 [CWE-563] Guherbara 'ExpectNoDerefChunk' du caran li pey hev nirxan têne destnîşan kirin. Dibe ku ev xeletiyek e. Rêzan kontrol bikin: 4970, 4973. SemaType.cpp 4973

Fragment N28: Rewşa her gav rast

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

Hişyariya PVS-Studio: V547 [CWE-571] Gotina 'nextByte != 0x90' her dem rast e. X86DisassemblerDecoder.cpp 379

Kontrolkirin nayê wateya. Têgûherr nextByte her tim ne wekhevî nirxê ye 0x90, ku ji kontrolê berê tê. Ev celeb xeletiyek mentiqî ye.

Fragment N29 - N...: Şertên hertim rast/derew

Analîzator gelek hişyariyan dide ku hemî rewş (V547) an jî beşek jê (V560) her dem rast an derew e. Bi gelemperî ev ne xeletiyên rastîn in, lê bi tenê kodek şikestî, encama berfirehkirina makro, û yên wekî wan in. Lêbelê, maqûl e ku meriv li van hemî hişyariyan binêre, ji ber ku xeletiyên mentiqî yên rastîn carinan carinan çêdibin. Mînakî, ev beşa kodê gumanbar e:

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

Hişyariya PVS-Studio: V560 [CWE-570] Beşek îfadeya şertî her gav xelet e: RegNo == 0xe. ARMdisassembler.cpp 939

Berdewamiya 0xE nirxa 14 di deh de ye. Îmtîhan RegNo == 0xe wateya xwe nake ji ber ku eger RegNo > 13, wê demê fonksiyon dê pêkanîna xwe temam bike.

Bi nasnameyên V547 û V560 re gelek hişyariyên din hebûn, lê wekî V595, Ez ne eleqedar bûm ku van hişyariyan bixwînim. Jixwe diyar bû ku têra min materyalê nivîsandina gotarekê hebû :). Ji ber vê yekê, nayê zanîn ka çend xeletiyên bi vî rengî di LLVM de bi karanîna PVS-Studio ve têne nas kirin.

Ez ê mînakek bidim we ka çima xwendina van tetikan bêzar e. Analîzator di derxistina hişyariyek ji bo koda jêrîn de bi rastî rast e. Lê ev ne xeletiyek e.

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

Hişyarî PVS-Studio: V547 [CWE-570] Gotina '!HasError' her gav xelet e. UnwrappedLineParser.cpp 1635

Fragment N30: ​​Vegera gumanbar

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

Hişyariya PVS-Studio: V612 [CWE-670] 'Vegerandin'ek bê şert û merc di nav xelekekê de. R600OptimizeVectorRegisters.cpp 63

Ev an xeletiyek an teknîkek taybetî ye ku armanc e ku tiştek ji bernamenûsên ku kodê dixwînin rave bike. Ev sêwiran tiştek ji min re rave nake û pir bi guman xuya dike. Çêtir e mirov wisa nenivîse :).

Westya? Paşê dema çêkirina çay an qehweyê ye.

Bi karanîna analîzera PVS-Studio di LLVM 8 de xeletiyan bibînin

Kêmasiyên ku ji hêla tespîtên nû ve têne nas kirin

Ez difikirim ku 30 aktîvkirina tespîtên kevn bes e. Ka em naha bibînin ka çi tiştên balkêş dikarin bi teşhîsên nû yên ku piştî wê di analyzerê de derketine bibînin pêşî kontrol dike. Di vê demê de, bi tevahî 66 tespîtên gelemperî li analîzera C ++ hatin zêdekirin.

Fragment N31: Koda ku nayê gihîştin

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

Hişyariya PVS-Studio: V779 [CWE-561] Koda negihîştî hat dîtin. Dibe ku xeletiyek hebe. ExecutionUtils.cpp 146

Wekî ku hûn dikarin bibînin, herdu şaxên operatorê if bi banga operatorê re bi dawî dibe vegera. Li gorî vê, konteynir CtorDtorsByPriority dê qet neyê paqij kirin.

Fragment N32: Koda ku nayê gihîştin

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

Hişyariya PVS-Studio: V779 [CWE-561] Koda negihîştî hate tespît kirin. Dibe ku xeletiyek hebe. LLParser.cpp 835

Rewşa balkêş. Ka em pêşî li vê derê binêrin:

return ParseTypeIdEntry(SummaryID);
break;

Di nihêrîna pêşîn de xuya ye ku li vir xeletiyek tune. Ew wekî operator xuya dike şikesta li vir yek zêde heye, û hûn dikarin wê bi tenê jêbirin. Lêbelê, hemî ne ewqas hêsan e.

Analîzator li ser rêzan hişyariyek dide:

Lex.setIgnoreColonInIdentifiers(false);
return false;

Û bi rastî, ev kod nayê gihîştin. Hemû doz di gûherr bi bangek operator bi dawî dibe vegera. Û niha tenê bêaqil şikesta ew qas bê zirar xuya nake! Dibe ku yek ji şaxan divê bi dawî bibe şikesta, ne li ser vegera?

Fragment N33: Vesazkirina rasthatî ya biteyên bilind

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

Hişyariya PVS-Studio: V784 Mezinahiya maskeya bit ji mezinahiya operanda yekem kêmtir e. Ev ê bibe sedema windabûna bitên bilind. RuntimeDyld.cpp 815

Ji kerema xwe not bikin ku fonksiyona getStubAlignment type vedigere bêavber. Ka em nirxa îfadeyê bihesibînin, bihesibînin ku fonksiyon nirxa 8 vedigerîne:

~(getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

Niha bala xwe bidin ku guhêrbar DataSize cureyek 64-bit bê îmze heye. Derket holê ku dema ku operasyona DataSize & 0xFFFFFFF8u pêk bînin, hemî sî û du bit-ên rêza bilind dê ji nû ve werin vegerandin. Bi îhtîmaleke mezin, ev ne ya ku bernameçêker dixwest e. Ez guman dikim ku wî dixwest hesab bike: DataSize & 0xFFFFFFFFFFFFFFFFFF8u.

Ji bo rastkirina xeletiyê, divê hûn vê yekê binivîsin:

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

Yan jî

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

Fragment N34: Asta tîpa eşkere têkçû

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

Hişyariya PVS-Studio: V1028 [CWE-190] Zêdebûna gengaz. Bihesibînin ku operandên operatora 'NumElts * Scale' bi tîpa 'size_t' biavêjin, ne encam. X86ISelLowering.h 1577

Dema ku guhêrbarên tîpan zêde dikin, avêtina tîpa eşkere tê bikar anîn da ku ji sermayê dûr nekevin int. Lêbelê, avêtina celebek eşkere li vir li hember rijandinê naparêze. Pêşî, guhêrbar dê werin zêdekirin, û tenê wê hingê dê encama 32-bit ya pirjimariyê li celebê were berfireh kirin. size_t.

Fragment N35: Kopî-Paste têkçû

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] Du parçeyên kodê yên wekhev hatin dîtin. Belkî, ev xeletiyek tîpî ye û divê guhêrbar 'Op1' li şûna 'Op0' were bikar anîn. InstCombineCompares.cpp 5507

Ev teşhîsa balkêş a nû rewşên ku perçeyek kodê hatiye kopî kirin û hin navên tê de dest bi guhertinê kirine destnîşan dike, lê li cîhek wan ew rast nekiriye.

Ji kerema xwe not bikin ku di bloka duyemîn de ew hatine guhertin Op0 li ser Op1. Lê li cihekî wan ew rast nekirin. Bi îhtîmaleke mezin diviyabû wiha bihata nivîsandin:

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

Fragment N36: Tevliheviya Guherbar

struct Status {
  unsigned Mask;
  unsigned Mode;

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

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

Hişyariya PVS-Studio: V1001 [CWE-563] Guherbara 'Mode' tê destnîşankirin lê heya dawiya fonksiyonê nayê bikar anîn. SIModeRegister.cpp 48

Pir xeternak e ku meriv argumanên fonksiyonê heman navên endamên polê bidin. Pir hêsan e ku meriv tevlihev bibe. Li pêşberî me tenê dozek wiha heye. Ev gotin ne wate ye:

Mode &= Mask;

Argumana fonksiyonê diguhere. Navê pêger. Ev arguman êdî nayê bikaranîn. Bi îhtîmaleke mezin diviya we bi vî rengî binivîsanda:

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

Fragment N37: Tevliheviya Guherbar

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

Hişyarî PVS-Studio: V1001 [CWE-563] Guherbara 'Mezinahî' tê destnîşankirin lê heta dawiya fonksiyonê nayê bikar anîn. Object.cpp 424

Rewş dişibe ya berê. Divê were nivîsandin:

this->Size += this->EntrySize;

Fragment N38-N47: Wan ji bîr kir ku navnîşê kontrol bikin

Berê, me li mînakên teşhîskirina tespîtkirinê mêze kir V595. Esasê wê ev e ku nîşanker di destpêkê de tê jêbirin, û tenê hingê tê kontrol kirin. Teşhîsa ciwan V1004 di wateyê de berevajî ye, lê gelek xeletiyan jî derdixe holê. Ew rewşên ku nîşanker di destpêkê de hate kontrol kirin û paşê ji bîr kirin ku wiya bike destnîşan dike. Ka em li rewşên weha yên ku di hundurê LLVM de hatine dîtin binêrin.

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

Hişyariya PVS-Studio: V1004 [CWE-476] Nîşaneya 'Ptr' piştî ku li dijî nullptr hate rast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 729, 738. TargetTransformInfoImpl.h 738

Têgûherr Ptr dibe ku wekhev be nullptr, wekî ku ji hêla kontrolê ve hatî destnîşan kirin:

if (Ptr != nullptr)

Lêbelê, li jêr vê nîşanê bêyî kontrolkirina pêşîn tête jêbirin:

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

Werin em rewşek din a bi vî rengî bifikirin.

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

Hişyariya PVS-Studio: V1004 [CWE-476] Nîşaneya 'FD' piştî ku li dijî nullptr hate rast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 3228, 3231. CGDebugInfo.cpp 3231

Bala xwe bidin nîşanê FD. Ez bawer im ku pirsgirêk bi zelalî xuya ye û ravekirinek taybetî hewce nake.

Û bêtir:

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

Hişyariya PVS-Studio: V1004 [CWE-476] Nîşankera 'PtrTy' piştî ku li dijî nullptr hate rast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 960, 965. InterleavedLoadCombinePass.cpp 965

Meriv çawa xwe ji xeletiyên weha biparêze? Li ser Code-Review bêtir baldar bin û analîzera statîk PVS-Studio bikar bînin da ku koda xwe bi rêkûpêk kontrol bikin.

Tiştek tune ku meriv perçeyên kodê yên din ên bi xeletiyên bi vî rengî vebêje. Ez ê di gotarê de tenê navnîşek hişyariyan bihêlim:

  • V1004 [CWE-476] Nîşankera 'Expr' piştî ku li dijî nullptr hate rast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 1049, 1078. DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] Nîşankera 'PI' piştî ku li dijî nullptr hate piştrast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 733, 753. LegacyPassManager.cpp 753
  • V1004 [CWE-476] Nîşankera 'StatepointCall' piştî ku li dijî nullptr hate piştrast kirin bi rengek neewle hate bikar anîn. Rêzan kontrol bikin: 4371, 4379. Verifier.cpp 4379
  • V1004 [CWE-476] Nîşankera 'RV' piştî ku li dijî nullptr hate rast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 2263, 2268. TGParser.cpp 2268
  • V1004 [CWE-476] Nîşankera 'CalleeFn' piştî ku li dijî nullptr hate piştrast kirin bi ne ewle hate bikar anîn. Rêzan kontrol bikin: 1081, 1096. SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] Nîşankera 'TC' piştî ku li dijî nullptr hate verast kirin bi neewle hate bikar anîn. Rêzan kontrol bikin: 1819, 1824. Driver.cpp 1824

Fragment N48-N60: Ne krîtîk, lê kêmasiyek (derketina bîranîna gengaz)

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

Hişyariya PVS-Studio: V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Stratejiyan' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-isel-fuzzer.cpp 58

Ji bo lê zêde bike hêmanek li dawiya konteynerek mîna std:: vektor > tu nikarî bi tenê binivîsî xxx.push_back(nû X), ji ber ku veguhertina nepenî ji tune X* в std::unique_ptr.

Çareseriya hevpar nivîsandin e xxx.emplace_back(X nû)ji ber ku ew berhev dike: rêbaz emplace_back hêmanek rasterast ji argumanên xwe ava dike û ji ber vê yekê dikare çêkerên eşkere bikar bîne.

Ew ne ewle ye. Ger vektor tije be, wê hingê bîranîn ji nû ve tê veqetandin. Dibe ku operasyona ji nû ve veqetandina bîranînê têk biçe, di encamê de îstîsnayek were avêtin std::bad_alloc. Di vê rewşê de, nîşanker dê winda bibe û tişta hatî afirandin dê çu carî neyê jêbirin.

Çareseriyek ewledar e ku çêbikin unique_ptrberî ku vektor hewl bide ku bîranînê ji nû ve veqetîne, dê xwediyê nîşanderê be:

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

Ji C++14, hûn dikarin 'std::make_unique' bikar bînin:

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

Ev celeb xeletî ji bo LLVM ne krîtîk e. Ger bîranîn neyê veqetandin, berhevkar dê bi tenê raweste. Lêbelê, ji bo serîlêdanên bi dirêj uptime, ku nekare tenê biqede heke veqetandina bîranînê têk biçe, ev dikare bibe xeletiyek rastînek xirab.

Ji ber vê yekê, her çend ev kod ji LLVM re xetereyek pratîkî çênabe jî, min kêrhatî dît ku ez li ser vê şêwaza xeletiyê biaxivim û ku analîstê PVS-Studio fêr bûye ku wê nas bike.

Hişyariyên din ên vî rengî:

  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Derbas' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. PassManager.h 546
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'AA'yê tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. AliasAnalysis.h 324
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Entries' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'AllEdges' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. CFGMST.h 268
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'VMaps' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. SimpleLoopUnswitch.cpp 2012
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Records' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. FDRLogBuilder.h 30
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'PendingSubmodules' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. ModuleMap.cpp 810
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Objects' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. DebugMap.cpp 88
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Stratejiyan' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 685
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 686
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 688
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 689
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 690
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 691
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 692
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 693
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Guherker' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. llvm-stress.cpp 694
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Operands' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Stash' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] Nîşanek bê xwedan bi rêbaza 'emplace_back' li konteynera 'Matchers' tê zêdekirin. Di rewşek îstîsnayek de lehiya bîranînê dê çêbibe. GlobalISelEmitter.cpp 2702

encamê

Min bi tevahî 60 hişyarî da û paşê rawestiya. Ma kêmasiyên din hene ku analîzera PVS-Studio di LLVM de destnîşan dike? Erê heye. Lêbelê, gava ku min perçeyên kodê ji bo gotarê dinivîsand, êvar dereng bû, an jî hêj şev, û min biryar da ku ew dem e ku ez jê re rojek bibêjim.

Ez hêvî dikim ku we ew balkêş dît û hûn ê bixwazin ku analîzerê PVS-Studio biceribînin.

Hûn dikarin analîzkerê dakêşin û bişkojka mînberê li wir bistînin vê rûpelê.

Ya herî girîng, analîzên statîk bi rêkûpêk bikar bînin. Kontrolên yek-dem, ji hêla me ve ji bo populerkirina metodolojiya analîza statîk û PVS-Studio ne senaryoyek normal e.

Di baştirkirina kalîte û pêbaweriya koda xwe de serkeftin!

Bi karanîna analîzera PVS-Studio di LLVM 8 de xeletiyan bibînin

Heke hûn dixwazin vê gotarê bi temaşevanên îngilîzîaxêv re parve bikin, ji kerema xwe lînka wergerê bikar bînin: Andrey Karpov. Bi PVS-Studio re çewtiyên di LLVM 8 de bibînin.

Source: www.habr.com

Add a comment