Tfittxija bugs f'LLVM 8 billi tuża l-analizzatur PVS-Studio

Tfittxija bugs f'LLVM 8 billi tuża l-analizzatur PVS-Studio
Għaddew aktar minn sentejn mill-aħħar verifika tal-kodiċi tal-proġett LLVM bl-użu tal-analizzatur PVS-Studio tagħna. Ejja niżguraw li l-analizzatur PVS-Studio għadu għodda ewlenija għall-identifikazzjoni ta 'żbalji u vulnerabbiltajiet potenzjali. Biex tagħmel dan, aħna se niċċekkjaw u nsibu żbalji ġodda fir-rilaxx LLVM 8.0.0.

Artiklu li jrid jinkiteb

Biex inkun onest, ma ridtx nikteb dan l-artiklu. Mhux interessanti li tikteb dwar proġett li diġà vverifikajna diversi drabi (1, 2, 3). Huwa aħjar li tikteb dwar xi ħaġa ġdida, imma m'għandi l-ebda għażla.

Kull darba li tiġi rilaxxata jew aġġornata verżjoni ġdida ta' LLVM Clang Analizzatur Statiku, nirċievu mistoqsijiet tat-tip li ġej fil-posta tagħna:

Ara, il-verżjoni l-ġdida ta 'Clang Static Analyzer tgħallmet issib żbalji ġodda! Jidhirli li r-rilevanza tal-użu ta 'PVS-Studio qed tonqos. Clang isib aktar żbalji minn qabel u jlaħħaq mal-kapaċitajiet ta 'PVS-Studio. X'taħseb dwar dan?

Għal dan irrid dejjem inwieġeb xi ħaġa bħal:

Ma noqogħdux idle lanqas! Aħna tjiebna b'mod sinifikanti l-kapaċitajiet tal-analizzatur PVS-Studio. Mela tinkwetax, inkomplu mmexxu bħal qabel.

Sfortunatament, din hija tweġiba ħażina. M'hemm l-ebda provi fiha. U għalhekk qed nikteb dan l-artiklu issa. Għalhekk, il-proġett LLVM għal darb'oħra ġie ċċekkjat u nstabu varjetà ta 'żbalji fih. Issa se nuri dawk li dehru interessanti għalija. Clang Static Analyzer ma jistax isib dawn l-iżbalji (jew huwa estremament inkonvenjenti li tagħmel dan bl-għajnuna tiegħu). Imma nistgħu. Barra minn hekk, sibt u ktibt dawn l-iżbalji kollha f'lejla waħda.

Iżda l-kitba tal-artiklu ħadet diversi ġimgħat. Sempliċement ma stajtx inġib ruħi biex inpoġġi dan kollu fit-test :).

Mill-mod, jekk inti interessat f'liema teknoloġiji jintużaw fl-analizzatur PVS-Studio biex tidentifika żbalji u vulnerabbiltajiet potenzjali, allura nissuġġerixxi li tiffamiljarizza ma' dan Nota.

Dijanjostiċi ġodda u qodma

Kif diġà nnutat, madwar sentejn ilu l-proġett LLVM reġa’ ġie ċċekkjat, u l-iżbalji misjuba ġew ikkoreġuti. Issa dan l-artikolu se jippreżenta lott ġdid ta 'żbalji. Għaliex instabu bugs ġodda? Hemm 3 raġunijiet għal dan:

  1. Il-proġett LLVM qed jevolvi, ibiddel kodiċi antik u jżid kodiċi ġdid. Naturalment, hemm żbalji ġodda fil-kodiċi modifikat u miktub. Dan juri biċ-ċar li l-analiżi statika għandha tintuża regolarment, u mhux okkażjonalment. L-artikoli tagħna juru tajjeb il-kapaċitajiet tal-analizzatur PVS-Studio, iżda dan m'għandu x'jaqsam xejn mat-titjib tal-kwalità tal-kodiċi u t-tnaqqis tal-ispiża tal-iffissar tal-iżbalji. Uża analizzatur tal-kodiċi statiku regolarment!
  2. Qed nifinalizzaw u ntejbu d-dijanjostiċi eżistenti. Għalhekk, l-analizzatur jista 'jidentifika żbalji li ma ndunax waqt skans preċedenti.
  3. F'PVS-Studio dehru dijanjostiċi ġodda li ma kinux jeżistu sentejn ilu. Iddeċidejt li nenfasizzahom f'sezzjoni separata biex nuri b'mod ċar l-iżvilupp ta 'PVS-Studio.

Difetti identifikati minn dijanjostiċi li kienu jeżistu sentejn ilu

Framment N1: Ikkopja-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
  ....
}

Twissija PVS-Studio: V501 [CWE-570] Hemm subespressjonijiet identiċi 'Name.startswith("avx512.mask.permvar.")' fuq ix-xellug u fuq il-lemin tal-'||' operatur. AutoUpgrade.cpp 73

Huwa ċċekkjat darbtejn li l-isem jibda bis-substring "avx512.mask.permvar.". Fit-tieni kontroll, ovvjament riedu jiktbu xi ħaġa oħra, iżda nesa jikkoreġu t-test ikkupjat.

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

Twissija PVS-Studio: V501 Hemm subespressjonijiet identiċi 'CXNameRange_WantQualifier' fuq ix-xellug u fuq il-lemin tal-'|' operatur. CIndex.cpp 7245

Minħabba typo, l-istess kostanti msemmija tintuża darbtejn CXNameRange_WantQualifier.

Framment N3: Konfużjoni mal-preċedenza tal-operatur

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

Twissija PVS-Studio: V502 [CWE-783] Forsi l-operatur '?:' jaħdem b'mod differenti milli kien mistenni. L-operatur '?:' għandu prijorità aktar baxxa mill-operatur '=='. PPCTargetTransformInfo.cpp 404

Fl-opinjoni tiegħi, dan huwa żball sabiħ ħafna. Iva, naf li għandi ideat strambi dwar is-sbuħija :).

Issa, skond prijoritajiet tal-operaturi, l-espressjoni hija evalwata kif ġej:

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

Mil-lat prattiku, kundizzjoni bħal din ma tagħmilx sens, peress li tista 'titnaqqas għal:

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

Dan huwa żball ċar. Ħafna probabbli, riedu jqabblu 0/1 ma 'varjabbli indiċi. Biex tiffissa l-kodiċi trid iżżid parentesi madwar l-operatur ternarju:

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

Mill-mod, l-operatur ternarju huwa perikoluż ħafna u jipprovoka żbalji loġiċi. Oqgħod attent ħafna magħha u ma tkun greedy bil-parentesi. Ħarist lejn dan is-suġġett f'aktar dettall hawn, fil-kapitolu "Oqgħod attent mill-?: Operatur u Ehmuh fil-Parentesi."

Framment N4, N5: Pointer 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;
  }
  ....
}

Twissija PVS-Studio: V522 [CWE-476] Jista' jsir dereferencing tal-pointer null 'LHS'. TGParser.cpp 2152

Jekk il-pointer LHS hija nulla, għandha tinħareġ twissija. Madankollu, minflok, dan l-istess pointer null se jiġi dereferenced: LHS->getAsString().

Din hija sitwazzjoni tipika ħafna meta żball ikun moħbi f'handler, peress li ħadd ma jittestjahom. L-analizzaturi statiċi jiċċekkjaw il-kodiċi kollu li jista' jintlaħaq, irrispettivament minn kemm jintuża. Dan huwa eżempju tajjeb ħafna ta 'kif l-analiżi statika tikkumplimenta tekniki oħra ta' ttestjar u protezzjoni ta 'żbalji.

Żball simili fl-immaniġġjar tal-pointer RHS permess fil-kodiċi eżatt taħt: V522 [CWE-476] Jista' jseħħ dereferencing tal-pointer null 'RHS'. TGParser.cpp 2186

Framment N6: Uża l-pointer wara li tiċċaqlaq

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

Twissija ta' PVS-Studio: V522 [CWE-476] Jista' jsir dereferencing tal-pointer null 'ProgClone'. Miscompilation.cpp 601

Fil-bidu pointer intelliġenti ProgClone ma jibqax jippossjedi l-oġġett:

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

Fil-fatt, issa ProgClone huwa pointer null. Għalhekk, dereferenza null pointer għandha sseħħ eżatt taħt:

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

Iżda, fir-realtà, dan mhux se jiġri! Innota li l-linja mhix attwalment eżegwita.

Fil-bidu tal-kontenitur Funzjonijiet Kompilati Ħażin approvat:

MiscompiledFunctions.clear();

Sussegwentement, id-daqs ta 'dan il-kontenitur jintuża fil-kondizzjoni tal-linja:

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

Huwa faċli li tara li l-linja ma tibda. Naħseb li dan huwa wkoll bug u l-kodiċi għandu jinkiteb b'mod differenti.

Jidher li ltqajna ma' dik il-famuża parità ta' żbalji! Żball wieħed jaħbi ieħor :).

Framment N7: Uża l-pointer wara li tiċċaqlaq

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

Twissija ta' PVS-Studio: V522 [CWE-476] Jista' jsir dereferencing tal-pointer null 'Test'. Miscompilation.cpp 709

L-istess sitwazzjoni mill-ġdid. Għall-ewwel, il-kontenut tal-oġġett jitmexxa, u mbagħad jintuża bħallikieku ma ġara xejn. Nara din is-sitwazzjoni aktar u aktar spiss fil-kodiċi tal-programm wara li s-semantika tal-moviment dehret f'C++. Dan huwa għaliex inħobb il-lingwa C++! Hemm aktar u aktar modi ġodda biex tispara riġel tiegħek stess. L-analizzatur PVS-Studio dejjem ikollu xogħol :).

Framment N8: Pointer 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);
}

Twissija ta' PVS-Studio: V522 [CWE-476] Jista' jsir dereferencing tal-pointer null 'Tip'. PrettyFunctionDumper.cpp 233

Minbarra li jimmaniġġjaw l-iżbalji, il-funzjonijiet tal-istampar tad-debugging normalment ma jiġux ittestjati. Għandna biss każ bħal dan quddiemna. Il-funzjoni qed tistenna lill-utent, li, minflok isolvi l-problemi tiegħu, se jkun sfurzat jirranġaha.

B'mod korrett:

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

Framment N9: Pointer 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());
   ....
}

Twissija ta' PVS-Studio: V522 [CWE-476] Jista' jsir dereferencing tal-pointer null 'Ty'. SearchableTableEmitter.cpp 614

Naħseb li kollox huwa ċar u ma jeħtieġx spjegazzjoni.

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

Twissija PVS-Studio: V570 Il-varjabbli 'Identifikatur->Tip' hija assenjata lilha nnifisha. FormatTokenLexer.cpp 249

M'hemm l-ebda punt li tassenja varjabbli għaliha nnifisha. X'aktarx li riedu jiktbu:

Identifier->Type = Question->Type;

Framment N11: Tkissir suspettuż

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

Twissija PVS-Studio: V622 [CWE-478] Ikkunsidra li tispezzjona l-istqarrija 'swiċċ'. Huwa possibbli li l-ewwel operatur 'każ' ikun nieqes. SystemZAsmParser.cpp 652

Fil-bidu hemm operatur suspettuż ħafna break. Insejt tikteb xi ħaġa oħra hawn?

Framment N12: Iċċekkjar pointer wara 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");
  ....
}

Twissija PVS-Studio: V595 [CWE-476] Il-pointer 'Callee' ġie utilizzat qabel ma ġie vverifikat kontra nullptr. Iċċekkja linji: 172, 174. AMDGPUInline.cpp 172

Pointer Callee fil-bidu hija dereferenced fil-ħin li tissejjaħ il-funzjoni getTTI.

U mbagħad jirriżulta li dan il-pointer għandu jiġi ċċekkjat għall-ugwaljanza nullptr:

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

Imma huwa tard wisq...

Framment N13 - N...: Iċċekkjar pointer wara dereferencing

Is-sitwazzjoni diskussa fil-framment tal-kodiċi preċedenti mhijiex unika. Jidher hawn:

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

Twissija PVS-Studio: V595 [CWE-476] Il-pointer 'CalleeFn' ġie utilizzat qabel ma ġie vverifikat kontra nullptr. Iċċekkja l-linji: 1079, 1081. SimplifyLibCalls.cpp 1079

U hawn:

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

Twissija PVS-Studio: V595 [CWE-476] Il-pointer 'ND' intuża qabel ma ġie vverifikat kontra nullptr. Iċċekkja linji: 532, 534. SemaTemplateInstantiateDecl.cpp 532

U hawn:

  • V595 [CWE-476] Il-pointer 'U' ġie utilizzat qabel ma ġie vverifikat kontra nullptr. Iċċekkja linji: 404, 407. DWARFormValue.cpp 404
  • V595 [CWE-476] Il-pointer 'ND' ġie utilizzat qabel ma ġie vverifikat kontra nullptr. Iċċekkja linji: 2149, 2151. SemaTemplateInstantiate.cpp 2149

U mbagħad sirt mhux interessat li nistudja t-twissijiet bin-numru V595. Allura ma nafx jekk hemmx aktar żbalji simili minbarra dawk elenkati hawn. Ħafna probabbli hemm.

Framment N17, N18: Ċaqliq suspettuż

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

Twissija PVS-Studio: V629 [CWE-190] Ikkunsidra li tispezzjona l-espressjoni '~(Daqs - 1) << 1'. Ċaqliq tal-bit tal-valur 32-bit b'espansjoni sussegwenti għat-tip 64-bit. AArch64AddressingModes.h 260

Jista 'ma jkunx bug u l-kodiċi jaħdem eżatt kif maħsub. Iżda dan huwa ċar post suspettuż ħafna u jeħtieġ li jiġi ċċekkjat.

Ejja ngħidu l-varjabbli daqs huwa ugwali għal 16, u mbagħad l-awtur tal-kodiċi ppjanat li ġġibu f'varjabbli NImms valur:

1111111111111111111111111111111111111111111111111111111111100000

Madankollu, fir-realtà r-riżultat se jkun:

0000000000000000000000000000000011111111111111111111111111100000

Il-fatt hu li l-kalkoli kollha jseħħu bl-użu tat-tip 32-bit mhux iffirmat. U allura biss, dan it-tip mhux iffirmat ta '32 bit se jiġi estiż impliċitament għal uint64_t. F'dan il-każ, l-aktar bits sinifikanti se jkunu żero.

Tista' tirranġa s-sitwazzjoni bħal din:

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

Sitwazzjoni simili: V629 [CWE-190] Ikkunsidra li tispezzjona l-espressjoni 'Immr << 6'. Ċaqliq tal-bit tal-valur 32-bit b'espansjoni sussegwenti għat-tip 64-bit. AArch64AddressingModes.h 269

Framment N19: kelma prinċipali nieqsa inkella?

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

Twissija PVS-Studio: V646 [CWE-670] Ikkunsidra li tispezzjona l-loġika tal-applikazzjoni. Huwa possibbli li l-kelma prinċipali "inkella" tkun nieqsa. AMDGPUAsmParser.cpp 5655

M'hemm l-ebda żball hawn. Peress li dak iż-żmien-blokk tal-ewwel if jispiċċa bi tkompli, allura ma jimpurtax, hemm kelma prinċipali inkella jew le. Jew il-mod il-kodiċi se jaħdem l-istess. Xorta mitlufa inkella jagħmel il-kodiċi aktar mhux ċar u perikoluż. Jekk fil-futur tkompli tisparixxi, il-kodiċi se jibda jaħdem b'mod kompletament differenti. Fl-opinjoni tiegħi huwa aħjar li żżid inkella.

Framment N20: Erba' typos tal-istess tip

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

Twissijiet ta' PVS-Studio:

  • V655 [CWE-480] Il-kordi kienu magħqudin iżda ma jintużawx. Ikkunsidra li tispezzjona l-espressjoni 'Riżultat + Isem.str()'. Simbolu.cpp 32
  • V655 [CWE-480] Il-kordi kienu magħqudin iżda ma jintużawx. Ikkunsidra li tispezzjona l-espressjoni 'Riżultat + "(Klassi ObjC)" + Isem.str()'. Simbolu.cpp 35
  • V655 [CWE-480] Il-kordi kienu magħqudin iżda ma jintużawx. Ikkunsidra li tispezzjona l-espressjoni 'Riżultat + "(Klassi ObjC EH)" + Isem.str()'. Simbolu.cpp 38
  • V655 [CWE-480] Il-kordi kienu magħqudin iżda ma jintużawx. Ikkunsidra li tispezzjona l-espressjoni 'Riżultat + "(ObjC IVar)" + Isem.str()'. Simbolu.cpp 41

B'inċident, l-operatur + jintuża minflok l-operatur +=. Ir-riżultat huwa disinji li huma nieqsa minn tifsira.

Framment N21: Imġieba mhux definita

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

Ipprova sib il-kodiċi perikoluż lilek innifsek. U din hija stampa biex tfixkel l-attenzjoni sabiex ma tħaresx immedjatament lejn it-tweġiba:

Tfittxija bugs f'LLVM 8 billi tuża l-analizzatur PVS-Studio

Twissija PVS-Studio: V708 [CWE-758] Tintuża kostruzzjoni perikoluża: 'FeaturesMap[Op] = FeaturesMap.size()', fejn 'FeaturesMap' hija ta' klassi 'mappa'. Dan jista' jwassal għal imġieba mhux definita. RISCVCompressInstEmitter.cpp 490

Linja tal-problema:

FeaturesMap[Op] = FeaturesMap.size();

Jekk element Op ma jinstabx, allura jinħoloq element ġdid fil-mappa u n-numru ta' elementi f'din il-mappa jinkiteb hemm. Mhux magħruf jekk il-funzjoni se tissejjaħ daqs qabel jew wara li żżid element ġdid.

Framment N22-N24: Assenjazzjonijiet ripetuti

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

Twissija PVS-Studio: V519 [CWE-563] Il-varjabbli 'NType' hija assenjata valuri darbtejn suċċessivament. Forsi dan huwa żball. Iċċekkja linji: 1663, 1664. MachOObjectFile.cpp 1664

Ma naħsibx li hawn żball reali. Biss assenjazzjoni ripetuta bla bżonn. Iżda xorta waħda taħwid.

Bl-istess mod:

  • V519 [CWE-563] Il-varjabbli 'B.NDesc' hija assenjata valuri darbtejn suċċessivament. Forsi dan huwa żball. Iċċekkja linji: 1488, 1489. llvm-nm.cpp 1489
  • V519 [CWE-563] Il-varjabbli hija assenjata valuri darbtejn suċċessivament. Forsi dan huwa żball. Iċċekkja linji: 59, 61. coff2yaml.cpp 61

Framment N25-N27: Aktar assenjazzjonijiet mill-ġdid

Issa ejja nħarsu lejn verżjoni kemmxejn differenti ta 'assenjazzjoni mill-ġdid.

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

Twissija PVS-Studio: V519 [CWE-563] Il-varjabbli 'Allinjament' hija assenjata valuri darbtejn suċċessivament. Forsi dan huwa żball. Iċċekkja l-linji: 1158, 1160. LoadStoreVectorizer.cpp 1160

Dan huwa kodiċi stramb ħafna li jidher li fih żball loġiku. Fil-bidu, varjabbli Allinjament jiġi assenjat valur skont il-kundizzjoni. U mbagħad l-inkarigu jerġa' jseħħ, iżda issa mingħajr ebda kontroll.

Sitwazzjonijiet simili jistgħu jidhru hawn:

  • V519 [CWE-563] Il-varjabbli 'Effetti' hija assenjata valuri darbtejn suċċessivament. Forsi dan huwa żball. Iċċekkja linji: 152, 165. WebAssemblyRegStackify.cpp 165
  • V519 [CWE-563] Il-varjabbli 'ExpectNoDerefChunk' hija assenjata valuri darbtejn suċċessivament. Forsi dan huwa żball. Iċċekkja linji: 4970, 4973. SemaType.cpp 4973

Framment N28: Dejjem kundizzjoni vera

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

Twissija PVS-Studio: V547 [CWE-571] L-espressjoni 'nextByte != 0x90' hija dejjem vera. X86DisassemblerDecoder.cpp 379

Iċċekkjar ma jagħmilx sens. Varjabbli nextByte dejjem mhux ugwali għall-valur 0x90, li ġej mill-verifika preċedenti. Dan huwa xi tip ta 'żball loġiku.

Framment N29 - N...: Kundizzjonijiet dejjem veri/foloz

L-analizzatur joħroġ ħafna twissijiet li l-kundizzjoni kollha (V547) jew parti minnha (V560) hija dejjem vera jew falza. Ħafna drabi dawn mhumiex żbalji reali, iżda sempliċement kodiċi sloppy, ir-riżultat ta 'espansjoni makro, u simili. Madankollu, jagħmel sens li tħares lejn dawn it-twissijiet kollha, peress li żbalji loġiċi ġenwini jseħħu minn żmien għal żmien. Pereżempju, din it-taqsima tal-kodiċi hija suspettuża:

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

Twissija PVS-Studio: V560 [CWE-570] Parti mill-espressjoni kondizzjonali hija dejjem falza: RegNo == 0xe. ARMDisassembler.cpp 939

Il-kostanti 0xE huwa l-valur 14 f'deċimali. Eżami RegNo == 0xe ma jagħmilx sens għax jekk RegNo > 13, allura l-funzjoni se tlesti l-eżekuzzjoni tagħha.

Kien hemm ħafna twissijiet oħra bl-IDs V547 u V560, iżda bħal ma V595, Ma kontx interessat li nistudja dawn it-twissijiet. Kien diġà ċar li kelli biżżejjed materjal biex nikteb artiklu :). Għalhekk, mhux magħruf kemm jistgħu jiġu identifikati żbalji ta' dan it-tip f'LLVM bl-użu ta' PVS-Studio.

Nagħtik eżempju ta 'għaliex l-istudju ta' dawn il-kawżi huwa boring. L-analizzatur għandu raġun assolut meta joħroġ twissija għall-kodiċi li ġej. Iżda dan mhuwiex żball.

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

Twissija PVS-Studio: V547 [CWE-570] L-espressjoni '!HasError' hija dejjem falza. UnwrappedLineParser.cpp 1635

Framment N30: ​​​​Ritorn suspettuż

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

Twissija PVS-Studio: V612 [CWE-670] 'Ritorn' inkondizzjonat f'linja. R600OptimizeVectorRegisters.cpp 63

Dan huwa jew żball jew teknika speċifika li hija maħsuba biex tispjega xi ħaġa lill-programmaturi li jaqraw il-kodiċi. Dan id-disinn ma jispjegali xejn u jidher suspettuż ħafna. Aħjar ma tiktebx hekk :).

Għajjien? Imbagħad wasal iż-żmien li tagħmel it-te jew il-kafè.

Tfittxija bugs f'LLVM 8 billi tuża l-analizzatur PVS-Studio

Difetti identifikati minn dijanjostiċi ġodda

Naħseb li 30 attivazzjoni ta 'dijanjostika antika hija biżżejjed. Ejja issa naraw x'affarijiet interessanti jistgħu jinstabu bid-dijanjostiċi l-ġodda li dehru fl-analizzatur wara preċedenti kontrolli. Matul dan iż-żmien, total ta '66 dijanjostika għal skopijiet ġenerali ġew miżjuda mal-analizzatur C++.

Framment N31: Kodiċi ma jistax jintlaħaq

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

Twissija PVS-Studio: V779 [CWE-561] Kodiċi li ma jistax jintlaħaq. Huwa possibbli li jkun hemm żball. ExecutionUtils.cpp 146

Kif tistgħu taraw, iż-żewġ fergħat tal-operatur if jispiċċa b'sejħa lill-operatur ritorn. Għaldaqstant, il-kontenitur CtorDtorsByPriority qatt mhu se jkun ikklerjat.

Framment N32: Kodiċi ma jistax jintlaħaq

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

Twissija ta' PVS-Studio: V779 [CWE-561] Kodiċi li ma jintlaħaqx. Huwa possibbli li jkun hemm żball. LLParser.cpp 835

Sitwazzjoni interessanti. Ejja nħarsu lejn dan il-post l-ewwel:

return ParseTypeIdEntry(SummaryID);
break;

L-ewwel daqqa t'għajn, jidher li m'hemm l-ebda żball hawnhekk. Jidher bħall-operatur break hemm waħda żejda hawn, u tista 'sempliċement tħassarha. Madankollu, mhux kollha daqshekk sempliċi.

L-analizzatur joħroġ twissija fuq il-linji:

Lex.setIgnoreColonInIdentifiers(false);
return false;

U tabilħaqq, dan il-kodiċi ma jistax jintlaħaq. Il-każijiet kollha fil jaqilbu jispiċċa b'sejħa mill-operatur ritorn. U issa bla sens waħdu break ma tidhirx daqshekk bla ħsara! Forsi waħda mill-fergħat għandha tispiċċa bi break, mhux mixgħul ritorn?

Framment N33: Reset bl-addoċċ ta 'bits għoljin

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

Twissija PVS-Studio: V784 Id-daqs tal-maskra tal-bit huwa inqas mid-daqs tal-ewwel operand. Dan se jikkawża t-telf ta 'bits ogħla. RuntimeDyld.cpp 815

Jekk jogħġbok innota li l-funzjoni getStubAlignment tip prospetti mhux iffirmat. Ejja nikkalkulaw il-valur tal-espressjoni, billi nassumu li l-funzjoni tirritorna l-valur 8:

~(getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

Issa avviż li l-varjabbli DataSize għandu tip mhux iffirmat ta' 64 bit. Jirriżulta li meta twettaq l-operazzjoni DataSize & 0xFFFFFFF8u, tnejn u tletin bit ta 'ordni għolja se jiġu reset għal żero. Ħafna probabbli, dan mhuwiex dak li ried il-programmatur. Nissuspetta li ried jikkalkula: DataSize & 0xFFFFFFFFFFFFFFF8u.

Biex tirranġa l-iżball, għandek tikteb dan:

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

Jew hekk:

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

Framment N34: mitfugħa tat-tip espliċitu fallut

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

Twissija PVS-Studio: V1028 [CWE-190] Overflow possibbli. Ikkunsidra l-ikkastjar ta' operandi tal-operatur 'NumElts * Scale' għat-tip 'size_t', mhux ir-riżultat. X86ISelLowering.h 1577

L-ikkastjar tat-tip espliċitu jintuża biex jevita l-overflow meta timmultiplika varjabbli tat-tip int. Madankollu, ikkastjar tat-tip espliċitu hawnhekk ma jipproteġix kontra l-overflow. L-ewwel, il-varjabbli se jiġu mmultiplikati, u mbagħad biss ir-riżultat ta '32-bit tal-multiplikazzjoni se jiġi estiż għat-tip daqs_t.

Framment N35: Ikkopja-Paste falliet

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] Instabu żewġ frammenti tal-kodiċi simili. Forsi, din hija typo u l-varjabbli 'Op1' għandha tintuża minflok 'Op0'. InstCombineCompares.cpp 5507

Din id-dijanjostika interessanti ġdida tidentifika sitwazzjonijiet fejn biċċa kodiċi ġiet ikkupjata u xi ismijiet fiha bdew jinbidlu, iżda f'post wieħed ma kkoreġuhiex.

Jekk jogħġbok innota li fit-tieni blokk inbidlu Op0 fuq Op1. Iżda f'post wieħed ma rranġawhx. Aktarx li kellu jinkiteb hekk:

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

Framment N36: Konfużjoni Varjabbli

struct Status {
  unsigned Mask;
  unsigned Mode;

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

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

Twissija PVS-Studio: V1001 [CWE-563] Il-varjabbli 'Mode' hija assenjata iżda ma tintużax sa tmiem il-funzjoni. SIModeRegister.cpp 48

Huwa perikoluż ħafna li l-argumenti tal-funzjoni jingħataw l-istess ismijiet bħall-membri tal-klassi. Huwa faċli ħafna li titħawwad. Għandna biss każ bħal dan quddiemna. Din l-espressjoni ma tagħmilx sens:

Mode &= Mask;

L-argument tal-funzjoni jinbidel. Dak kollox. Dan l-argument m'għadux jintuża. X'aktarx kellek ktibtu hekk:

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

Framment N37: Konfużjoni Varjabbli

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

Twissija PVS-Studio: V1001 [CWE-563] Il-varjabbli 'Daqs' hija assenjata iżda ma tintużax sa tmiem il-funzjoni. Oġġett.cpp 424

Is-sitwazzjoni hija simili għal dik preċedenti. Għandu jinkiteb:

this->Size += this->EntrySize;

Framment N38-N47: Insew jiċċekkjaw l-indiċi

Preċedentement, ħares lejn eżempji ta 'attivazzjoni dijanjostika V595. L-essenza tagħha hija li l-pointer huwa dereferenced fil-bidu, u mbagħad biss iċċekkjat. Dijanjostika żgħażagħ V1004 huwa l-oppost fit-tifsira, iżda juri wkoll ħafna żbalji. Tidentifika sitwazzjonijiet fejn il-pointer ġie ċċekkjat fil-bidu u mbagħad insejt jagħmel dan. Ejja nħarsu lejn każijiet bħal dawn misjuba ġewwa LLVM.

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

Twissija PVS-Studio: V1004 [CWE-476] Il-pointer 'Ptr' intuża b'mod mhux sikur wara li ġie vverifikat kontra nullptr. Iċċekkja linji: 729, 738. TargetTransformInfoImpl.h 738

Varjabbli ptr jistgħu jkunu ugwali nullptr, kif muri mill-kontroll:

if (Ptr != nullptr)

Madankollu, taħt dan il-pointer huwa dereferenced mingħajr verifika preliminari:

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

Ejja nikkunsidraw każ ieħor simili.

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

Twissija PVS-Studio: V1004 [CWE-476] Il-pointer 'FD' intuża b'mod mhux sigur wara li ġie vverifikat kontra nullptr. Iċċekkja linji: 3228, 3231. CGDebugInfo.cpp 3231

Oqgħod attent għas-sinjal FD. Jiena ċert li l-problema hija viżibbli b'mod ċar u mhi meħtieġa l-ebda spjegazzjoni speċjali.

U aktar:

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

Twissija PVS-Studio: V1004 [CWE-476] Il-pointer 'PtrTy' intuża b'mod mhux sigur wara li ġie vverifikat kontra nullptr. Iċċekkja linji: 960, 965. InterleavedLoadCombinePass.cpp 965

Kif tipproteġi lilek innifsek minn żbalji bħal dawn? Kun aktar attent fuq Code-Review u uża l-analizzatur statiku PVS-Studio biex tiċċekkja regolarment il-kodiċi tiegħek.

M'hemm l-ebda skop li tiċċita frammenti oħra ta 'kodiċi bi żbalji ta' dan it-tip. Se nħalli biss lista ta 'twissijiet fl-artiklu:

  • V1004 [CWE-476] Il-pointer 'Expr' intuża b'mod mhux sikur wara li ġie vverifikat kontra nullptr. Iċċekkja l-linji: 1049, 1078. DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] Il-pointer 'PI' intuża b'mod mhux sikur wara li ġie vverifikat kontra nullptr. Iċċekkja l-linji: 733, 753. LegacyPassManager.cpp 753
  • V1004 [CWE-476] Il-pointer 'StatepointCall' intuża b'mod mhux sikur wara li ġie vverifikat kontra nullptr. Iċċekkja linji: 4371, 4379. Verifier.cpp 4379
  • V1004 [CWE-476] Il-pointer 'RV' intuża b'mod mhux sikur wara li ġie vverifikat kontra nullptr. Iċċekkja linji: 2263, 2268. TGParser.cpp 2268
  • V1004 [CWE-476] Il-pointer 'CalleeFn' intuża b'mod mhux sigur wara li ġie vverifikat kontra nullptr. Iċċekkja l-linji: 1081, 1096. SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] Il-pointer 'TC' intuża b'mod mhux sikur wara li ġie vverifikat kontra nullptr. Iċċekkja linji: 1819, 1824. Driver.cpp 1824

Framment N48-N60: Mhux kritiku, iżda difett (tnixxija possibbli tal-memorja)

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

Twissija PVS-Studio: V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Istrateġiji' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-isel-fuzzer.cpp 58

Biex iżżid element fit-tarf ta 'kontenitur simili std::vector > ma tistax tikteb biss xxx.push_back (X ġdid), peress li m'hemm l-ebda konverżjoni impliċita minn X* в std::unique_ptr.

Soluzzjoni komuni hija li tikteb xxx.emplace_back(X ġdid)peress li jikkompila: metodu emplace_back jibni element direttament minn argumenti u għalhekk jista' juża kostrutturi espliċiti.

Mhuwiex sigur. Jekk il-vettur ikun mimli, allura l-memorja tiġi allokata mill-ġdid. L-operazzjoni ta' allokazzjoni mill-ġdid tal-memorja tista' tfalli, li tirriżulta f'eċċezzjoni li tintefa' std::bad_alloc. F'dan il-każ, il-pointer jintilef u l-oġġett maħluq qatt mhu se jitħassar.

Soluzzjoni sigura hija li toħloq unique_ptrli se jippossjedi l-pointer qabel ma l-vettur jipprova jalloka mill-ġdid il-memorja:

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

Minn C++14, tista' tuża 'std::make_unique':

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

Dan it-tip ta' difett mhuwiex kritiku għal LLVM. Jekk il-memorja ma tistax tiġi allokata, il-kompilatur sempliċement jieqaf. Madankollu, għal applikazzjonijiet b'tul uptime, li ma tistax tispiċċa biss jekk l-allokazzjoni tal-memorja tfalli, dan jista 'jkun bug diżgustanti reali.

Għalhekk, għalkemm dan il-kodiċi ma joħloqx theddida prattika għal LLVM, sibt utli li nitkellem dwar dan il-mudell ta 'żball u li l-analizzatur PVS-Studio tgħallem jidentifikah.

Twissijiet oħra ta’ dan it-tip:

  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Passes' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. PassManager.h 546
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'AAs' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. AliasAnalysis.h 324
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Entries' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'AllEdges' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. CFGMST.h 268
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'VMaps' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. SimpleLoopUnswitch.cpp 2012
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Records' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. FDRLogBuilder.h 30
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'PendingSubmodules' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. ModuleMap.cpp 810
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Oġġetti' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. DebugMap.cpp 88
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Istrateġiji' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 685
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 686
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 688
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 689
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 690
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 691
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 692
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 693
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Modifikaturi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. llvm-stress.cpp 694
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Operandi' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Stash' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] Pointer mingħajr sid huwa miżjud mal-kontenitur 'Matchers' bil-metodu 'emplace_back'. Tnixxija tal-memorja se sseħħ f'każ ta 'eċċezzjoni. GlobalISelEmitter.cpp 2702

Konklużjoni

Ħarġejt 60 twissija b’kollox u mbagħad waqaft. Hemm difetti oħra li l-analizzatur PVS-Studio jiskopri fl-LLVM? Iva għandi. Madankollu, meta kont qed nikteb frammenti tal-kodiċi għall-artiklu, kien tard filgħaxija, jew aħjar anke bil-lejl, u ddeċidejt li kien wasal iż-żmien li nsejħilha kuljum.

Nispera li sibtha interessanti u tkun trid tipprova l-analizzatur PVS-Studio.

Tista 'tniżżel l-analizzatur u tikseb iċ-ċavetta tal-minjieri fuq Din il-paġna.

L-aktar importanti, uża analiżi statika regolarment. Kontrolli ta' darba, imwettqa minna sabiex popolarizzaw il-metodoloġija ta 'analiżi statika u PVS-Studio mhumiex xenarju normali.

Xorti tajba fit-titjib tal-kwalità u l-affidabbiltà tal-kodiċi tiegħek!

Tfittxija bugs f'LLVM 8 billi tuża l-analizzatur PVS-Studio

Jekk trid taqsam dan l-artikolu ma 'udjenza li titkellem bl-Ingliż, jekk jogħġbok uża l-link tat-traduzzjoni: Andrey Karpov. Tfittxija Bugs f'LLVM 8 ma PVS-Studio.

Sors: www.habr.com

Żid kumment