Fabhtanna a aimsiú in LLVM 8 ag baint úsáide as an anailíseoir PVS-Studio

Fabhtanna a aimsiú in LLVM 8 ag baint úsáide as an anailíseoir PVS-Studio
Tá níos mó ná dhá bhliain caite ó rinneadh seiceáil cód dheireanach ar thionscadal LLVM ag baint úsáide as ár n-anailíseoir PVS-Studio. Déanaimis cinnte go bhfuil an anailísí PVS-Studio fós ina phríomhuirlis chun earráidí agus leochaileachtaí féideartha a aithint. Chun seo a dhéanamh, déanfaimid earráidí nua a sheiceáil agus a aimsiú san eisiúint LLVM 8.0.0.

Alt le scríobh

Le bheith macánta, ní raibh mé ag iarraidh an t-alt seo a scríobh. Níl sé suimiúil scríobh faoi thionscadal atá seiceáilte againn arís agus arís eile (1, 2, 3). Is fearr scríobh faoi rud éigin nua, ach níl aon rogha agam.

Gach uair a scaoiltear nó a nuashonraítear leagan nua de LLVM Anailíseoir Statach Clang, faighimid ceisteanna den chineál seo a leanas inár ríomhphost:

Féach, d'fhoghlaim an leagan nua de Anailíseoir Statach Clang conas earráidí nua a aimsiú! Feictear dom go bhfuil laghdú ag teacht ar ábharthacht úsáid PVS-Studio. Aimsíonn Clang níos mó earráidí ná mar a bhí roimhe agus cuireann sé suas le cumais PVS-Studio. Cad a cheapann tú faoi seo?

Chuige seo ba mhaith liom i gcónaí rud éigin mar seo a fhreagairt:

Ní shuíonn muid díomhaoin ach an oiread! Tá feabhas suntasach déanta againn ar chumais an anailísí PVS-Studio. Mar sin ná bí buartha, leanaimid orainn ag stiúradh mar a bhí roimhe seo.

Ar an drochuair, is drochfhreagra é seo. Níl aon cruthúnais ann. Agus is é sin an fáth go bhfuil an t-alt seo á scríobh agam anois. Mar sin, tá an tionscadal LLVM seiceáilte arís agus tá éagsúlacht earráidí aimsithe ann. Léireoidh mé anois iad siúd a raibh cuma spéisiúil ormsa orthu. Ní féidir le Anailíseoir Clang Statach na hearráidí seo a aimsiú (nó tá sé thar a bheith deacair é sin a dhéanamh lena chabhair). Ach is féidir linn. Thairis sin, fuair mé agus scríobh mé síos na hearráidí seo go léir i tráthnóna amháin.

Ach ghlac roinnt seachtainí leis an alt a scríobh. Ní raibh mé in ann mé féin a thabhairt liom chun é seo go léir a chur i téacs :).

Dála an scéil, má tá suim agat cad iad na teicneolaíochtaí a úsáidtear san anailíseoir PVS-Studio chun earráidí agus leochaileachtaí a d'fhéadfadh a bheith ann a aithint, molaim duit dul i dtaithí air seo. Nóta.

Diagnóisic nua agus sean

Mar a tugadh faoi deara cheana féin, timpeall dhá bhliain ó shin rinneadh an tionscadal LLVM a sheiceáil arís, agus ceartaíodh na hearráidí a aimsíodh. Anois beidh an t-alt seo i láthair bhaisc nua earráidí. Cén fáth a bhfuarthas fabhtanna nua? Tá 3 chúis leis seo:

  1. Tá an tionscadal LLVM ag athrú, ag athrú seanchód agus ag cur cód nua leis. Ar ndóigh, tá earráidí nua sa chód modhnaithe agus scríofa. Léiríonn sé seo go soiléir gur cheart anailís statach a úsáid go rialta, agus ní ó am go chéile. Léiríonn ár n-alt go maith cumais an anailísí PVS-Studio, ach níl baint ar bith aige seo le cáilíocht an chóid a fheabhsú agus an costas a bhaineann le earráidí a shocrú a laghdú. Bain úsáid as anailísí cód statach go rialta!
  2. Táimid ag tabhairt chun críche agus ag feabhsú diagnóisic reatha. Mar sin, is féidir leis an anailíseoir earráidí a aithint nár thug sé faoi deara le linn scanadh roimhe seo.
  3. Tá diagnóisic nua le feiceáil i PVS-Studio nach raibh ann 2 bhliain ó shin. Chinn mé aird a tharraingt orthu i rannóg ar leith chun forbairt PVS-Studio a thaispeáint go soiléir.

Lochtanna arna sainaithint ag diagnóisic a bhí ann 2 bhliain ó shin

Cuid N1: Cóip-Greamaigh

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

Rabhadh PVS-Studio: V501 [CWE-570] Tá na fo-léirithe comhionanna 'Name.startswith ("avx512.mask.permvar.")' ar chlé agus ar dheis den '||' oibreoir. Uath-uasghrádú.cpp 73

Déantar seiceáil faoi dhó go dtosaíonn an t-ainm leis an bhfotheaghrán "avx512.mask.permvar.". Sa dara seiceáil, ba léir gur theastaigh uathu rud éigin eile a scríobh, ach rinne siad dearmad ar an téacs cóipeáilte a cheartú.

Mír 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;
  ....
}

Rabhadh PVS-Studio: V501 Tá fo-léirithe comhionanna 'CXNameRange_WantQualifier' ar chlé agus ar dheis an '|' oibreoir. CIndex.cpp 7245

De bharr tíopála, úsáidtear an tairiseach ainmnithe céanna faoi dhó CXNameRange_WantQualifier.

Cuid N3: Mearbhall le tosaíocht oibreora

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

Rabhadh PVS-Studio: V502 [CWE-783] B’fhéidir go n-oibríonn an t-oibreoir ‘?:’ ar bhealach difriúil ná mar a bhíothas ag súil leis. Tá tosaíocht níos ísle ag an oibreoir '?:' ná ag an oibreoir '=='. PPCTargetTransformInfo.cpp 404

Is é mo thuairim gur botún an-álainn é seo. Sea, tá a fhios agam go bhfuil smaointe aisteach agam faoi áilleacht :).

Anois, de réir tosaíochtaí oibreora, déantar an slonn a mheas mar seo a leanas:

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

Ó thaobh praiticiúil, ní dhéanann coinníoll den sórt sin ciall, mar is féidir é a laghdú go dtí:

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

Is botún soiléir é seo. Is dócha go raibh siad ag iarraidh 0/1 a chur i gcomparáid le hathróg innéacs. Chun an cód a shocrú ní mór duit lúibíní a chur timpeall ar an oibreoir trínártha:

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

Dála an scéil, tá an t-oibreoir trínártha an-chontúirteach agus spreagann sé earráidí loighciúla. Bí an-chúramach leis agus ná bí sanntach le lúibíní. D'fhéach mé ar an ábhar seo níos mine anseo, sa chaibidil “Bí ar an airdeall ón ?: Oibreoir agus Cuir faoi Iamh é i mBáithreachas.”

Fragment N4, N5: Pointeoir 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;
  }
  ....
}

Rabhadh PVS-Studio: V522 [CWE-476] D’fhéadfadh sé go ndéanfaí an pointeoir nialasach ‘LHS’ a athshonrú. TGParser.cpp 2152

Má tá an pointeoir LHS ar neamhní, ba cheart rabhadh a eisiúint. Mar sin féin, ina ionad sin, déanfar an pointeoir nialasach céanna seo a dhífhostú: LHS->getAsString().

Is gnáthchás é seo nuair a bhíonn earráid i bhfolach i láimhseálaí earráide, toisc nach ndéanann aon duine tástáil orthu. Seiceálann anailíseoirí statacha gach cód insroichte, is cuma cé chomh minic a úsáidtear é. Is sampla an-mhaith é seo ar conas a chomhlánaíonn anailís statach teicnící tástála agus cosanta earráide eile.

Earráid láimhseála pointeora dá samhail HRH ceadaithe sa chód díreach thíos: V522 [CWE-476] D’fhéadfadh sé go ndéanfaí an pointeoir nialasach ‘RHS’ a dhífhostú. TGParser.cpp 2186

Fragment N6: Úsáid an pointeoir tar éis bogadh

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

Rabhadh PVS-Stiúideo: V522 [CWE-476] D’fhéadfadh sé go ndéanfaí an pointeoir nialasach ‘ProgClone’ a athshonrú. Miscompilation.cpp 601

Ag an tús pointeoir cliste ClárClone scoirfidh sé de bheith ina húinéir ar an réad:

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

Go deimhin, anois ClárClone is pointeoir nialasach. Mar sin, ba cheart go dtarlódh tagairt pointeora nialasach díreach thíos:

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

Ach, i ndáiríre, ní tharlóidh sé seo! Tabhair faoi deara nach bhfuil an lúb chun báis i ndáiríre.

Ag tús an choimeádáin Feidhmeanna Miscompiled glanta:

MiscompiledFunctions.clear();

Ansin, úsáidtear méid an choimeádáin seo sa riocht lúb:

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

Is furasta a fheiceáil nach dtosaíonn an lúb. Sílim gur fabht é seo freisin agus ba cheart an cód a scríobh ar bhealach difriúil.

Is cosúil gur tháinig muid ar an bpaireacht cháiliúil earráidí sin! Cuimsíonn botún amháin botún eile :).

Fragment N7: Úsáid an pointeoir tar éis bogadh

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

Rabhadh PVS-Stiúideo: V522 [CWE-476] D'fhéadfadh sé go ndéanfaí an pointeoir nialasach 'Tástáil' a athshonrú. Miscompilation.cpp 709

An scéal céanna arís. Ar dtús, bogtar ábhar an ruda, agus ansin úsáidtear é amhail is nár tharla aon rud. Feicim an cás seo níos mó agus níos minice i gcód cláir tar éis do shéimeantaic gluaiseachta a bheith le feiceáil in C++. Sin é an fáth gur breá liom an teanga C++! Tá níos mó agus níos mó bealaí nua ann chun do chos féin a scaoileadh. Beidh obair i gcónaí ag an anailísí PVS-Studio :).

Mír N8: Pointeoir 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);
}

Rabhadh PVS-Stiúideo: V522 [CWE-476] D’fhéadfadh sé go ndéanfaí an pointeoir nialasach ‘Cineál’ a dhífhostú. PrettyFunctionDumper.cpp 233

Chomh maith le láimhseálaithe earráide, ní dhéantar tástáil ar fheidhmeanna asphrionta dífhabhtaithe de ghnáth. Níl ach a leithéid de chás os ár gcomhair. Tá an fheidhm ag fanacht leis an úsáideoir, a bheidh, in ionad a chuid fadhbanna a réiteach, iallach a shocrú é.

Ceart:

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

Mír N9: Pointeoir 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());
   ....
}

Rabhadh PVS-Stiúideo: V522 [CWE-476] D’fhéadfadh sé go ndéanfaí an pointeoir nialasach ‘Ty’ a athshonrú. InchuardaitheTableEmitter.cpp 614

Sílim go bhfuil gach rud soiléir agus nach gá míniú.

Mír 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;
}

Rabhadh PVS-Studio: V570 Sanntar an athróg 'Aitheantóir->Cineál' dó féin. FormatTokenLexer.cpp 249

Níl aon phointe ag baint le hathróg a shannadh dó féin. Is dócha gur theastaigh uathu scríobh:

Identifier->Type = Question->Type;

Fragment N11: Briseadh amhrasach

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

Rabhadh PVS-Studio: V622 [CWE-478] Smaoinigh ar an ráiteas ‘lasc’ a iniúchadh. Is féidir go bhfuil an chéad oibreoir 'cás' in easnamh. SystemZAsmParser.cpp 652

Tá oibreoir an-amhrasach ag an tús bhriseadh. An ndearna tú dearmad rud éigin eile a scríobh anseo?

Cuid N12: Pointeoir a sheiceáil tar éis díthagairt a dhéanamh

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

Rabhadh PVS-Studio: V595 [CWE-476] Úsáideadh an pointeoir ‘Callee’ sular fíoraíodh é i gcoinne nullptr. Línte seiceála: 172, 174. AMDGPUInline.cpp 172

Pointeoir Callee ag an tús tá dereferenced ag an am a dtugtar an fheidhm faighTTI.

Agus ansin tharlaíonn sé gur chóir an pointeoir seo a sheiceáil le haghaidh comhionannais nullptr:

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

Ach tá sé ró-dhéanach…

Fragment N13 - N...: Pointeoir a sheiceáil tar éis díthagairt

Níl an scéal a pléadh sa bhlúire cód roimhe seo uathúil. Tá sé le feiceáil anseo:

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

Rabhadh PVS-Studio: V595 [CWE-476] Úsáideadh an pointeoir ‘CalleeFn’ sular fíoraíodh é i gcoinne nullptr. Línte seiceála: 1079, 1081. SimplifyLibCalls.cpp 1079

Agus anseo:

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

Rabhadh PVS-Studio: V595 [CWE-476] Úsáideadh an pointeoir 'ND' sular fíoraíodh é i gcoinne nullptr. Seiceáil línte: 532, 534. SemaTemplateInstantiateDecl.cpp 532

Agus anseo:

  • V595 [CWE-476] Úsáideadh an pointeoir 'U' sular fíoraíodh é i gcoinne nullptr. Línte seiceála: 404, 407. DWARFormValue.cpp 404
  • V595 [CWE-476] Úsáideadh an pointeoir 'ND' sular fíoraíodh é i gcoinne nullptr. Línte seiceála: 2149, 2151. SemaTemplateInstantiate.cpp 2149

Agus ansin níor bhain mé leas as staidéar a dhéanamh ar na rabhaidh leis an uimhir V595. Mar sin níl a fhios agam an bhfuil níos mó earráidí cosúla seachas na cinn atá liostaithe anseo. Is dócha go bhfuil.

Fragment N17, N18: Aistriú amhrasach

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

Rabhadh PVS-Studio: V629 [CWE-190] Smaoinigh ar an slonn '~ (Méid - 1) << 1' a iniúchadh. Aistriú giotán den luach 32-giotán agus leathnú ina dhiaidh sin chuig an gcineál 64-giotán. AArch64AddressingModes.h 260

Seans nach fabht atá ann agus oibríonn an cód go díreach mar a bhí beartaithe. Ach is léir gur áit an-amhrasach é seo agus ní mór é a sheiceáil.

Ligean le rá an athróg méid comhionann le 16, agus ansin bheartaigh údar an chóid é a fháil in athróg nimms luach:

1111111111111111111111111111111111111111111111111111111111100000

Mar sin féin, i ndáiríre beidh an toradh:

0000000000000000000000000000000011111111111111111111111111100000

Is é fírinne an scéil go dtarlaíonn gach ríomh ag baint úsáide as an gcineál 32-giotán gan síniú. Agus ansin amháin, déanfar an cineál 32-giotán seo gan síniú a leathnú go hintuigthe uint64_t. Sa chás seo, beidh na giotáin is suntasaí náid.

Is féidir leat an cás a shocrú mar seo:

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

Cás cosúil leis: V629 [CWE-190] Smaoinigh ar an slonn 'Immr << 6' a iniúchadh. Aistriú giotán den luach 32-giotán agus leathnú ina dhiaidh sin chuig an gcineál 64-giotán. AArch64AddressingModes.h 269

Fragment N19: Eochairfhocal ar iarraidh eile?

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

Rabhadh PVS-Studio: V646 [CWE-670] Smaoinigh ar loighic an fheidhmchláir a iniúchadh. Seans go bhfuil eochairfhocal ‘eile’ in easnamh. AMDGPUAsmParser.cpp 5655

Níl aon botún anseo. Ó tharla an bloc sin den chéad uair if chríochnaíonn le leanúint ar aghaidh, ansin is cuma, tá eochairfhocal eile nó nach bhfuil. Nó slí oibreoidh an cód mar an gcéanna. Fós caillte eile a dhéanann an cód níos doiléir agus contúirteacha. Más rud é sa todhchaí leanúint ar aghaidh disappears, beidh an cód tosú ag obair go hiomlán difriúil. Is é mo thuairim go bhfuil sé níos fearr a chur leis eile.

Fragment N20: Ceithre clóscríobhán den chineál céanna

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

Rabhadh PVS-Studio:

  • V655 [CWE-480] Comhdhlúthaíodh na teaghráin ach ní úsáidtear iad. Smaoinigh ar an slonn 'Torthaí + Ainm.str()' a iniúchadh. Siombail.cpp 32
  • V655 [CWE-480] Comhdhlúthaíodh na teaghráin ach ní úsáidtear iad. Smaoinigh ar an slonn 'Toradh + "(ObjC Class)" + Name.str()' a iniúchadh. Siombail.cpp 35
  • V655 [CWE-480] Comhdhlúthaíodh na teaghráin ach ní úsáidtear iad. Smaoinigh ar an slonn 'Toradh + "(ObjC Class EH)" + Name.str()' a iniúchadh. Siombail.cpp 38
  • V655 [CWE-480] Comhdhlúthaíodh na teaghráin ach ní úsáidtear iad. Smaoinigh ar an slonn 'Toradh + "(ObjC IVar)" + Name.str()' a iniúchadh. Siombail.cpp 41

Trí thimpiste, úsáidtear an t-oibreoir + in ionad an oibreora +=. Is é an toradh ná dearaí nach bhfuil brí leo.

Fragment N21: Iompar neamhshainithe

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

Déan iarracht an cód contúirteach a aimsiú duit féin. Agus is pictiúr é seo chun aird a tharraingt ar shiúl ionas nach bhféachtar láithreach ar an bhfreagra:

Fabhtanna a aimsiú in LLVM 8 ag baint úsáide as an anailíseoir PVS-Studio

Rabhadh PVS-Studio: V708 [CWE-758] Úsáidtear tógáil chontúirteach: 'FeaturesMap[Op] = FeaturesMap.size()', áit a bhfuil 'FeaturesMap' den aicme 'mapa'. D'fhéadfadh iompar neamhshainithe a bheith mar thoradh air seo. RISCVCCompressInstEmitter.cpp 490

Líne fhadhb:

FeaturesMap[Op] = FeaturesMap.size();

Más eilimint Op Ní fhaightear, ansin cruthaítear eilimint nua sa léarscáil agus scríobhtar líon na ndúl sa léarscáil seo ann. Níl a fhios ach an dtabharfar an fheidhm méid roimh nó tar éis eilimint nua a chur leis.

Fragment N22-N24: Tascanna arís agus arís eile

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

Rabhadh PVS-Studio: V519 [CWE-563] Sanntar luachanna don athróg ‘NType’ faoi dhó as a chéile. B’fhéidir gur botún é seo. Línte seiceála: 1663, 1664. MachOObjectFile.cpp 1664

Ní dóigh liom go bhfuil botún fíor anseo. Just a sannadh arís agus arís eile gan ghá. Ach fós botún.

Mar an gcéanna:

  • V519 [CWE-563] Sanntar luachanna don athróg ‘B.NDesc’ faoi dhó as a chéile. B’fhéidir gur botún é seo. Línte seiceála: 1488, 1489. llvm-nm.cpp 1489
  • V519 [CWE-563] Sanntar luachanna don athróg faoi dhó as a chéile. B’fhéidir gur botún é seo. Seiceáil línte: 59, 61. coff2yaml.cpp 61

Fragment N25-N27: Tuilleadh athshannta

Anois, déanaimis féachaint ar leagan beagán difriúil den athshannadh.

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

Rabhadh PVS-Stiúideo: V519 [CWE-563] Sanntar luachanna don athróg ‘Ailíniú’ dhá uair as a chéile. B’fhéidir gur botún é seo. Seiceáil línte: 1158, 1160. LoadStoreVectorizer.cpp 1160

Is é seo an cód an-aisteach go bhfuil cosúil earráid loighciúil. Ag an tús, athraitheach Ailíniú sanntar luach ag brath ar an gcoinníoll. Agus ansin tarlaíonn an tasc arís, ach anois gan aon seiceáil.

Tá cásanna cosúla le feiceáil anseo:

  • V519 [CWE-563] Sanntar luachanna don athróg ‘Éifeachtaí’ faoi dhó as a chéile. B’fhéidir gur botún é seo. Línte seiceála: 152, 165. WebAssemblyRegStackify.cpp 165
  • V519 [CWE-563] Sanntar luachanna don athróg ‘ExpectNoDerefChunk’ faoi dhó as a chéile. B’fhéidir gur botún é seo. Línte seiceála: 4970, 4973. SemaType.cpp 4973

Mír N28: Bail fíor i gcónaí

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

Rabhadh PVS-Studio: V547 [CWE-571] Tá an abairt ‘nextByte!= 0x90’ fíor i gcónaí. X86DisassemblerDecoder.cpp 379

Ní dhéanann seiceáil ciall. Athróg nextByte i gcónaí nach ionann an luach 0x90, a leanann ón seiceáil roimhe seo. Is earráid loighciúil de shaghas éigin é seo.

Cuid N29 - N...: Coinníollacha fíor/bréagacha i gcónaí

Eisíonn an anailíseoir go leor rabhadh go bhfuil an coinníoll iomlán (V547) nó cuid de (V560) fíor nó bréagach i gcónaí. Go minic ní earráidí fíor iad seo, ach go simplí cód sloppy, mar thoradh ar leathnú macra, agus a leithéidí. Mar sin féin, tá sé ciallmhar breathnú ar na rabhaidh seo go léir, toisc go dtarlaíonn fíorearráidí loighciúla ó am go chéile. Mar shampla, tá an chuid seo den chód amhrasach:

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

Rabhadh PVS-Studio: V560 [CWE-570] Bíonn cuid den léiriú coinníollach bréagach i gcónaí: RegNo == 0xe. ARMDisassembler.cpp 939

Is é an tairiseach 0xE an luach 14 i deachúil. Scrúdú Rial Níl == 0xe nach bhfuil ciall leis mar má Rial > 13, ansin déanfaidh an fheidhm a fhorghníomhú i gcrích.

Bhí go leor rabhadh eile le IDs V547 agus V560, ach mar a bhí V595, ní raibh suim agam staidéar a dhéanamh ar na rabhaidh seo. Bhí sé soiléir cheana féin go raibh go leor ábhar agam chun alt a scríobh :). Mar sin, ní fios cé mhéad earráid den chineál seo is féidir a aithint in LLVM ag baint úsáide as PVS-Studio.

Tabharfaidh mé sampla duit de cén fáth a bhfuil sé leadránach staidéar a dhéanamh ar na truicear seo. Tá an anailíseoir go hiomlán ceart agus é ag eisiúint rabhadh don chód seo a leanas. Ach ní botún é seo.

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

Rabhadh PVS-Stiúideo: V547 [CWE-570] Léiriú '!HasError' i gcónaí bréagach. UnwrappedLineParser.cpp 1635

Fragment N30: ​​Fill ar ais amhrasach

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

Rabhadh PVS-Studio: V612 [CWE-670] ‘Filleadh’ gan choinníoll laistigh de lúb. R600OptimizeVectorRegisters.cpp 63

Earráid nó teicníocht ar leith é seo atá beartaithe chun rud éigin a mhíniú do ríomhchláraitheoirí a léann an cód. Ní mhíníonn an dearadh seo aon rud dom agus tá cuma an-amhrasach air. Is fearr gan scríobh mar sin :).

Tuirseach? Ansin tá sé in am tae nó caife a dhéanamh.

Fabhtanna a aimsiú in LLVM 8 ag baint úsáide as an anailíseoir PVS-Studio

Lochtanna arna sainaithint ag diagnóisic nua

Sílim gur leor 30 gníomhachtú diagnóisic d'aois. Feicfimid anois cad iad na rudaí suimiúla is féidir a fháil leis na diagnóisic nua a bhí le feiceáil san anailíseoir ina dhiaidh sin roimhe seo seiceanna. Le linn an ama seo, cuireadh 66 dhiagnóisiú ginearálta san iomlán leis an anailísí C++.

Fragment N31: Cód dosroichte

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

Rabhadh PVS-Studio: V779 [CWE-561] Cód dorochtana aimsithe. Is féidir go bhfuil earráid i láthair. ExecutionUtils.cpp 146

Mar a fheiceann tú, an dá bhrainse den oibreoir if chríochnaíonn sé le glaoch ar an oibreoir ar ais. Dá réir sin, an coimeádán CtorDtorsByTosaíocht ní bheidh glanta.

Fragment N32: Cód dosroichte

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

Rabhadh PVS-Stiúideo: V779 [CWE-561] Cód dosroichte braite. Is féidir go bhfuil earráid i láthair. LLParser.cpp 835

Staid suimiúil. Breathnaímid ar an áit seo ar dtús:

return ParseTypeIdEntry(SummaryID);
break;

Ar an gcéad amharc, is cosúil nach bhfuil aon earráid anseo. Breathnaíonn sé cosúil leis an oibreoir bhriseadh tá ceann breise anseo, agus is féidir leat a scriosadh go simplí. Mar sin féin, ní léir chomh simplí.

Eisíonn an anailíseoir rabhadh ar na línte:

Lex.setIgnoreColonInIdentifiers(false);
return false;

Agus go deimhin, níl an cód seo inrochtana. Gach cás i aistriú chríochnaíonn sé le glao ón oibreoir ar ais. Agus anois senseless ina n-aonar bhriseadh nach cuma chomh neamhdhíobhálach! B'fhéidir gur chóir go mbeadh deireadh le ceann de na brainsí bhriseadh, ní ar ar ais?

Fragment N33: Athshocrú randamach ar ghiotán arda

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

Rabhadh PVS-Studio: V784 Tá méid an masc giotán níos lú ná méid an chéad operand. Beidh sé seo ina chúis le caillteanas giotán níos airde. RuntimeDild.cpp 815

Tabhair faoi deara go bhfuil an fheidhm getStubAilíniú cineál tuairisceáin gan síniú. Déanaimis luach an slonn a ríomh, ag glacadh leis go dtugann an fheidhm an luach 8 ar ais:

~(getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

Anois faoi deara go bhfuil an athróg Méid Sonraí tá cineál 64-giotán gan síniú aige. Tharlaíonn sé go raibh nuair a bheidh an oibríocht DataSize & 0xFFFFFFF8u á dhéanamh, athshocrófar na tríocha dó giotán ard-ordú go nialas. Is dócha, ní hé seo an rud a theastaigh ón ríomhchláraitheoir. Doigh liom go raibh sé ag iarraidh a ríomh: DataSize & 0xFFFFFFFFFFFFFFF8u.

Chun an earráid a réiteach, ba cheart duit é seo a scríobh:

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

Nó mar sin:

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

Fragment N34: Teip den chineál follasach

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

Rabhadh PVS-Studio: V1028 [CWE-190] Cur thar maoil a d’fhéadfadh a bheith ann. Smaoinigh ar oibríochtaí an oibreora 'NumElts * Scale' a réitigh go dtí an cineál 'size_t', ní an toradh. X86ISelLowering.h 1577

Úsáidtear cineál réitigh follasach chun ró-shreabhadh a sheachaint nuair a bhíonn athróga cineáil á iolrú int. Mar sin féin, ní chosnaíonn cineál-réitigh sainráite anseo in aghaidh ró-shreabhadh. Ar dtús, déanfar na hathróga a iolrú, agus go dtí sin leathnófar toradh 32-giotán an iolrúcháin go dtí an cineál méid_t.

Fragment N35: Cóip-Greamú Theip

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] Fuarthas dhá mhír chóid chomhchosúla. B’fhéidir gur athróg typo é seo agus ba cheart athróg ‘Op1’ a úsáid in ionad ‘Op0’. InstCombineCompares.cpp 5507

Aithníonn an dhiagnóiseach spéisiúil nua seo cásanna ina ndearnadh cóip de chód agus inar tosaíodh ar roinnt ainmneacha a athrú, ach in aon áit amháin níor cheartaigh siad é.

Tabhair faoi deara gur athraigh siad sa dara bloc Op0 ar Op1. Ach in aon áit amháin níor réitigh siad é. Is dócha gur cheart é a bheith scríofa mar seo:

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

Cuid N36: Mearbhall Athraitheach

struct Status {
  unsigned Mask;
  unsigned Mode;

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

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

Rabhadh PVS-Studio: V1001 [CWE-563] Sanntar an athróg ‘Mód’ ach ní úsáidtear í faoi dheireadh na feidhme. SIModeRegister.cpp 48

Tá sé an-chontúirteach na hainmneacha céanna a thabhairt d’argóintí feidhme agus baill ranga. Tá sé an-éasca a bheith ar dhaoine eatarthu. Níl ach a leithéid de chás os ár gcomhair. Ní dhéanann an slonn seo ciall:

Mode &= Mask;

Athraíonn argóint na feidhme. Sin é an méid. Ní úsáidtear an argóint seo a thuilleadh. Is dócha gur cheart duit é a scríobh mar seo:

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

Cuid N37: Mearbhall Athraitheach

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

Rabhadh PVS-Studio: V1001 [CWE-563] Sanntar an athróg ‘Méid’ ach ní úsáidtear í faoi dheireadh na feidhme. Réad.cpp 424

Tá an scéal cosúil leis an gceann roimhe seo. Ba chóir a scríobh:

this->Size += this->EntrySize;

Fragment N38-N47: Rinne siad dearmad an t-innéacs a sheiceáil

Roimhe seo, d’fhéachamar ar shamplaí de thrioblóidí diagnóiseacha V595. Is é an bunús atá leis ná go ndéantar díragairt ar an bpointeoir ag an tús, agus ní dhéantar é a sheiceáil ach ansin. Diagnóisic óga V1004 a mhalairt i gciall, ach freisin nochtann a lán de na hearráidí. Sainaithníonn sé cásanna inar seiceáladh an pointeoir ag an tús agus ina ndearnadh dearmad ansin. Breathnaímid ar chásanna den sórt sin a fhaightear taobh istigh de 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());  // <=
  ....
}

Rabhadh PVS-Studio: V1004 [CWE-476] Úsáideadh an pointeoir 'Ptr' go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 729, 738. TargetTransformInfoImpl.h 738

Athróg Ptr féadfaidh sé a bheith comhionann nullptr, mar is léir ón seic:

if (Ptr != nullptr)

Mar sin féin, faoi bhun an phointeora seo dírítear aird orthu gan réamhsheiceáil:

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

Déanaimis cás eile den chineál céanna a mheas.

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

Rabhadh PVS-Studio: V1004 [CWE-476] Úsáideadh an pointeoir 'FD' go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 3228, 3231. CGDebugInfo.cpp 3231

Tabhair aird ar an gcomhartha FD. Táim cinnte go bhfuil an fhadhb le feiceáil go soiléir agus níl aon mhíniú speisialta ag teastáil.

Agus a thuilleadh:

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

Rabhadh PVS-Studio: V1004 [CWE-476] Úsáideadh an pointeoir 'PtrTy' go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 960, 965. InterleavedLoadCombinePass.cpp 965

Conas tú féin a chosaint ó earráidí den sórt sin? Bí níos airdeallaí ar Athbhreithniú Cód agus bain úsáid as an anailísí statach PVS-Studio chun do chód a sheiceáil go rialta.

Ní fiú blúirí cód eile a lua le hearráidí den chineál seo. Ní fhágfaidh mé ach liosta rabhaidh san alt:

  • V1004 [CWE-476] Úsáideadh an pointeoir ‘Expr’ go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 1049, 1078. DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] Úsáideadh an pointeoir ‘PI’ go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 733, 753. LegacyPassManager.cpp 753
  • V1004 [CWE-476] Úsáideadh an pointeoir ‘StatepointCall’ go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 4371, 4379. Verifier.cpp 4379
  • V1004 [CWE-476] Úsáideadh an pointeoir ‘RV’ go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 2263, 2268. TGParser.cpp 2268
  • V1004 [CWE-476] Úsáideadh an pointeoir ‘CalleeFn’ go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 1081, 1096. SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] Úsáideadh an pointeoir ‘TC’ go neamhshábháilte tar éis é a fhíorú i gcoinne nullptr. Línte seiceála: 1819, 1824. Driver.cpp 1824

Fragment N48-N60: Níl sé ríthábhachtach, ach locht (sceitheadh ​​cuimhne féideartha)

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

Rabhadh PVS-Studio: V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘Strategies’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-isel-fuzzer.cpp 58

Chun eilimint a chur le deireadh coimeádán cosúil le std::veicteoir > ní féidir leat scríobh go díreach xxx.push_back(X nua), ós rud é nach bhfuil aon chomhshó intuigthe ó X* в std:: uathúil_ptr.

Réiteach coitianta ná scríobh xxx.emplace_back(X nua)ó tiomsaíonn sé: modh emplace_back tógann sé eilimint go díreach óna hargóintí agus dá bhrí sin is féidir leis cruthaitheoirí follasacha a úsáid.

Níl sé sábháilte. Má tá an veicteoir lán, ansin déantar an chuimhne a ath-leithdháileadh. D’fhéadfadh go dteipfeadh ar an oibríocht ath-leithdháilte cuimhne, agus mar thoradh air sin caitear eisceacht std:: bad_alloc. Sa chás seo, caillfear an pointeoir agus ní scriosfar an réad cruthaithe choíche.

Tá réiteach sábháilte a chruthú uathúil_ptrag a mbeidh an pointeoir féin sula ndéanann an veicteoir iarracht cuimhne a athdháileadh:

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

Ó C++14, is féidir leat 'std::make_unique' a úsáid:

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

Níl an cineál seo fabht ríthábhachtach do LLVM. Mura féidir cuimhne a leithdháileadh, stopfaidh an tiomsaitheoir. Mar sin féin, le haghaidh iarratas le fada Aga fónaimh, nach féidir a fhoirceannadh díreach má theipeann ar leithdháileadh cuimhne, is féidir leis seo a bheith ina fhabht olc.

Mar sin, cé nach bhfuil an cód seo ina bhagairt phraiticiúil do LLVM, fuair mé go raibh sé úsáideach labhairt faoin bpatrún earráide seo agus gur fhoghlaim an anailísí PVS-Studio é a aithint.

Rabhadh eile den chineál seo:

  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Pasanna' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. PassManager.h 546
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘AAs’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. AiliasAnail.h 324
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Iontrálacha' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘AllEdges’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. CFGMST.h 268
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'VMaps' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. SimpleLoopUnswitch.cpp 2012
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘Records’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. FDRLogBuilder.h 30
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘PendingSubmodules’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. ModuleMap.cpp 810
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘Objects’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. DebugMap.cpp 88
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Straitéisí' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 685
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 686
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 688
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 689
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 690
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 691
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 692
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 693
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Athraithe' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. llvm-strus.cpp 694
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘Operands’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán ‘Stash’ tríd an modh ‘emplace_back’. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] Cuirtear pointeoir gan úinéir leis an gcoimeádán 'Matchers' tríd an modh 'emplace_back'. Tarlóidh sceitheadh ​​cuimhne i gcás eisceachta. GlobalISelEmitter.cpp 2702

Conclúid

D'eisigh mé 60 rabhadh san iomlán agus stop mé ansin. An bhfuil lochtanna eile ann a bhraitheann an t-anailísí PVS-Studio in LLVM? Sea, tá agam. Mar sin féin, nuair a bhí blúirí cód á scríobh agam don alt, bhí sé déanach tráthnóna, nó in áit fiú oíche, agus chinn mé go raibh sé in am é a ghlaoch in aghaidh an lae.

Tá súil agam go raibh sé suimiúil duit agus go mbeidh tú ag iarraidh triail a bhaint as an anailísí PVS-Studio.

Is féidir leat an anailíseoir a íoslódáil agus an eochair minesweeper a fháil ag an leathanach seo.

Níos tábhachtaí fós, bain úsáid as anailís statach go rialta. Seiceálacha aonuaire, a rinne muid d'fhonn an mhodheolaíocht anailís statach a popularize agus nach bhfuil PVS-Studio cás gnáth.

Ádh mór i bhfeabhsú cáilíocht agus iontaofacht do chód!

Fabhtanna a aimsiú in LLVM 8 ag baint úsáide as an anailíseoir PVS-Studio

Más mian leat an t-alt seo a roinnt le lucht féachana Béarla, bain úsáid as an nasc aistriúcháin: Andrey Karpov. Bugs a Lorg in LLVM 8 le PVS-Studio.

Foinse: will.com

Add a comment