A’ lorg bhiteagan ann an LLVM 8 a’ cleachdadh an anailisiche PVS-Studio

A’ lorg bhiteagan ann an LLVM 8 a’ cleachdadh an anailisiche PVS-Studio
Tha còrr air dà bhliadhna air a dhol seachad bhon sgrùdadh còd mu dheireadh den phròiseact LLVM a’ cleachdadh ar n-anailisiche PVS-Studio. Dèan cinnteach gu bheil an anailisiche PVS-Studio fhathast na phrìomh inneal airson mearachdan agus so-leòntachd a chomharrachadh. Gus seo a dhèanamh, nì sinn sgrùdadh agus lorgaidh sinn mearachdan ùra anns an naidheachd LLVM 8.0.0.

Artaigil ri sgrìobhadh

Gus a bhith onarach, cha robh mi airson an artaigil seo a sgrìobhadh. Chan eil e inntinneach sgrìobhadh mu phròiseact air an do rinn sinn sgrùdadh grunn thursan (1, 2, 3). Tha e nas fheàrr sgrìobhadh mu rudeigin ùr, ach chan eil roghainn agam.

Gach uair a thèid dreach ùr de LLVM fhoillseachadh no ùrachadh Mion-sgrùdaire Clang Statach, gheibh sinn ceistean den t-seòrsa a leanas nar post:

Seall, tha an dreach ùr de Clang Static Analyzer air ionnsachadh gus mearachdan ùra a lorg! Tha e coltach rium gu bheil iomchaidheachd cleachdadh PVS-Studio a’ dol sìos. Bidh Clang a’ lorg barrachd mhearachdan na bha e roimhe agus a’ togail suas ri comasan PVS-Studio. Dè do bheachd air seo?

Airson seo tha mi an-còmhnaidh ag iarraidh rudeigin mar seo a fhreagairt:

Cha bhith sinn a’ suidhe leisg idir! Tha sinn air comasan an anailisiche PVS-Studio a leasachadh gu mòr. Mar sin na gabh dragh, cumaidh sinn oirnn a’ stiùireadh mar a bha sinn roimhe.

Gu mì-fhortanach, is e droch fhreagairt a tha seo. Chan eil dearbhadh sam bith ann. Agus is ann air sgàth sin a tha mi a’ sgrìobhadh an artaigil seo a-nis. Mar sin, chaidh am pròiseact LLVM a sgrùdadh a-rithist agus chaidh grunn mhearachdan a lorg ann. Seallaidh mi a-nis an fheadhainn a bha inntinneach dhomh. Chan urrainn do Clang Static Analyzer na mearachdan sin a lorg (no tha e air leth mì-ghoireasach sin a dhèanamh le a chuideachadh). Ach is urrainn dhuinn. A bharrachd air an sin, lorg mi agus sgrìobh mi sìos na mearachdan sin uile ann an aon fheasgar.

Ach thug sgrìobhadh an artaigil grunn sheachdainean. Cha b’ urrainn dhomh mi fhìn a thoirt leam airson seo uile a chuir ann an teacsa :).

Co-dhiù, ma tha ùidh agad anns na teicneòlasan a thathas a’ cleachdadh anns an anailisiche PVS-Studio gus mearachdan agus so-leòntachd a chomharrachadh, tha mi a’ moladh eòlas fhaighinn air an seo. nota.

Diagnosachd ùr is sean

Mar a chaidh ainmeachadh cheana, timcheall air dà bhliadhna air ais chaidh am pròiseact LLVM a sgrùdadh a-rithist, agus chaidh na mearachdan a chaidh a lorg a cheartachadh. A-nis nochdaidh an artaigil seo baidse ùr de mhearachdan. Carson a chaidh biastagan ùra a lorg? Tha 3 adhbharan airson seo:

  1. Tha am pròiseact LLVM ag atharrachadh, ag atharrachadh seann chòd agus a’ cur còd ùr ris. Gu nàdarra, tha mearachdan ùra anns a’ chòd atharraichte agus sgrìobhte. Tha seo a’ sealltainn gu soilleir gum bu chòir mion-sgrùdadh statach a chleachdadh gu cunbhalach, agus chan ann bho àm gu àm. Tha na h-artaigilean againn a’ nochdadh gu math comasan an anailisiche PVS-Studio, ach chan eil gnothach aig seo ri bhith a’ leasachadh càileachd còd agus a’ lughdachadh cosgais mearachdan a chàradh. Cleachd anailisiche còd statach gu cunbhalach!
  2. Tha sinn a’ cur crìoch air agus ag adhartachadh diagnosachd gnàthaichte. Mar sin, faodaidh an anailisiche mearachdan a chomharrachadh nach do mhothaich e rè sganaidhean roimhe.
  3. Tha diagnosachd ùr air nochdadh ann am PVS-Studio nach robh ann o chionn 2 bhliadhna. Cho-dhùin mi an comharrachadh ann an earrann air leth gus leasachadh PVS-Studio a nochdadh gu soilleir.

Duilgheadasan air an comharrachadh le diagnosachd a bha ann o chionn 2 bhliadhna

Earrann N1: Copy-Paste

static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
  if (Name == "addcarryx.u32" || // Added in 8.0
    ....
    Name == "avx512.mask.cvtps2pd.128" || // Added in 7.0
    Name == "avx512.mask.cvtps2pd.256" || // Added in 7.0
    Name == "avx512.cvtusi2sd" || // Added in 7.0
    Name.startswith("avx512.mask.permvar.") || // Added in 7.0     // <=
    Name.startswith("avx512.mask.permvar.") || // Added in 7.0     // <=
    Name == "sse2.pmulu.dq" || // Added in 7.0
    Name == "sse41.pmuldq" || // Added in 7.0
    Name == "avx2.pmulu.dq" || // Added in 7.0
  ....
}

Rabhadh PVS-Studio: V501 [CWE-570] Tha co-ionann fo-fhrith-bheachdan 'Name.startswith ("avx512.mask.permvar.")' air an taobh chlì agus air an làimh dheis den '||' gnìomhaiche. Ùrachadh gu fèin-ghluasadach.cpp 73

Thathas a’ dèanamh sgrùdadh dùbailte air gu bheil an t-ainm a’ tòiseachadh leis an fho-earrann “avx512.mask.permvar.”. Anns an dàrna seic, bha e follaiseach gu robh iad airson rudeigin eile a sgrìobhadh, ach dhìochuimhnich iad an teacsa a chaidh a chopaigeadh a cheartachadh.

Earrann 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 Tha na h-aon fho-aithrisean 'CXNameRange_WantQualifier' air an taobh chlì agus air taobh deas an '|' gnìomhaiche. Cindex.cpp 7245

Air sgàth typo, bidh an aon sheasmhach ainmichte air a chleachdadh dà uair CXNameRange_WantQualifier.

Pàirt N3: Mì-chinnt le prìomhachas gnìomhaiche

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] Is dòcha gu bheil an gnìomhaiche ‘?:’ ag obair ann an dòigh eadar-dhealaichte na bha dùil. Tha prìomhachas nas ìsle aig a' ghnìomhaiche '?:' na an gnìomhaiche '=='. PPCTargetTransformInfo.cpp 404

Nam bheachd-sa, is e mearachd glè bhrèagha a tha seo. Tha, tha fios agam gu bheil beachdan neònach agam mu bhòidhchead :).

A-nis, a rèir prìomhachasan gnìomhaiche, tha an abairt air a mheasadh mar a leanas:

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

Bho shealladh practaigeach, chan eil a leithid de staid a 'dèanamh ciall, oir faodar a lùghdachadh gu:

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

Is e mearachd soilleir a tha seo. Nas coltaiche, bha iad airson coimeas a dhèanamh eadar 0/1 le caochladair Clàr-innse. Gus an còd a chàradh feumaidh tu bragan a chuir timcheall air a’ ghnìomhaiche ternary:

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

Air an t-slighe, tha an gnìomhaiche ternary gu math cunnartach agus a 'brosnachadh mhearachdan loidsigeach. Bi gu math faiceallach leis agus na bi sanntach le bragan. Thug mi sùil nas mionaidiche air a’ chuspair seo an seo, anns a’ chaibideil “Bi faiceallach mun ?: Gnìomhaiche agus Cuir a-steach e ann am Pàrantan.”

Criomag N4, N5: Puing neonach

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] Dh’ fhaodadh gun tèid iomradh a thoirt air a’ phuing neo-null ‘LHS’. TGParser.cpp 2152

Ma tha am puing LHS tha e null, bu chòir rabhadh a thoirt seachad. Ach, an àite sin, thèid an aon phuing null seo a thoirt às: LHS-> getAsString().

Is e suidheachadh gu math àbhaisteach a tha seo nuair a tha mearachd falaichte ann an làimhseachadh mearachd, leis nach eil duine gan deuchainn. Bidh sgrùdairean statach a’ sgrùdadh a h-uile còd ruigsinneach, ge bith dè cho tric sa thèid a chleachdadh. Is e fìor dheagh eisimpleir a tha seo air mar a tha mion-sgrùdadh statach a’ cur ri dòighean deuchainn agus dìon mhearachdan eile.

Mearachd làimhseachaidh puing coltach ris RHS ceadaichte sa chòd dìreach gu h-ìosal: V522 [CWE-476] Dh’ fhaodadh gun tèid iomradh a thoirt air a’ phuing null ‘RHS’. TGParser.cpp 2186

Earrann N6: A’ cleachdadh a’ phuing às deidh gluasad

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-Studio: V522 [CWE-476] Dh’ fhaodadh gun tèid iomradh a thoirt air a’ phuing null ‘ProgClone’. Miscompilation.cpp 601

Aig an toiseach inneal snasail ProgClone sguir e de shealbh an nì:

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

Gu dearbh, a-nis ProgClone tha e na phuing null. Mar sin, bu chòir iomradh puing null a bhith ann dìreach gu h-ìosal:

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

Ach, ann an da-rìribh, cha tachair seo! Thoir an aire nach eil an lùb air a chuir gu bàs gu fìor.

Aig toiseach a 'chòmhdaich Gnìomhan Miscompiled air a ghlanadh:

MiscompiledFunctions.clear();

An ath rud, tha meud an t-soithich seo air a chleachdadh ann an staid lùb:

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

Tha e furasta fhaicinn nach tòisich an lùb. Tha mi a’ smaoineachadh gur e bug a tha seo cuideachd agus bu chòir an còd a sgrìobhadh ann an dòigh eadar-dhealaichte.

Tha e coltach gun do thachair sinn ris a’ cho-ionannachd mhearachdan ainmeil sin! Tha aon mhearachd a' falach fear eile :).

Earrann N7: A’ cleachdadh a’ phuing às deidh gluasad

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-Studio: V522 [CWE-476] Dh’ fhaodadh gun tèid iomradh a thoirt air a’ phuing null ‘Deuchainn’. Miscompilation.cpp 709

An aon suidheachadh a-rithist. An toiseach, tha susbaint an nì air a ghluasad, agus an uairsin tha e air a chleachdadh mar gum biodh dad air tachairt. Bidh mi a’ faicinn an t-suidheachaidh seo barrachd is nas trice ann an còd prògram às deidh dha semantics gluasaid nochdadh ann an C ++. Sin as coireach gu bheil gaol agam air a’ chànan C ++! Tha barrachd is barrachd dhòighean ùra ann airson do chas fhèin a chuir dheth. Bidh obair an-còmhnaidh aig an anailisiche PVS-Studio :).

Earrann N8: Puing neonach

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-Studio: V522 [CWE-476] Dh’ fhaodadh gun tèid iomradh a thoirt air a’ phuing null ‘Type’. PrettyFunctionDumper.cpp 233

A bharrachd air làimhseachadh mhearachdan, mar as trice cha bhithear a’ dèanamh deuchainn air gnìomhan clò-bhualaidh deasbaid. Tha dìreach a leithid de chùis againn air thoiseach oirnn. Tha an gnìomh a 'feitheamh ris an neach-cleachdaidh, a dh' fheumas, an àite a bhith a 'fuasgladh nan duilgheadasan aige, a chàradh.

Ceart:

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

Earrann N9: Puing neonach

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-Studio: V522 [CWE-476] Dh’ fhaodadh gun tèid iomradh a thoirt air a’ phuing null ‘Ty’. SearchableTableEmitter.cpp 614

Tha mi a’ smaoineachadh gu bheil a h-uile dad soilleir agus nach eil feum air mìneachadh.

Earrann 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 Tha an caochladair 'Identifier-> Type' air a shònrachadh dha fhèin. FormatTokenLexer.cpp 249

Chan eil feum air caochladair a shònrachadh dha fhèin. Is dòcha gu robh iad airson sgrìobhadh:

Identifier->Type = Question->Type;

Earrann N11: Briseadh amharasach

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] Beachdaich air an aithris ‘switch’ a sgrùdadh. Tha e comasach gu bheil a’ chiad ghnìomhaiche ‘cùis’ a dhìth. SystemZAsmParser.cpp 652

Tha gnìomhaiche gu math amharasach aig an toiseach fois. An do dhìochuimhnich thu rudeigin eile a sgrìobhadh an seo?

Earrann N12: A' sgrùdadh comharraiche an dèidh iomradh a thoirt air

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] Chaidh am puing ‘Callee’ a chleachdadh mus deach a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 172, 174. AMDGPUInline.cpp 172

Pointer Callee aig an toiseach tha dereferenced aig an àm ris an canar an gnìomh faighTTI.

Agus an uairsin tha e a 'tionndadh a-mach gum bu chòir an comharra seo a bhith air a sgrùdadh airson co-ionannachd nullptr:

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

Ach tha e ro fhadalach…

Earrann N13 - N...: A’ sgrùdadh comharraiche às deidh dhut iomradh a thoirt air

Chan eil an suidheachadh a chaidh a dheasbad anns a’ chriomag còd roimhe gun samhail. Tha e a’ nochdadh an seo:

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] Chaidh am puing ‘CalleeFn’ a chleachdadh mus deach a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 1079, 1081. SimplifyLibCalls.cpp 1079

Agus an seo:

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] Chaidh am puing ‘ND’ a chleachdadh mus deach a dhearbhadh an aghaidh nullptr. Loidhne-sgrùdaidh: 532, 534. SemaTemplateInstantiateDecl.cpp 532

Agus an seo:

  • V595 [CWE-476] Chaidh am puing 'U' a chleachdadh mus deach a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 404, 407. DWARFormValue.cpp 404
  • V595 [CWE-476] Chaidh am puing 'ND' a chleachdadh mus deach a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 2149, 2151. SemaTemplateInstantiate.cpp 2149

Agus an uairsin dh’ fhàs mi gun ùidh ann a bhith a’ sgrùdadh nan rabhaidhean leis an àireamh V595. Mar sin chan eil fios agam a bheil barrachd mhearachdan coltach ris a bharrachd air an fheadhainn a tha air an liostadh an seo. As dualtaiche gu bheil.

Earrann N17, N18: Gluasad amharasach

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] Beachdaich air sgrùdadh a dhèanamh air an abairt '~ (Meud - 1) << 1'. Gluasad beag den luach 32-bit le leudachadh às deidh sin chun t-seòrsa 64-bit. AArch64AddressingModes.h 260

Is dòcha nach e biast a th’ ann agus tha an còd ag obair dìreach mar a bha dùil. Ach tha e soilleir gur e àite gu math amharasach a tha seo agus feumar sgrùdadh a dhèanamh air.

Canaidh sinn an caochlaideach meud co-ionann ri 16, agus an uairsin bha ùghdar a’ chòd an dùil a thoirt ann an caochladair NImms luach:

1111111111111111111111111111111111111111111111111111111111100000

Ach, ann an da-rìribh bidh an toradh:

0000000000000000000000000000000011111111111111111111111111100000

Is e an fhìrinn gu bheil a h-uile àireamhachadh a ’tachairt a’ cleachdadh an seòrsa 32-bit gun ainm. Agus dìreach an uairsin, thèid an seòrsa 32-bit seo gun ainm a leudachadh gu h-obann uint64_t. Anns a 'chùis seo, bidh na pìosan as cudromaiche neoni.

Faodaidh tu an suidheachadh a cheartachadh mar seo:

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

Suidheachadh coltach ris: V629 [CWE-190] Beachdaich air an abairt 'Immr << 6' a sgrùdadh. Gluasad beag den luach 32-bit le leudachadh às deidh sin chun t-seòrsa 64-bit. AArch64AddressingModes.h 269

Earrann N19: Facal-luirg a dhìth 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] Beachdaich air sgrùdadh a dhèanamh air loidsig an tagraidh. Tha e comasach gu bheil prìomh fhacal ‘eile’ a dhìth. AMDGPUAsmParser.cpp 5655

Chan eil mearachd an seo. Bhon uairsin - bloc a 'chiad fhear if a' crìochnachadh le leantainn air adhart, an uairsin chan eil e gu diofar, tha prìomh fhacal ann eile no nach eil. Co-dhiù, obraichidh an còd mar an ceudna. Fhathast air chall eile a’ dèanamh a’ chòd nas neo-shoilleir agus cunnartach. Ma tha san àm ri teachd leantainn air adhart à sealladh, tòisichidh an còd ag obair gu tur eadar-dhealaichte. Na mo bheachd-sa tha e nas fheàrr a chur ris eile.

Earrann N20: Ceithir typos den aon sheòrsa

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

Rabhaidhean PVS-Studio:

  • V655 [CWE-480] Chaidh na teudan a cheangal ach chan eilear gan cleachdadh. Beachdaich air sgrùdadh a dhèanamh air an abairt 'Toradh + Name.str()'. samhla.cpp 32
  • V655 [CWE-480] Chaidh na teudan a cheangal ach chan eilear gan cleachdadh. Beachdaich air sgrùdadh a dhèanamh air an abairt 'Toraidh + "(Clas ObjC)" + Name.str()'. samhla.cpp 35
  • V655 [CWE-480] Chaidh na teudan a cheangal ach chan eilear gan cleachdadh. Beachdaich air sgrùdadh a dhèanamh air an abairt 'Toradh + "(ObjC Class EH)" + Name.str()'. samhla.cpp 38
  • V655 [CWE-480] Chaidh na teudan a cheangal ach chan eilear gan cleachdadh. Beachdaich air sgrùdadh a dhèanamh air an abairt 'Toradh + "(ObjC IVar)" + Name.str()'. samhla.cpp 41

Le tubaist, thèid an gnìomhaiche + a chleachdadh an àite a’ ghnìomhaiche +=. Is e an toradh dealbhadh gun chiall.

Earrann N21: Giùlan neo-mhìnichte

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

Feuch an lorg thu an còd cunnartach thu fhèin. Agus is e seo dealbh airson aire a tharraing gus nach coimhead thu sa bhad air an fhreagairt:

A’ lorg bhiteagan ann an LLVM 8 a’ cleachdadh an anailisiche PVS-Studio

Rabhadh PVS-Studio: V708 [CWE-758] Cleachdadh togail cunnartach: 'FeaturesMap[Op] = FeaturesMap.size()', far a bheil 'FeaturesMap' den chlas 'mapa'. Faodaidh seo leantainn gu giùlan mì-chinnteach. RISCVCCompressInstEmitter.cpp 490

Loidhne duilgheadas:

FeaturesMap[Op] = FeaturesMap.size();

Ma tha eileamaid Op Chan eil lorg, an uairsin tha eileamaid ùr air a chruthachadh sa mhapa agus tha an àireamh de eileamaidean sa mhapa seo sgrìobhte an sin. Chan eil fios an tèid an gnìomh a ghairm meud ro no às deidh eileamaid ùr a chur ris.

Earrann N22-N24: Sònrachaidhean a-rithist

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] Tha an caochladair ‘NType’ air a thoirt seachad luachan dà uair às deidh a chèile. Is dòcha gur e mearachd a tha seo. Loidhne-sgrùdaidh: 1663, 1664. MachOObjectFile.cpp 1664

Chan eil mi a’ smaoineachadh gu bheil fìor mhearachd an seo. Dìreach obair neo-riatanach a-rithist. Ach fhathast blunder.

Mar an ceudna:

  • V519 [CWE-563] Tha an caochladair 'B.NDesc' air a shònrachadh luachan dà uair an dèidh a chèile. Is dòcha gur e mearachd a tha seo. Loidhne-sgrùdaidh: 1488, 1489. llvm-nm.cpp 1489
  • V519 [CWE-563] Tha an caochladair air luachan a shònrachadh dà uair às deidh a chèile. Is dòcha gur e mearachd a tha seo. Thoir sùil air loidhnichean: 59, 61. coff2yaml.cpp 61

Earrann N25-N27: Barrachd ath-shònrachaidhean

A-nis leig dhuinn sùil a thoirt air dreach beagan eadar-dhealaichte de ath-shònrachadh.

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-Studio: V519 [CWE-563] Tha an caochladair 'Co-thaobhadh' air a shònrachadh dà uair an dèidh a chèile. Is dòcha gur e mearachd a tha seo. Loidhnichean sgrùdaidh: 1158, 1160. LoadStoreVectorizer.cpp 1160

Is e còd gu math neònach a tha seo a tha coltach gu bheil mearachd loidsigeach ann. Aig an toiseach, caochlaideach Co-thaobhadh tha luach air a shònrachadh a rèir an t-suidheachaidh. Agus an uairsin bidh an obair a 'tachairt a-rithist, ach a-nis gun sgrùdadh sam bith.

Chithear suidheachaidhean coltach ris an seo:

  • V519 [CWE-563] Tha an caochladair ‘Effects’ air a shònrachadh luachan dà uair às deidh a chèile. Is dòcha gur e mearachd a tha seo. Loidhne-sgrùdaidh: 152, 165. WebAssemblyRegStackify.cpp 165
  • V519 [CWE-563] Tha an caochladair ‘ExpectNoDerefChunk’ air luachan a shònrachadh dà uair às deidh a chèile. Is dòcha gur e mearachd a tha seo. Loidhnichean sgrùdaidh: 4970, 4973. SemaType.cpp 4973

Earrann N28: An-còmhnaidh fìor staid

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] Tha an abairt ‘nextByte!= 0x90’ an-còmhnaidh fìor. X86DisassemblerDecoder.cpp 379

Chan eil sgrùdadh a’ dèanamh ciall. Caochlaideach athBite an-còmhnaidh nach eil co-ionann ris an luach 0x90, a tha a’ leantainn bhon t-seic roimhe. Is e seo seòrsa de mhearachd loidsigeach.

Earrann N29 - N...: An-còmhnaidh fìor / ceàrr

Bidh an anailisiche a’ toirt a-mach mòran rabhaidhean gu bheil an suidheachadh gu lèir (V547) no pàirt dheth (V560) an-còmhnaidh fìor no ceàrr. Gu tric chan e fìor mhearachdan a tha seo, ach dìreach còd sloppy, toradh leudachadh macro, agus an leithid. Ach, tha e ciallach coimhead air na rabhaidhean sin uile, leis gu bheil fìor mhearachdan loidsigeach a’ tachairt bho àm gu àm. Mar eisimpleir, tha an earrann seo den chòd amharasach:

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] Tha pàirt de mhìneachadh cumhach an-còmhnaidh meallta: RegNo == 0xe. ARMDisassembler.cpp 939

Is e an seasmhach 0xE an luach 14 ann an deicheach. Sgrùdadh Reg Chan eil == 0xe chan eil e ciallach oir ma tha Riaghailt > 13, an uairsin cuiridh an gnìomh crìoch air a chur gu bàs.

Bha mòran rabhaidhean eile ann le IDan V547 agus V560, ach mar le V595, cha robh ùidh agam ann a bhith a 'sgrùdadh nan rabhaidhean sin. Bha e soilleir mar-thà gun robh stuth gu leòr agam airson artaigil a sgrìobhadh :). Mar sin, chan eil fios cia mheud mearachd den t-seòrsa seo a dh’ fhaodar aithneachadh ann an LLVM a’ cleachdadh PVS-Studio.

Bheir mi eisimpleir dhut air carson a tha sgrùdadh air na brosnachaidhean sin dòrainneach. Tha an anailisiche gu tur ceart ann a bhith a’ toirt seachad rabhadh airson a’ chòd a leanas. Ach chan e mearachd a tha seo.

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

Rabhadh PVS-Studio: V547 [CWE-570] Tha abairt ‘! HasError’ an-còmhnaidh meallta. Loidhne Parser.cpp 1635

Fragment N30: ​​Tilleadh amharasach

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] ‘Tilleadh’ gun chumhachan taobh a-staigh lùb. R600OptimizeVectorRegisters.cpp 63

Is e mearachd a tha seo no dòigh sònraichte a thathar an dùil rudeigin a mhìneachadh do luchd-prògramaidh a tha a’ leughadh a’ chòd. Chan eil an dealbhadh seo a’ mìneachadh dad dhomh agus tha e a’ coimhead gu math amharasach. Tha e nas fheàrr gun a bhith a’ sgrìobhadh mar sin :).

Sgìthichte? An uairsin tha an t-àm ann tì no cofaidh a dhèanamh.

A’ lorg bhiteagan ann an LLVM 8 a’ cleachdadh an anailisiche PVS-Studio

Duilgheadasan air an comharrachadh le diagnosachd ùr

Tha mi a’ smaoineachadh gu bheil 30 gnìomh de sheann diagnosachd gu leòr. Chì sinn a-nis dè na rudan inntinneach a lorgar leis na diagnosachd ùr a nochd san anailisiche às deidh sin roimhe seo seicichean. Rè na h-ùine seo, chaidh 66 diagnosachd coitcheann gu h-iomlan a chur ris an anailisiche C ++.

Earrann N31: Còd nach gabh a ruighinn

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 nach gabh ruighinn air a lorg. Tha e comasach gu bheil mearachd an làthair. Cur gu bàsUtils.cpp 146

Mar a chì thu, an dà mheur den ghnìomhaiche if a’ crìochnachadh le fios chun ghnìomhaiche air ais. A rèir sin, an container CtorDtorsLe prìomhachas cha tèid a ghlanadh gu bràth.

Earrann N32: Còd nach gabh a ruighinn

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-Studio: V779 [CWE-561] Còd nach gabh ruighinn air a lorg. Tha e comasach gu bheil mearachd an làthair. LLParser.cpp 835

Suidheachadh inntinneach. Bheir sinn sùil air an àite seo an toiseach:

return ParseTypeIdEntry(SummaryID);
break;

Aig a 'chiad sealladh, tha e coltach nach eil mearachd an seo. Tha e coltach ris a’ ghnìomhaiche fois tha fear a bharrachd an seo, agus faodaidh tu dìreach a sguabadh às. Ach, chan eil a h-uile cho sìmplidh.

Bidh an anailisiche a’ toirt seachad rabhadh air na loidhnichean:

Lex.setIgnoreColonInIdentifiers(false);
return false;

Agus gu dearbh, chan eil an còd seo ruigsinneach. A h-uile cùis ann an suidse a’ crìochnachadh le fios bhon ghnìomhaiche air ais. Agus a-nis gun chiall leis fhèin fois chan eil e a’ coimhead cho gun chron! Is dòcha gum bu chòir aon de na meuran crìochnachadh le foischan ann air adhart air ais?

Pàirt N33: Ath-shuidheachadh air thuaiream de bhuillean àrda

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 Tha meud an masg beagan nas lugha na meud a 'chiad operand. Bidh seo ag adhbhrachadh call pìosan nas àirde. RuntimeDild.cpp 815

Thoir an aire gu bheil an gnìomh faighStubAlignment seòrsa tilleadh gun ainm. Feuch an obraich sinn a-mach luach an abairt, a’ gabhail ris gu bheil an gnìomh a’ tilleadh an luach 8:

~ (getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

A-nis mothaich gu bheil an caochlaideach Meud dàta tha seòrsa 64-bit gun ainm aige. Tha e a’ tionndadh a-mach, nuair a bhios tu a’ coileanadh gnìomhachd DataSize & 0xFFFFFFF8u, gun tèid na trithead ’s a dhà pìosan àrd-òrdugh ath-shuidheachadh gu neoni. Nas coltaiche, chan e seo a bha am prògramadair ag iarraidh. Tha amharas agam gu robh e airson obrachadh a-mach: DataSize & 0xFFFFFFFFFFFFFF8u.

Gus a’ mhearachd a cheartachadh, bu chòir dhut seo a sgrìobhadh:

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

No mar sin:

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

Earrann N34: Dh’ fhàillig seòrsa de sheòrsa sònraichte

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 thairis a dh’ fhaodadh a bhith ann. Beachdaich air a bhith a’ tilgeadh obrands den ghnìomhaiche ‘NumElts * Scale’ chun t-seòrsa ‘size_t’, chan e an toradh. X86ISelLowering.h 1577

Thathas a’ cleachdadh tilgeadh seòrsa sònraichte gus cus sruthadh a sheachnadh nuair a thathar ag iomadachadh caochladairean seòrsa int. Ach, chan eil tilgeadh seòrsa soilleir an seo a’ dìon an aghaidh thar-shruth. An toiseach, thèid na caochladairean iomadachadh, agus dìreach an uairsin thèid toradh 32-bit an iomadachaidh a leudachadh chun t-seòrsa meud_t.

Earrann N35: Leth-bhreac air fàiligeadh

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] Chaidh dà chriomag còd coltach ris a lorg. Is dòcha gur e typo a tha seo agus bu chòir caochladair ‘Op1’ a chleachdadh an àite ‘Op0’. Dèan coimeas eadar InstCombine.cpp 5507

Tha am breithneachadh inntinneach ùr seo a’ comharrachadh shuidheachaidhean far an deach pìos còd a chopaigeadh agus cuid de na h-ainmean a th’ ann air tòiseachadh air atharrachadh, ach ann an aon àite chan eil iad air a cheartachadh.

Thoir an aire gun do dh'atharraich iad san dàrna bloc Air 0 air Air 1. Ach ann an aon àite cha do shocraich iad e. Is coltaiche gum bu chòir a bhith air a sgrìobhadh mar seo:

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

Earrann N36: Mì-chinnt caochlaideach

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] Tha an caochladair ‘Modh’ air a shònrachadh ach chan eil e air a chleachdadh ro dheireadh na gnìomh. SIModeRegister.cpp 48

Tha e glè chunnartach na h-aon ainmean a thoirt do bhuill a’ chlas air argamaidean gnìomh. Tha e gu math furasta a bhith troimh-chèile. Tha dìreach a leithid de chùis againn air thoiseach oirnn. Chan eil an abairt seo a’ dèanamh ciall:

Mode &= Mask;

Bidh an argamaid gnìomh ag atharrachadh. Sin e. Chan eil an argamaid seo air a chleachdadh tuilleadh. Is dòcha gum bu chòir dhut a bhith air a sgrìobhadh mar seo:

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

Earrann N37: Mì-chinnt caochlaideach

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] Tha an caochladair 'Meud' air a shònrachadh ach chan eil e air a chleachdadh ro dheireadh a 'ghnìomh. Rud.cpp 424

Tha an suidheachadh coltach ris an fhear roimhe. Bu chòir a sgrìobhadh:

this->Size += this->EntrySize;

Criomag N38-N47: Dhìochuimhnich iad sgrùdadh a dhèanamh air a’ chlàr-amais

Roimhe seo, thug sinn sùil air eisimpleirean de bhrosnachadh breithneachaidh V595. Is e an rud a th 'ann gu bheil am puing air a dhì-ghairm aig an toiseach, agus dìreach an uairsin air a sgrùdadh. Diagnosachd òga a V1004 tha an taobh eile ann an ciall, ach tha e cuideachd a’ nochdadh mòran mhearachdan. Bidh e a’ comharrachadh shuidheachaidhean far an deach am puing a sgrùdadh aig an toiseach agus an uairsin dhìochuimhnich sin a dhèanamh. Bheir sinn sùil air na cùisean sin a lorgar am broinn 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] Chaidh am puing ‘Ptr’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 729, 738. TargetTransformInfoImpl.h 738

Caochlaideach Ptr faodaidh e bhith co-ionnan nullptr, mar a chithear leis an t-seic:

if (Ptr != nullptr)

Ach, gu h-ìosal tha an comharra seo air a chuir dheth gun sgrùdadh tòiseachaidh:

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

Beachdaichidh sinn air cùis eile den aon seòrsa.

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] Chaidh am puing ‘FD’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 3228, 3231. CGDebugInfo.cpp 3231

Thoir aire don t-soidhne FD. Tha mi cinnteach gu bheil an duilgheadas ri fhaicinn gu soilleir agus nach eil feum air mìneachadh sònraichte.

Agus a bharrachd:

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] Chaidh am puing ‘PtrTy’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 960, 965. InterleavedLoadCombinePass.cpp 965

Ciamar thu fhèin a dhìon bho mhearachdan mar sin? Bi nas furachail air Còd-Lèirmheas agus cleachd an anailisiche statach PVS-Studio gus do chòd a sgrùdadh gu cunbhalach.

Chan eil adhbhar ann a bhith ag ainmeachadh criomagan còd eile le mearachdan den t-seòrsa seo. Chan fhàg mi ach liosta de rabhaidhean san artaigil:

  • V1004 [CWE-476] Chaidh am puing ‘Expr’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 1049, 1078. DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] Chaidh am puing ‘PI’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 733, 753. LegacyPassManager.cpp 753
  • V1004 [CWE-476] Chaidh am puing ‘StatepointCall’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 4371, 4379. Verifier.cpp 4379
  • V1004 [CWE-476] Chaidh am puing ‘RV’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean sgrùdaidh: 2263, 2268. TGParser.cpp 2268
  • V1004 [CWE-476] Chaidh am puing ‘CalleeFn’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhne-sgrùdaidh: 1081, 1096. SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] Chaidh am puing ‘TC’ a chleachdadh gu mì-shàbhailte às deidh dha a bhith air a dhearbhadh an aghaidh nullptr. Loidhnichean seic: 1819, 1824. Driver.cpp 1824

Criomag N48-N60: Chan eil e riatanach, ach uireasbhaidh (aodion cuimhne comasach)

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] Thathas a’ cur puing às aonais sealbhadair ris a’ bhogsa ‘Ro-innleachdan’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-isel-fuzzer.cpp 58

Gus eileamaid a chur ri deireadh container mar std::vector > chan urrainn dhut dìreach sgrìobhadh xxx.push_back(X ùr), leis nach eil tionndadh follaiseach ann bho X* в std::unique_ptr.

Is e fuasgladh cumanta sgrìobhadh xxx.emplace_back(X ùr)oir tha e a 'cur ri chèile: modh àite_cùl a’ togail eileamaid gu dìreach bho na h-argamaidean aige agus mar sin faodaidh iad luchd-togail soilleir a chleachdadh.

Chan eil e sàbhailte. Ma tha an vectar làn, thèid cuimhne ath-riarachadh. Dh’ fhaodadh gun fàillig an obair ath-riarachadh cuimhne, agus mar thoradh air an sin thèid eisgeachd a thilgeil std :: bad_alloc. Anns a 'chùis seo, thèid am puing a chall agus cha tèid an rud a chaidh a chruthachadh a dhubhadh às gu bràth.

Is e fuasgladh sàbhailte a chruthachadh gun samhail_ptraig am bi sealbh air a’ phuing mus feuchaidh an vectar ri cuimhne ath-riarachadh:

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

Bho C ++14, faodaidh tu 'std :: make_unique' a chleachdadh:

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

Chan eil an seòrsa uireasbhaidh seo deatamach airson LLVM. Mura h-urrainnear cuimhne a thoirt seachad, stadaidh an t-inneal-cruinneachaidh. Ach, airson iarrtasan le fada uptime, nach urrainn a thighinn gu crìch ma dh’ fhailicheas riarachadh cuimhne, faodaidh seo a bhith na fhìor bhuga.

Mar sin, ged nach eil an còd seo na chunnart practaigeach do LLVM, bha e feumail dhomh bruidhinn mun phàtran mearachd seo agus gu bheil an anailisiche PVS-Studio air ionnsachadh a chomharrachadh.

Rabhaidhean eile den t-seòrsa seo:

  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘Passes’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. Manaidsear-siubhail.h 546
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ ghobhar ‘AAs’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. AliasAnailis.h 324
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘Entries’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘AllEdges’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. CFGMST.h 268
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘VMaps’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. SimpleLoopUnswitch.cpp 2012
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘Records’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. FDRLogBuilder.h 30
  • V1023 [CWE-460] Tha comharraiche gun sealbhadair air a chur ris a’ ghobhar ‘PendingSubmodules’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. ModuleMap.cpp 810
  • V1023 [CWE-460] Thathas a’ cur puing às aonais sealbhadair ris a’ bhogsa ‘Objects’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. DebugMap.cpp 88
  • V1023 [CWE-460] Tha comharraiche gun sealbhadair air a chur ris a’ bhogsa ‘Ro-innleachdan’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 685
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 686
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 688
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 689
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 690
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 691
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 692
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 693
  • V1023 [CWE-460] Thathas a’ cur puing gun sealbhadair ris a’ bhogsa ‘Modifiers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. llvm-cuideam.cpp 694
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘Operands’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] Thathas a’ cur puing às aonais sealbhadair ris a’ bhogsa ‘Stash’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] Thathas a’ cur puing gun shealbhadair ris a’ bhogsa ‘Matchers’ leis an dòigh ‘emplace_back’. Bidh aodion cuimhne a’ tachairt gun fhios nach bi eisgeachd ann. GlobalISelEmitter.cpp 2702

co-dhùnadh

Chuir mi a-mach 60 rabhadh gu h-iomlan agus an uairsin stad mi. A bheil uireasbhaidhean eile ann a lorgas an anailisiche PVS-Studio ann an LLVM? Tha, tha agam. Ach, nuair a bha mi a 'sgrìobhadh criomagan còd airson an artaigil, b' e deireadh an fheasgair a bh 'ann, no eadhon oidhche, agus cho-dhùin mi gu robh an t-àm ann latha a ghairm.

Tha mi an dòchas gun robh e inntinneach dhut agus gum bi thu airson an anailisiche PVS-Studio fheuchainn.

Faodaidh tu an anailisiche a luchdachadh sìos agus an iuchair minesweeper fhaighinn aig an duilleag seo.

Nas cudromaiche, cleachd mion-sgrùdadh statach gu cunbhalach. Sgrùdaidhean aon-ùine, air a dhèanamh leinn gus an dòigh-obrach airson mion-sgrùdadh statach agus PVS-Studio a chleachdadh mar shuidheachadh àbhaisteach.

Math fortanach ann a bhith ag adhartachadh càileachd agus earbsachd do chòd!

A’ lorg bhiteagan ann an LLVM 8 a’ cleachdadh an anailisiche PVS-Studio

Ma tha thu airson an artaigil seo a cho-roinn le luchd-èisteachd Beurla, cleachd an ceangal eadar-theangachaidh: Andrey Karpov. A’ lorg bhiteagan ann an LLVM 8 le PVS-Studio.

Source: www.habr.com

Cuir beachd ann