ホームページ >Java >&#&チュートリアル >PVS-Studio 4 の新しい診断ルール
PVS-Studio 7.34 リリースでは、Java の汚染分析、C# の Unity 固有の診断ルール、OWASP の詳細など、多数の新しい診断ルールがアナライザーに導入されました。この記事ではそれらすべてを説明します。
このリリースでは、C チームは一般分析診断ルールとさまざまなソフトウェア開発標準のサポートに焦点を当てました。
しかし、帽子をしっかり持ってください、これはほんの始まりにすぎません!チームはさらに多くの MISRA 標準診断ルールをカバーする予定ですので、さらなるニュースにご期待ください :)
そして今のところ、7.34 リリースの主なルールを見てみましょう。
この診断ルールは、説明メッセージなしで作成された例外を検出するように設計されています。
メッセージが存在しないと、エラーの検出と修正のプロセスが妨げられるだけでなく、全体的なコードの可読性が低下する可能性があります。
PVS-Studio アナライザーに警告を生成させるコードの例を次に示します。
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
エラーが発生した場合、SomeCheck 関数は空のメッセージを含む例外をスローします。これは Foo 関数で処理されます。処理中、std::cerr には例外の理由に関する情報が含まれることが期待されますが、含まれていません。
このようにコードを記述することで、開発者は同僚に「楽しくデバッグしてください」という願いを送ります。これは、失敗の正確な原因を理解するのを妨げます。
ルールは標準例外に対して機能します。カスタム アノテーション メカニズムを使用して、カスタム例外の警告を発行できます。
この診断ルールの詳細については、ドキュメントを確認してください。
この診断ルールは C 言語にのみ適用されます。
const または volatile 修飾子を使用する関数型定義のケースを検出することを目的としています。
C23 標準 (6.7.4.1 項の 10 番目の点) によれば、これらの型を使用すると未定義の動作が発生します。
PVS-Studio アナライザーに警告を生成させるコードの例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
この診断ルールの詳細については、ドキュメントを確認してください。
リファクタリングやデバッグの際に役立つ C 言語のもう 1 つの診断ルール。
このルールにより、アナライザーは整数型から enum 型への暗黙的なキャストを検出できるようになります。
PVS-Studio 警告を含むコード例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
このコードは条件演算子 (?:) を使用して 2 つの整数変数 posOne と posTwo のどちらかを選択し、暗黙的なキャストが行われます。
この診断ルールの詳細については、ドキュメントを確認してください。
これは、SAST 原則に沿った、セキュリティに焦点を当てた新しい診断ルールです。
このルールは、OWASP セキュリティ検証標準に従って設計されました。
これは、廃止された暗号化関数の呼び出しを検出することを目的としています。これらを使用すると、重大なソフトウェア セキュリティ問題が発生する可能性があります。
PVS-Studio 警告を含むコード例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
Microsoft のドキュメントによると、CryptoImportKey 関数と CryptoDestroyKey 関数は非推奨になっています。これらは、Cryptography Next Generation の安全な対応物 (BCryptoImportKey および BCryptoDestroyKey) に置き換える必要があります。
この診断ルールの詳細については、ドキュメントを確認してください。
しかし、それは単なるウォームアップです! C および C チームは、さまざまなソフトウェア開発標準に関するさらに多くの診断ルールをカバーする予定です。 MISRA 規格には特別な注意が払われます。それでは、ニュースをお待ちください:)
新しい PVS-Studio 7.34 リリースでは、C# チームは Unity 固有の診断ルールの作成に重点を置きましたが、一般分析ルールも忘れていませんでした。
後者から始めましょう。
この新しい診断ルールは、A または B ではないパターンの誤った使用を検出することを目的としています。この問題は、操作の優先順位に関する開発者の混乱に起因します。
PVS-Studio 警告を含むコード例:
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
メソッドの開始時に、入力パラメータのキーが空の文字列または null かどうかチェックされます。
しかし、条件式の論理に誤りがあります。 not 演算子の優先順位は、or 演算子の優先順位よりも高くなります。その結果、否定は式の右辺には適用されません。また、key が null に設定されている場合、条件は true になります。
この診断ルールの詳細については、ドキュメントを確認してください。
これは、Unity 固有の新しいルール シリーズの最初の診断ルールです。
UnityEngine.Object (またはそこから継承された他のオブジェクト) と System.WeakReference の使用を検出することを目的としています。
エンジン自体によるインスタンスの暗黙的な使用により、弱い参照の動作は予期されたものと異なる場合があります。
PVS-Studio 警告を含むコード例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
この例では、GameObject クラスのオブジェクトへの弱い参照が見られます。作成者がこのオブジェクトへの強い参照を作成していない場合でも、ガベージ コレクターはそれをクリーンアップできません。
この診断ルールの詳細については、ドキュメントを確認してください。
Unity の別の診断ルールでは、アナライザーは await 演算子を使用して同じ UnityEngine.Awaitable オブジェクトが複数使用されている場所を検索します。
オブジェクトは、最適化の目的でオブジェクト プールに保存されます。
await-call では、Awaitable オブジェクトがプールに返されます。その後、同じオブジェクトに再度 await が適用されると、例外が発生します。場合によっては、デッドロックが発生する可能性もあります。
PVS-Studio 警告を含むコード例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
このコードでは、例外またはデッドロックが発生します。その理由を説明しましょう。 awaitable の await 呼び出しを使用して値を取得します。次に、結果変数をこの値で初期化します。以前に条件付き構造で awaitable に await が適用されていたため、デッドロックが発生します。
この診断ルールの詳細については、ドキュメントを確認してください。
この診断ルールは、UnityEngine.Object クラスの Destroy メソッドまたは DestroyImmediate メソッドの呼び出しに関連する異常を検出することを目的としています。
この問題は、UnityEngine.Transform 型の引数が使用されている状況で発生します。これにより、メソッド呼び出し中にエラーが発生します。ゲーム オブジェクトから Transform コンポーネントを削除することは、Unity では許可されていません。
PVS-Studio 警告を含むコード例:
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
MonoBehaviour 基本クラスのtransform プロパティは、Transform クラスのインスタンスを返し、これが引数として Destroy メソッドに渡されます。
この方法でメソッドを呼び出すと、Unity はエラー メッセージを表示しますが、コンポーネント自体は破棄されません。
この診断ルールの詳細については、ドキュメントを確認してください。
この診断ルールは、さまざまな範囲のエラー、つまりパフォーマンスの問題を対象としています。
静的分析が Unity プロジェクトの最適化にどのように役立つかに興味がある場合は、ぜひこの記事をお読みください。
このルールの目的は、頻繁に実行されるメソッドでの Unity オブジェクトの作成をアナライザーが検出できるようにすることです。
ゲーム オブジェクトを定期的に作成/破棄すると、CPU に負荷がかかるだけでなく、ガベージ コレクターの呼び出し頻度も増加します。これはパフォーマンスに影響します。
PVS-Studio 警告を含むコード例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
ここの Update メソッドでは、ゲーム オブジェクト _instance が作成され、破棄されます。 Update はフレームが更新されるたびに実行されるため、可能な限りこれらの操作を避けることをお勧めします。
この診断ルールの詳細については、ドキュメントを確認してください。
ところで、他の Unity 診断はまだ公開されていません。私たちのチームからの良いニュースを受け取る準備をしてください:)
C# アナライザーの重要な機能強化の 1 つ、つまり呼び出し間のメソッドの戻り値の変更の追跡についてお知らせするしかありません。それによって何が変わるのでしょうか?分解してみましょう。
この例を確認してください:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
Example() メソッドは、Foo() の戻り値が null かどうかをチェックします。その後、条件の本文で Foo() メソッドが再度呼び出され、その戻り値が逆参照されます。
以前は、アナライザーは呼び出しのコンテキストを考慮せず、宣言のコードのみに焦点を当てていたため、この場合に警告を生成していました。アナライザーは、null が返される可能性があることを暗示していました。
アナライザーは、Foo() がどちらの場合も同じ値を返すことを認識し、警告は表示されません。
しかし、コードを少し変更した例を見てみましょう...
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
Foo() メソッドの宣言から、_condition == true の場合、メソッドは null 以外を返すことがわかります。
アナライザーは 2 回目の呼び出しの前に _condition フィールドの変更を確認し、Foo() 内で使用されるフィールドが変更された場合、Foo() の戻り値も変更された可能性があると推測します。
その結果、逆参照の可能性に関する警告が残ります。
C# アナライザーが .NET 9 プロジェクトの分析をサポートするようになりました。 PVS-Studio 7.34 のこれらおよびその他の新機能の詳細については、こちらをご覧ください。
PVS-Studio 7.34 のリリースにより、Java アナライザーにテイント分析のメカニズムが追加されました!
このメカニズムは、最初の診断ルールである SQL インジェクションの検索の基礎となりました。 Java アナライザーの将来の更新では、SAST、最も一般的な潜在的な脆弱性の OWASP トップ 10 リスト、およびその他のテイント関連の診断ルールに焦点を当てます。
ここで、いくつかの新しい一般分析ルールから始めましょう。これも価値のあるものです。
この新しい診断ルールは、後置演算の値が使用されていないコード内の領域を強調表示します。
問題は、操作が冗長であるか、より深刻な問題として、操作が混同され、開発者が接頭辞 1 を使用したいと考えたことです。
PVS-Studio 警告を含むコード例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
演算子は、calculateSomething メソッドが返す値には影響しません。
この診断ルールの詳細については、ドキュメントを確認してください。
この診断ルールの名前からわかるように、オーバーフローの可能性を検出します。
PVS-Studio 警告を含むコード例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
整数型の変数に有効な範囲外の値が割り当てられているため、オーバーフローが発生します。
変数には、開発者が割り当てようとした値とは明らかに異なる値が格納されます。
この診断ルールの詳細については、ドキュメントを確認してください。
この診断は、同期の問題を特定するのに役立ちます。
PVS-Studio 警告を含むコード例:
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
アナライザーは、非同期コンテキストで呼び出される可能性がある wait、notify、および NoticeAll メソッドを検出します。これらは、同期が行われるオブジェクトのモニターで動作します。つまり、それらの呼び出しは、同期されたコンテキスト内でのみ、また同期が行われるオブジェクト上でのみ正しくなります。
wait、notify、または NoticeAll メソッドが非同期コンテキストまたは間違ったオブジェクトで呼び出された場合、IllegalMonitorStateException 例外が発生します。
この診断ルールの詳細については、ドキュメントを確認してください。
Java アナライザーの最初のテイント関連診断ルール!具体的には、アナライザーは潜在的な SQL インジェクションを検出できるようになりました。
SQL インジェクションは、攻撃者がコードを SQL クエリに挿入できるようにする脆弱性です。クエリで外部データを使用する場合、それを正しく検証しないと、データベースに保存されている情報の整合性と機密性が危険にさらされることになります。
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
ユーザーが悪意があることが判明し、param の値がほぼ次の場合: - 「111' または 1=1; テーブル ユーザーを削除; ' 」を選択 - ユーザー テーブルに別れを告げることができます。したがって、外部データを確認することが重要です。
この診断ルールの詳細については、ドキュメントを確認してください。
読んでいただきありがとうございます!
記事のリクエストやご質問がございましたら、お気軽にフィードバックフォームよりお送りください。最後になりましたが、ぜひコメント欄でご意見をお聞かせください:)
以上がPVS-Studio 4 の新しい診断ルールの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。