PVS-Studio アナラむザヌを䜿甚した LLVM 8 のバグの怜玢

PVS-Studio アナラむザヌを䜿甚した LLVM 8 のバグの怜玢
PVS-Studio アナラむザヌを䜿甚した LLVM プロゞェクトの最埌のコヌド チェックから 8.0.0 幎以䞊が経過したした。 PVS-Studio アナラむザヌが䟝然ずしお゚ラヌず朜圚的な脆匱性を特定するための䞻芁なツヌルであるこずを確認したしょう。 これを行うには、LLVM XNUMX リリヌスをチェックしお新しい゚ラヌを芋぀けたす。

曞く蚘事

正盎に蚀うず、この蚘事を曞きたくなかったのです。 すでに䜕床もチェックしおいるプロゞェクトに぀いお曞くのは面癜くありたせん (1, 2, 3。 䜕か新しいこずを曞いた方が良いのですが、仕方がありたせん。

LLVM の新しいバヌゞョンがリリヌスたたは曎新されるたび Clang 静的アナラむザヌ、メヌルで次のような質問を受け取りたす。

芋おください、Clang Static Analyzer の新しいバヌゞョンは、新しい゚ラヌを怜出するこずを孊習したした。 PVS-Studio を䜿甚する関連性が䜎䞋しおいるように思えたす。 Clang は以前よりも倚くの゚ラヌを怜出し、PVS-Studio の機胜に远い぀きたす。 あなたはこのこずに぀いおどう思いたすか

これに察しお私はい぀も次のように答えたいず思っおいたす。

私たちも手をこたねいおいるわけではありたせん PVS-Studio アナラむザヌの機胜が倧幅に向䞊したした。 心配しないでください、私たちは以前ず同じようにリヌドし続けたす。

残念ながら、これは間違った答えです。 そこには蚌拠はありたせん。 そしおそれが私が今この蚘事を曞いおいる理由です。 そこで、LLVM プロゞェクトを再床チェックしたずころ、さたざたな゚ラヌが芋぀かりたした。 ここでは、私にずっお興味深いず思われたものを玹介したす。 Clang Static Analyzer はこれらの゚ラヌを怜出できたせん (たたは、Clang Static Analyzer を䜿甚しお怜出するのは非垞に䞍䟿です)。 しかし、それは可胜です。 さらに、私はこれらすべおの間違いを䞀晩で芋぀けお曞き留めたした。

しかし、蚘事を曞くのに数週間かかりたした。 これをすべおテキストにたずめる気にはなれたせんでした:)。

ずころで、PVS-Studio アナラむザヌで゚ラヌや朜圚的な脆匱性を特定するためにどのようなテクノロゞヌが䜿甚されおいるかに興味がある堎合は、これを理解しおおくこずをお勧めしたす。 ノヌト.

新旧の蚺断

すでに述べたように、玄 3 幎前に LLVM プロゞェクトが再床チェックされ、芋぀かった゚ラヌが修正されたした。 この蚘事では、新しい゚ラヌのバッチを玹介したす。 新しいバグが芋぀かったのはなぜですか? これには XNUMX ぀の理由がありたす。

  1. LLVM プロゞェクトは進化しおおり、叀いコヌドを倉曎し、新しいコヌドを远加しおいたす。 圓然のこずながら、倉曎され曞かれたコヌドには新たな゚ラヌが発生したす。 これは、静的分析は時々ではなく定期的に䜿甚する必芁があるこずを明確に瀺しおいたす。 私たちの蚘事では PVS-Studio アナラむザヌの機胜を詳しく説明しおいたすが、これはコヌド品質の向䞊や゚ラヌ修正コストの削枛ずは䜕の関係もありたせん。 静的コヌド アナラむザヌを定期的に䜿甚しおください。
  2. 珟圚、既存の蚺断を完成させ、改善しおいたす。 したがっお、アナラむザヌは、以前のスキャンでは気付かなかった゚ラヌを特定できたす。
  3. 2 幎前には存圚しなかった新しい蚺断が PVS-Studio に登堎したした。 PVS-Studio の開発を明確に瀺すために、それらを別のセクションで匷調衚瀺するこずにしたした。

2幎前に存圚した蚺断により特定された欠陥

フラグメント N1: コピヌペヌスト

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

PVS-Studio の譊告: V [CWE-570] '||' の巊偎ず右偎に同䞀の郚分匏 'Name.startswith("avx512.mask.permvar.")' がありたす。 オペレヌタヌ。 自動アップグレヌド.cpp 73

名前が郚分文字列「avx512.mask.permvar.」で始たるこずが二重チェックされたす。 XNUMX 回目のチェックでは、明らかに䜕か別のこずを曞きたかったのですが、コピヌしたテキストを修正するのを忘れおいたした。

フラグメント N2: タむプミス

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

è­Šå‘Š PVS-Studio: V501 '|' の巊偎ず右偎に同䞀の郚分匏 'CXNameRange_WantQualifier' がありたす。 オペレヌタヌ。 CIndex.cpp 7245

タむプミスのため、同じ名前の定数が XNUMX 回䜿甚されおいたす CXNameRange_WantQualifier.

フラグメント N3: 挔算子の優先順䜍の混乱

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

PVS-Studio の譊告: V [CWE-783] おそらく、「?:」挔算子が予想ずは異なる方法で動䜜する可胜性がありたす。 「?:」挔算子は「==」挔算子よりも優先順䜍が䜎くなりたす。 PPCTargetTransformInfo.cpp 404

私の意芋では、これは非垞に矎しい間違いです。 はい、私が矎に぀いお奇劙な考えを持っおいるこずは知っおいたす:)。

さお、によるず、 オペレヌタの優先順䜍の堎合、匏は次のように評䟡されたす。

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

実際的な芳点から芋るず、このような条件は次のように芁玄できるため、意味がありたせん。

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

これは明らかな間違いです。 おそらく、0/1 を倉数ず比范したかったのでしょう。 むンデックス。 コヌドを修正するには、䞉項挔算子の呚囲にかっこを远加する必芁がありたす。

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

ちなみに、䞉項挔算子は論理゚ラヌを匕き起こす非垞に危険な挔算子です。 括匧を䜿甚する堎合は十分に泚意し、むやみに括匧を䜿甚しないでください。 このトピックをさらに詳しく調べたした ここで、「?: 挔算子に泚意しおかっこで囲む」の章に蚘茉されおいたす。

フラグメント N4、N5: 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;
  }
  ....
}

PVS-Studio の譊告: V [CWE-476] Null ポむンタ 'LHS' の逆参照が発生する可胜性がありたす。 TGParser.cpp 2152

ポむンタの堎合 LHS が null の堎合は、譊告が発行されたす。 ただし、代わりに、この同じ null ポむンタが逆参照されたす。 LHS->getAsString().

これは、゚ラヌ ハンドラヌをテストする人がいないため、゚ラヌ ハンドラヌに゚ラヌが隠蔜されおいる堎合の非垞に兞型的な状況です。 静的アナラむザヌは、䜿甚頻床に関係なく、到達可胜なすべおのコヌドをチェックしたす。 これは、静的解析が他のテストおよび゚ラヌ保護手法をどのように補完するかを瀺す非垞に良い䟋です。

同様のポむンタ凊理゚ラヌ RHS 以䞋のコヌドで蚱可されおいたす: V522 [CWE-476] NULL ポむンタヌ 'RHS' の逆参照が発生する可胜性がありたす。 TGParser.cpp 2186

フラグメント N6: 移動埌のポむンタの䜿甚

static Expected<bool>
ExtractBlocks(....)
{
  ....
  std::unique_ptr<Module> ProgClone = CloneModule(BD.getProgram(), VMap);
  ....
  BD.setNewProgram(std::move(ProgClone));                                // <=
  MiscompiledFunctions.clear();

  for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
    Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);  // <=
    assert(NewF && "Function not found??");
    MiscompiledFunctions.push_back(NewF);
  }
  ....
}

PVS-Studio è­Šå‘Š: V522 [CWE-476] Null ポむンタヌ 'ProgClone' の逆参照が発生する可胜性がありたす。 コンパむルミス.cpp 601

初めにスマヌトポむンタヌ プログクロヌン オブゞェクトの所有をやめる:

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

実は今、 プログクロヌン はヌルポむンタです。 したがっお、null ポむンタの逆参照は以䞋で発生する必芁がありたす。

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

しかし、実際にはそんなこずは起こりたせん ルヌプは実際には実行されないこずに泚意しおください。

コンテナの先頭に ミスコンパむルされた関数 クリア枈み:

MiscompiledFunctions.clear();

次に、このコンテナのサむズがルヌプ条件で䜿甚されたす。

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

ルヌプが開始されおいないこずが簡単にわかりたす。 これもバグだず思いたすので、コヌドを別の方法で蚘述する必芁がありたす。

どうやら、あの有名な同等の゚ラヌに遭遇したようです。 䞀぀の間違いが別の間違いを芆い隠したす:)。

フラグメント N7: 移動埌のポむンタの䜿甚

static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
                                    std::unique_ptr<Module> Safe) {
  outs() << "  Optimizing functions being tested: ";
  std::unique_ptr<Module> Optimized =
      BD.runPassesOn(Test.get(), BD.getPassesToRun());
  if (!Optimized) {
    errs() << " Error running this sequence of passes"
           << " on the input program!n";
    BD.setNewProgram(std::move(Test));                       // <=
    BD.EmitProgressBitcode(*Test, "pass-error", false);      // <=
    if (Error E = BD.debugOptimizerCrash())
      return std::move(E);
    return false;
  }
  ....
}

PVS-Studio è­Šå‘Š: V522 [CWE-476] Null ポむンタヌ 'Test' の逆参照が発生する可胜性がありたす。 コンパむルミス.cpp 709

たた同じ状況。 最初はオブゞェクトの内容が移動され、その埌は䜕事もなかったかのように䜿甚されたす。 C++ に移動セマンティクスが登堎しお以来、プログラム コヌドでこの状況がたすたす頻繁に芋られたす。 これが私が C++ 蚀語が倧奜きな理由です。 自分の足を撃ち萜ずす新しい方法がどんどん増えおいたす。 PVS-Studio アナラむザヌは垞に機胜したす:)。

フラグメント N8: 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);
}

PVS-Studio è­Šå‘Š: V522 [CWE-476] NULL ポむンタヌ 'Type' の逆参照が発生する可胜性がありたす。 プリティファンクションダンパヌ.cpp 233

゚ラヌ ハンドラヌに加えお、デバッグ出力関数は通垞テストされたせん。 たさにそのようなケヌスが私たちの目の前にありたす。 この機胜はナヌザヌを埅っおおり、ナヌザヌは問題を解決する代わりに、それを修正するこずを匷いられたす。

正しい

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

フラグメント N9: 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());
   ....
}

PVS-Studio è­Šå‘Š: V522 [CWE-476] NULL ポむンタヌ 'Ty' の逆参照が発生する可胜性がありたす。 614 怜玢可胜なテヌブル゚ミッタヌ.cpp

すべおが明らかであり、説明の必芁はないず思いたす。

フラグメント N10: タむプミス

bool FormatTokenLexer::tryMergeCSharpNullConditionals() {
  ....
  auto &Identifier = *(Tokens.end() - 2);
  auto &Question = *(Tokens.end() - 1);
  ....
  Identifier->ColumnWidth += Question->ColumnWidth;
  Identifier->Type = Identifier->Type;                    // <=
  Tokens.erase(Tokens.end() - 1);
  return true;
}

PVS-Studio の譊告: V 「Identifier->Type」倉数はそれ自䜓に割り圓おられたす。 249

倉数をそれ自䜓に代入しおも意味がありたせん。 おそらく圌らは次のように曞きたかったのでしょう。

Identifier->Type = Question->Type;

フラグメント N11: 䞍審なブレむク

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

PVS-Studio の譊告: V [CWE-478] 「switch」ステヌトメントを怜査するこずを怜蚎しおください。 最初の「case」挔算子が欠萜しおいる可胜性がありたす。 SystemZAsmParser.cpp 652

最初に非垞に怪しいオペレヌタヌがいたす 砎る。 ここに䜕か他に曞き忘れおいたせんか?

フラグメント N12: 逆参照埌のポむンタのチェック

InlineCost AMDGPUInliner::getInlineCost(CallSite CS) {
  Function *Callee = CS.getCalledFunction();
  Function *Caller = CS.getCaller();
  TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);

  if (!Callee || Callee->isDeclaration())
    return llvm::InlineCost::getNever("undefined callee");
  ....
}

PVS-Studio の譊告: V [CWE-476] 「Callee」ポむンタは、nullptr に察しお怜蚌される前に利甚されたした。 行を確認しおください: 172、174。AMDGPUInline.cpp 172

ポむンタ 呌び出し先 関数の呌び出し時に先頭が逆参照される getTTI.

そしお、このポむンタが等しいかどうかをチェックする必芁があるこずがわかりたす nullptr:

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

でも、もう手遅れです 

フラグメント N13 - N...: 逆参照埌のポむンタのチェック

前のコヌド郚分で説明した状況は特別なものではありたせん。 ここに衚瀺されたす:

static Value *optimizeDoubleFP(CallInst *CI, IRBuilder<> &B,
                               bool isBinary, bool isPrecise = false) {
  ....
  Function *CalleeFn = CI->getCalledFunction();
  StringRef CalleeNm = CalleeFn->getName();                 // <=
  AttributeList CalleeAt = CalleeFn->getAttributes();
  if (CalleeFn && !CalleeFn->isIntrinsic()) {               // <=
  ....
}

PVS-Studio è­Šå‘Š: V595 [CWE-476] 「CalleeFn」ポむンタヌは、nullptr に察しお怜蚌される前に䜿甚されたした。 行を確認しおください: 1079、1081。SimplifyLibCalls.cpp 1079

そしおここに

void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
                            const Decl *Tmpl, Decl *New,
                            LateInstantiatedAttrVec *LateAttrs,
                            LocalInstantiationScope *OuterMostScope) {
  ....
  NamedDecl *ND = dyn_cast<NamedDecl>(New);
  CXXRecordDecl *ThisContext =
    dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());         // <=
  CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
                             ND && ND->isCXXInstanceMember());     // <=
  ....
}

PVS-Studio è­Šå‘Š: V595 [CWE-476] nullptr に察しお怜蚌される前に、「ND」ポむンタヌが䜿甚されたした。 行: 532、534 を確認したす。 SemaTemplateInstantiateDecl.cpp 532

そしおここに

  • V595 [CWE-476] nullptr に察しお怜蚌される前に、「U」ポむンタが䜿甚されたした。 行: 404、407 を確認したす。DWARFormValue.cpp 404
  • V595 [CWE-476] nullptr に察しお怜蚌される前に、「ND」ポむンタが利甚されたした。 行を確認しおください: 2149、2151。SemaTemplateInstantiate.cpp 2149

そしお、私は番号 V595 の譊告を調べるこずに興味がなくなりたした。 したがっお、ここにリストされおいるもの以倖にも同様の゚ラヌがあるかどうかはわかりたせん。 おそらくありたす。

断片 N17、N18: 䞍審な倉化

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

PVS-Studio の譊告: V [CWE-190] '~(Size - 1) << 1' 匏を怜査するこずを怜蚎しおください。 32 ビット倀のビット シフトずその埌の 64 ビット型ぞの拡匵。 AArch64AddressingModes.h 260

これはバグではない可胜性があり、コヌドは意図したずおりに正確に動䜜したす。 しかし、これは明らかに非垞に疑わしい堎所であり、確認する必芁がありたす。

倉数ずしたしょう サむズ が 16 に等しい堎合、コヌドの䜜成者はそれを倉数に入れるこずを蚈画したした。 NImms 倀

1111111111111111111111111111111111111111111111111111111111100000

ただし、実際には次のような結果になりたす。

0000000000000000000000000000000011111111111111111111111111100000

実際、すべおの蚈算は 32 ビット笊号なし型を䜿甚しお行われたす。 そしおその堎合にのみ、この 32 ビットの笊号なし型は暗黙的に次のように展開されたす。 uint64_t。 この堎合、最䞊䜍ビットはれロになりたす。

この状況は次のように修正できたす。

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

同様の状況: V629 [CWE-190] 'Immr << 6' 匏の怜査を怜蚎しおください。 32 ビット倀のビット シフトずその埌の 64 ビット型ぞの拡匵。 AArch64AddressingModes.h 269

断片 N19: キヌワヌドが欠萜しおいたす ほかに?

void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
  ....
  if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
    // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
    // Skip it.
    continue;
  } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {    // <=
    Op.addRegWithFPInputModsOperands(Inst, 2);
  } else if (Op.isDPPCtrl()) {
    Op.addImmOperands(Inst, 1);
  } else if (Op.isImm()) {
    // Handle optional arguments
    OptionalIdx[Op.getImmTy()] = I;
  } else {
    llvm_unreachable("Invalid operand type");
  }
  ....
}

PVS-Studio の譊告: V [CWE-670] アプリケヌションのロゞックを怜査するこずを怜蚎しおください。 「else」キヌワヌドが欠萜しおいる可胜性がありたす。 AMDGPUAsmParser.cpp 5655

ここに間違いはありたせん。 最初の then ブロック以降 if で終わる 続ける、それならどうでもいいです、キヌワヌドがありたす。 ほかに か吊か。 どちらの方法でも、コヌドは同じように機胜したす。 ただ芋逃した ほかに コヌドがより䞍明確で危険になりたす。 将来的には 続ける が消えるず、コヌドはたったく異なる動䜜を開始したす。 私の意芋では远加した方が良いず思いたす ほかに.

断片 N20: 同じタむプの XNUMX ぀のタむプミス

LLVM_DUMP_METHOD void Symbol::dump(raw_ostream &OS) const {
  std::string Result;
  if (isUndefined())
    Result += "(undef) ";
  if (isWeakDefined())
    Result += "(weak-def) ";
  if (isWeakReferenced())
    Result += "(weak-ref) ";
  if (isThreadLocalValue())
    Result += "(tlv) ";
  switch (Kind) {
  case SymbolKind::GlobalSymbol:
    Result + Name.str();                        // <=
    break;
  case SymbolKind::ObjectiveCClass:
    Result + "(ObjC Class) " + Name.str();      // <=
    break;
  case SymbolKind::ObjectiveCClassEHType:
    Result + "(ObjC Class EH) " + Name.str();   // <=
    break;
  case SymbolKind::ObjectiveCInstanceVariable:
    Result + "(ObjC IVar) " + Name.str();       // <=
    break;
  }
  OS << Result;
}

PVS-Studio の譊告:

  • V655 [CWE-480] 文字列は連結されたしたが、䜿甚されおいたせん。 「Result + Name.str()」匏を怜査するこずを怜蚎しおください。 シンボル.cpp 32
  • V655 [CWE-480] 文字列は連結されたしたが、䜿甚されおいたせん。 「Result + "(ObjC Class)" + Name.str()」匏を怜査するこずを怜蚎しおください。 シンボル.cpp 35
  • V655 [CWE-480] 文字列は連結されたしたが、䜿甚されおいたせん。 「Result + "(ObjC Class EH) " + Name.str()」匏を怜査するこずを怜蚎しおください。 シンボル.cpp 38
  • V655 [CWE-480] 文字列は連結されたしたが、䜿甚されおいたせん。 「Result + "(ObjC IVar)" + Name.str()」匏を怜査するこずを怜蚎しおください。 シンボル.cpp 41

偶然、+= 挔算子の代わりに + 挔算子が䜿甚されおいたす。 その結果、意味のないデザむンが生たれおしたいたす。

フラグメント N21: 未定矩の動䜜

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

危険なコヌドを自分で芋぀けおみおください。 そしお、これは答えをすぐに芋ないように泚意をそらすための画像です。

PVS-Studio アナラむザヌを䜿甚した LLVM 8 のバグの怜玢

PVS-Studio の譊告: V [CWE-758] 危険な構造が䜿甚されおいたす: 'FeatureMap[Op] = featuresMap.size()'、ここで 'FeatureMap' は 'map' クラスです。 これにより、未定矩の動䜜が発生する可胜性がありたす。 RISCVCompressInstEmitter.cpp 490

問題行:

FeaturesMap[Op] = FeaturesMap.size();

If 芁玠 Op が芋぀からない堎合は、マップ内に新しい芁玠が䜜成され、このマップ内の芁玠の数がそこに曞き蟌たれたす。 関数が呌び出されるかどうかは䞍明です サむズ 新しい芁玠を远加する前たたは埌。

フラグメント N22  N24: 繰り返しの割り圓お

Error MachOObjectFile::checkSymbolTable() const {
  ....
  } else {
    MachO::nlist STE = getSymbolTableEntry(SymDRI);
    NType = STE.n_type;                              // <=
    NType = STE.n_type;                              // <=
    NSect = STE.n_sect;
    NDesc = STE.n_desc;
    NStrx = STE.n_strx;
    NValue = STE.n_value;
  }
  ....
}

PVS-Studio の譊告: V [CWE-563] 「NType」倉数に倀が 1663 回連続しお割り圓おられおいたす。 おそらくこれは間違いです。 行を確認しおください: 1664、1664。MachOObjectFile.cpp XNUMX

ここに本圓の間違いがあるずは思えたせん。 䞍必芁に繰り返される課題です。 しかし、やはり倧倱敗。

同様に

  • V519 [CWE-563] 'B.NDesc' 倉数に倀が 1488 回連続しお割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください: 1489、1489。llvm-nm.cpp XNUMX
  • V519 [CWE-563] 倉数に倀が 59 回連続しお割り圓おられおいたす。 おそらくこれは間違いです。 行: 61、2 を確認したす。 coff61yaml.cpp XNUMX

フラグメント N25  N27: さらなる再割り圓お

次に、少し異なるバヌゞョンの再割り圓おを芋おみたしょう。

bool Vectorizer::vectorizeLoadChain(
    ArrayRef<Instruction *> Chain,
    SmallPtrSet<Instruction *, 16> *InstructionsProcessed) {
  ....
  unsigned Alignment = getAlignment(L0);
  ....
  unsigned NewAlign = getOrEnforceKnownAlignment(L0->getPointerOperand(),
                                                 StackAdjustedAlignment,
                                                 DL, L0, nullptr, &DT);
  if (NewAlign != 0)
    Alignment = NewAlign;
  Alignment = NewAlign;
  ....
}

PVS-Studio è­Šå‘Š: V519 [CWE-563] 「Alignment」倉数に倀が 1158 回連続しお割り圓おられおいたす。 おそらくこれは間違いです。 行: 1160、1160 を確認したす。LoadStoreVectorizer.cpp XNUMX

これは非垞に奇劙なコヌドであり、明らかに論理゚ラヌが含たれおいたす。 初めは倉数 アラむンメント 条件に応じお倀が割り圓おられたす。 そしお再び割り圓おが行われたすが、チェックは行われたせん。

同様の状況がここでも芋られたす。

  • V519 [CWE-563] 「Effects」倉数に倀が 152 回連続しお割り圓おられたす。 おそらくこれは間違いです。 行: 165、165 を確認したす。WebAssemblyRegStackify.cpp XNUMX
  • V519 [CWE-563] 'ExpectNoDerefChunk' 倉数に 4970 回連続しお倀が割り圓おられたす。 おそらくこれは間違いです。 チェック行: 4973、4973。SemaType.cpp XNUMX

フラグメント N28: 垞に true 条件

static int readPrefixes(struct InternalInstruction* insn) {
  ....
  uint8_t byte = 0;
  uint8_t nextByte;
  ....
  if (byte == 0xf3 && (nextByte == 0x88 || nextByte == 0x89 ||
                       nextByte == 0xc6 || nextByte == 0xc7)) {
    insn->xAcquireRelease = true;
    if (nextByte != 0x90) // PAUSE instruction support             // <=
      break;
  }
  ....
}

PVS-Studio の譊告: V [CWE-571] 匏 'nextByte != 0x90' は垞に true です。 X86逆アセンブラヌデコヌダヌ.cpp 379

怜査しおも意味ないよ。 倉数 次のバむト 垞に倀ず等しくない 0x90、前のチェックから続きたす。 これはある皮の論理゚ラヌです。

フラグメント N29 - N...: 垞に true/false 条件

アナラむザヌは、状態党䜓が悪化するずいう譊告を倚数発行したす (V) たたはその䞀郚 (V) は垞に true たたは false です。 倚くの堎合、これらは実際の゚ラヌではなく、単玔にずさんなコヌドやマクロ展開の結果などです。 ただし、本物の論理゚ラヌが時々発生するため、これらの譊告をすべお確認するこずは意味がありたす。 たずえば、コヌドの次のセクションは疑わしいです。

static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
                                   uint64_t Address, const void *Decoder) {
  DecodeStatus S = MCDisassembler::Success;

  if (RegNo > 13)
    return MCDisassembler::Fail;

  if ((RegNo & 1) || RegNo == 0xe)
     S = MCDisassembler::SoftFail;
  ....
}

PVS-Studio の譊告: V [CWE-570] 条件匏の䞀郚が垞に false になりたす: RegNo == 0xe。 ARMDisassembler.cpp 939

定数 0xE は、14 進数の倀 XNUMX です。 怜査 RegNo == 0xe 意味がありたせん。 登録番号 > 13、その埌、関数は実行を完了したす。

他にも ID V547 および V560 の譊告が倚数ありたしたが、 V, 私はこれらの譊告を研究するこずに興味がありたせんでした。 蚘事を曞くのに十分な材料があるこずはすでに明らかでした :)。 したがっお、PVS-Studio を䜿甚しお LLVM でこのタむプの゚ラヌをどれだけ特定できるかは䞍明です。

これらのトリガヌの研究が退屈である理由の䟋を瀺したす。 アナラむザヌが次のコヌドに察しお譊告を発行したのは完党に正しいです。 しかし、これも間違いではありたせん。

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

PVS-Studio è­Šå‘Š: V547 [CWE-570] 匏 '!HasError' は垞に false です。 1635

フラグメントN30: 䞍審な垰還

static bool
isImplicitlyDef(MachineRegisterInfo &MRI, unsigned Reg) {
  for (MachineRegisterInfo::def_instr_iterator It = MRI.def_instr_begin(Reg),
      E = MRI.def_instr_end(); It != E; ++It) {
    return (*It).isImplicitDef();
  }
  ....
}

PVS-Studio の譊告: V [CWE-670] ルヌプ内の無条件の「リタヌン」。 R600OptimizeVectorRegisters.cpp 63

これぱラヌ、たたはコヌドを読んでいるプログラマヌに䜕かを説明するこずを目的ずした特定のテクニックのいずれかです。 このデザむンは私には䜕も説明できず、非垞に疑わしいように芋えたす。 そのように曞かないほうがいいです:)。

疲れた 次に、お茶たたはコヌヒヌを䜜る時間です。

PVS-Studio アナラむザヌを䜿甚した LLVM 8 のバグの怜玢

新しい蚺断によっお特定された欠陥

叀い蚺断のアクティベヌションは 30 回で十分だず思いたす。 次に、アナラむザヌに衚瀺された新しい蚺断でどのような興味深いこずが芋぀かるかを芋おみたしょう。 前ぞ 小切手。 この期間䞭に、合蚈 66 の汎甚蚺断が C++ アナラむザヌに远加されたした。

フラグメント N31: 到達䞍胜なコヌド

Error CtorDtorRunner::run() {
  ....
  if (auto CtorDtorMap =
          ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names),
                    NoDependenciesToRegister, true))
  {
    ....
    return Error::success();
  } else
    return CtorDtorMap.takeError();

  CtorDtorsByPriority.clear();

  return Error::success();
}

PVS-Studio の譊告: V [CWE-561] 到達䞍胜なコヌドが怜出されたした。 ゚ラヌが存圚する可胜性がありたす。 実行ナヌティリティ.cpp 146

ご芧のずおり、挔算子の䞡方の分岐は if オペレヌタヌぞの電話で終了 return。 したがっお、コンテナは、 CtorDtorsByPriority 決しおクリアされたせん。

フラグメント N32: 到達䞍胜なコヌド

bool LLParser::ParseSummaryEntry() {
  ....
  switch (Lex.getKind()) {
  case lltok::kw_gv:
    return ParseGVEntry(SummaryID);
  case lltok::kw_module:
    return ParseModuleEntry(SummaryID);
  case lltok::kw_typeid:
    return ParseTypeIdEntry(SummaryID);                        // <=
    break;                                                     // <=
  default:
    return Error(Lex.getLoc(), "unexpected summary kind");
  }
  Lex.setIgnoreColonInIdentifiers(false);                      // <=
  return false;
}

PVS-Studio è­Šå‘Š: V779 [CWE-561] 到達䞍胜なコヌドが怜出されたした。 ゚ラヌが存圚する可胜性がありたす。 LLParser.cpp 835

興味深い状況です。 たずはこの堎所を芋おみたしょう。

return ParseTypeIdEntry(SummaryID);
break;

䞀芋するず、ここには間違いがないように芋えたす。 オペレヌタヌっぜい ç Žã‚‹ ここには䜙分なものがありたすが、単玔に削陀できたす。 ただし、すべおがそれほど単玔ではありたせん。

アナラむザヌは次の行で譊告を発行したす。

Lex.setIgnoreColonInIdentifiers(false);
return false;

そしお確かに、このコヌドは到達できたせん。 すべおのケヌス スむッチ オペレヌタヌからの電話で終了 return。 そしお今は䞀人では無意味 ç Žã‚‹ それほど無害には芋えたせん おそらくブランチの XNUMX ぀は次のように終わるはずです。 砎るしかしではない return?

フラグメント N33: 䞊䜍ビットのランダム リセット

unsigned getStubAlignment() override {
  if (Arch == Triple::systemz)
    return 8;
  else
    return 1;
}

Expected<unsigned>
RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
                             const SectionRef &Section,
                             bool IsCode) {
  ....
  uint64_t DataSize = Section.getSize();
  ....
  if (StubBufSize > 0)
    DataSize &= ~(getStubAlignment() - 1);
  ....
}

PVS-Studio の譊告: V ビット マスクのサむズは、最初のオペランドのサむズよりも小さいです。 これにより、䞊䜍ビットが倱われたす。 ランタむムディルド.cpp 815

機胜に泚意しおください getStubAlignment 戻り倀の型 眲名されおいない。 関数が倀 8 を返すず仮定しお、匏の倀を蚈算しおみたしょう。

~(getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

ここで、倉数に泚目しおください。 デヌタサむズ 64 ビットの笊号なし型を持ちたす。 DataSize & 0xFFFFFFF8u 操䜜を実行するず、䞊䜍 0 ビットがすべお 8 にリセットされるこずがわかりたす。 おそらく、これはプログラマが望んでいたものではありたせん。 おそらく圌は DataSize & XNUMXxFFFFFFFFFFFFFFXNUMXu を蚈算したかったのだず思いたす。

゚ラヌを修正するには、次のように蚘述する必芁がありたす。

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

それずも

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

フラグメント N34: 明瀺的な型キャストの倱敗

template <typename T>
void scaleShuffleMask(int Scale, ArrayRef<T> Mask,
                      SmallVectorImpl<T> &ScaledMask) {
  assert(0 < Scale && "Unexpected scaling factor");
  int NumElts = Mask.size();
  ScaledMask.assign(static_cast<size_t>(NumElts * Scale), -1);
  ....
}

PVS-Studio の譊告: V [CWE-190] オヌバヌフロヌの可胜性がありたす。 'NumElts * Scale' 挔算子のオペランドを結果ではなく 'size_t' 型にキャストするこずを怜蚎しおください。 X86ISelLowering.h 1577

型倉数を乗算する際のオヌバヌフロヌを避けるために、明瀺的な型キャストが䜿甚されたす。 int型。 ただし、ここでの明瀺的な型キャストはオヌバヌフロヌを防ぐものではありたせん。 たず倉数が乗算され、その埌で乗算の 32 ビット結果が型に展開されたす。 サむズ_t.

フラグメント N35: コピヌペヌストの倱敗

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

V [CWE-682] 1 ぀の類䌌したコヌドの断片が芋぀かりたした。 おそらく、これはタむプミスであり、「Op0」の代わりに「Op5507」倉数を䜿甚する必芁がありたす。 InstCombineCompares.cpp XNUMX

この新しい興味深い蚺断は、コヌドの䞀郚がコピヌされ、その䞭の䞀郚の名前が倉曎され始めおいるにもかかわらず、ある堎所が修正されおいない状況を特定したす。

XNUMX 番目のブロックでは倉曎されおいるこずに泚意しおください Op0 Ма Op1。 しかし、ある堎所では修正されたせんでした。 おそらく次のように曞かれおいるはずです。

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

フラグメント N36: 倉数の混乱

struct Status {
  unsigned Mask;
  unsigned Mode;

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

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

PVS-Studio の譊告: V [CWE-563] 「Mode」倉数が割り圓おられおいたすが、関数の最埌たでは䜿甚されたせん。 SIModeRegister.cpp 48

関数の匕数にクラス メンバヌず同じ名前を付けるのは非垞に危険です。 非垞に混乱しやすいです。 たさにそのようなケヌスが私たちの目の前にありたす。 この衚珟は意味がありたせん:

Mode &= Mask;

関数の匕数が倉わりたす。 それだけです。 この匕数はもう䜿甚されたせん。 ほずんどの堎合、次のように蚘述する必芁がありたす。

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

フラグメント N37: 倉数の混乱

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

è­Šå‘Š PVS-Studio: V1001 [CWE-563] 「Size」倉数が割り圓おられおいたすが、関数の最埌たでは䜿甚されたせん。 オブゞェクト.cpp 424

状況は前回ず同様です。 次のように曞く必芁がありたす:

this->Size += this->EntrySize;

断片 N38-N47: むンデックスを確認するのを忘れたした

前回は、蚺断トリガヌの䟋に぀いお説明したした。 V。 その本質は、ポむンタが最初に逆参照され、その埌にのみチェックされるこずです。 若い蚺断者 V 意味は逆ですが、倚くの間違いも明らかになりたす。 ポむンタが最初にチェックされ、その埌チェックを忘れた状況を識別したす。 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());  // <=
  ....
}

PVS-Studio è­Šå‘Š: V1004 [CWE-476] 'Ptr' ポむンタヌは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行: 729、738 を確認しおください。TargetTransformInfoImpl.h 738

可倉 PTR 等しいかもしれない nullptr、チェックによっお蚌明されるように:

if (Ptr != nullptr)

ただし、このポむンタより䞋では、事前チェックなしで逆参照されたす。

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

別の同様のケヌスを考えおみたしょう。

llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
                                                          bool Stub) {
  ....
  auto *FD = dyn_cast<FunctionDecl>(GD.getDecl());
  SmallVector<QualType, 16> ArgTypes;
  if (FD)                                                                // <=
    for (const ParmVarDecl *Parm : FD->parameters())
      ArgTypes.push_back(Parm->getType());
  CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv(); // <=
  ....
}

PVS-Studio è­Šå‘Š: V1004 [CWE-476] 「FD」ポむンタヌは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行を確認しおください: 3228、3231。CGDebugInfo.cpp 3231

暙識に泚意しおください FD。 問題は明らかであり、特別な説明は必芁ないず思いたす。

さらに

static void computePolynomialFromPointer(Value &Ptr, Polynomial &Result,
                                         Value *&BasePtr,
                                         const DataLayout &DL) {
  PointerType *PtrTy = dyn_cast<PointerType>(Ptr.getType());
  if (!PtrTy) {                                                   // <=
    Result = Polynomial();
    BasePtr = nullptr;
  }
  unsigned PointerBits =
      DL.getIndexSizeInBits(PtrTy->getPointerAddressSpace());     // <=
  ....
}

PVS-Studio è­Šå‘Š: V1004 [CWE-476] 「PtrTy」ポむンタヌは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行を確認しおください: 960、965。 InterleavedLoadCombinePass.cpp 965

このような゚ラヌから身を守るにはどうすればよいでしょうか? コヌドレビュヌにさらに泚意を払い、PVS-Studio 静的アナラむザヌを䜿甚しおコヌドを定期的にチェックしおください。

このタむプの゚ラヌがある他のコヌド断片を匕甚するこずは意味がありたせん。 蚘事には譊告のリストのみを残しおおきたす。

  • V1004 [CWE-476] 'Expr' ポむンタは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行を確認しおください: 1049、1078。 DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] nullptr に察しお怜蚌された埌、「PI」ポむンタが安党に䜿甚されたせんでした。 行を確認しおください: 733、753。 LegacyPassManager.cpp 753
  • V1004 [CWE-476] 「StatepointCall」ポむンタは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行を確認しおください: 4371、4379。 Verifier.cpp 4379
  • V1004 [CWE-476] 「RV」ポむンタは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行を確認したす: 2263、2268。TGParser.cpp 2268
  • V1004 [CWE-476] 'CalleeFn' ポむンタヌは、nullptr に察しお怜蚌された埌、安党に䜿甚されたせんでした。 行を確認しおください: 1081、1096。SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] nullptr に察しお怜蚌された埌、'TC' ポむンタが安党に䜿甚されたせんでした。 行を確認しおください: 1819、1824。 Driver.cpp 1824

フラグメント N48  N60: 重倧ではありたせんが、欠陥 (メモリ リヌクの可胜性がありたす)

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

PVS-Studio の譊告: V [CWE-460] 所有者のないポむンタが「emplace_back」メ゜ッドによっお「Strategies」コンテナに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-isel-fuzzer.cpp 58

次のようにコンテナの最埌に芁玠を远加するには std::vector > ただ曞くこずはできたせん xxx.push_back(新しい X)からの暗黙的な倉換がないため、 X* в std::unique_ptr.

䞀般的な解決策は次のように曞くこずです xxx.emplace_back(新しい X)コンパむルされるのでメ゜ッド emplace_back 匕数から盎接芁玠を構築するため、明瀺的なコンストラクタヌを䜿甚できたす。

安党ではありたせん。 ベクタヌがいっぱいの堎合、メモリが再割り圓おされたす。 メモリの再割り圓お操䜜が倱敗し、䟋倖がスロヌされる堎合がありたす。 std::bad_alloc。 この堎合、ポむンタは倱われ、䜜成されたオブゞェクトは削陀されたせん。

安党な解決策は、 unique_ptrこれは、ベクトルがメモリの再割り圓おを詊みる前にポむンタを所有したす。

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

C++14 以降、「std::make_unique」を䜿甚できたす。

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

このタむプの欠陥は、LLVM にずっお重倧ではありたせん。 メモリを割り圓おられない堎合、コンパむラは単に停止したす。 ただし、長いアプリケヌションの堎合は、 皌働時間メモリ割り圓おに倱敗した堎合に単に終了するこずはできたせんが、これは非垞に厄介なバグである可胜性がありたす。

したがっお、このコヌドは LLVM に察しお実質的な脅嚁をもたらすものではありたせんが、この゚ラヌ パタヌンず、PVS-Studio アナラむザヌがそれを識別する方法を孊習したこずに぀いお説明するこずが有益であるこずがわかりたした。

このタむプのその他の譊告:

  • V1023 [CWE-460] 所有者のないポむンタヌが、「emplace_back」メ゜ッドによっお「Passes」コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 PassManager.h 546
  • V1023 [CWE-460] 所有者のないポむンタヌが 'emplace_back' メ゜ッドによっお 'AAs' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 ゚むリアス分析.h 324
  • V1023 [CWE-460] 所有者のないポむンタヌが、「emplace_back」メ゜ッドによっお「Entries」コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'AllEdges' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 CFGMST.h 268
  • V1023 [CWE-460] 所有者のないポむンタヌが 'emplace_back' メ゜ッドによっお 'VMaps' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 SimpleLoopUnswitch.cpp 2012
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Records' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 FDRLogBuilder.h 30
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'PendingSubmodules' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 モゞュヌルマップ.cpp 810
  • V1023 [CWE-460] 所有者のないポむンタヌが 'emplace_back' メ゜ッドによっお 'Objects' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 デバッグマップ.cpp 88
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Strategies' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 685
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 686
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 688
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 689
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 690
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 691
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 692
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 693
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Modifiers' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 llvm-ストレス.cpp 694
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Operands' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] 所有者のないポむンタヌが、'emplace_back' メ゜ッドによっお 'Stash' コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] 所有者のないポむンタヌが、「emplace_back」メ゜ッドによっお「Matchers」コンテナヌに远加されたす。 䟋倖が発生するずメモリ リヌクが発生したす。 GlobalISelEmitter.cpp 2702

たずめ

合蚈60回の譊告を発しお停止したした。 PVS-Studio アナラむザヌが LLVM で怜出する他の欠陥はありたすか? はい、ありたす。 しかし、蚘事甚のコヌドの断片を曞き出しおいるず、倕方、ずいうか倜になっおしたったので、もう終わりにしようず決心したした。

興味を持っおいただき、PVS-Studio アナラむザヌを詊しおみおいただければ幞いです。

アナラむザヌをダりンロヌドしお、マむンスむヌパのキヌを入手できたす。 このペヌゞ.

最も重芁なこずは、静的分析を定期的に䜿甚するこずです。 XNUMX回限りのチェック、静的解析の方法論ず PVS-Studio を普及させるために圓瀟が実斜するシナリオは通垞のシナリオではありたせん。

コヌドの品質ず信頌性が向䞊するよう頑匵っおください。

PVS-Studio アナラむザヌを䜿甚した LLVM 8 のバグの怜玢

この蚘事を英語圏の読者ず共有したい堎合は、翻蚳リンクを䜿甚しおください: Andrey Karpov。 PVS-Studio を䜿甚した LLVM 8 のバグの怜玢.

出所 habr.com

コメントを远加したす