SCW アイコン
ヒーロー背景(区切りなし)
ブログ

Java問題 - ビット単位演算子とブール演算子

アラン・リチャードソン
2021年02月07日 掲載
最終更新日: 2026年3月9日

Java問題 - ビット単位演算子とブール演算子

「Java Gotcha」 - 誤って実装しやすい一般的なミスパターンです。

Javaでうっかり陥りやすい非常に単純な問題の一つは、ブール比較演算子の代わりにビット単位演算子を使用してしまうことです。

例えば、本当に「&&」を使おうとしたときに、単純な入力ミスによって「&」を使う可能性があります。

コードをレビューする際に一般的に学ぶヒューリスティックは以下の通りです。

「&」または「|」を条件式で使用することは意図されたものではない可能性があります。

このブログ記事では、ヒューリスティックを検討し、このコーディング問題を特定して解決する方法を探ります。


何が問題なんだ?ビット単位の演算はブール値で正常に動作します。


ブール値と共にビット演算子を使用することは完全に有効であるため、Javaは構文エラーを報告しません。

ビット単位の論理和(|)とビット単位の論理積(&)の両方について真理値表を探索するためにJUnitテストを構成すると、ビット演算子の出力が真理値表と一致していることが確認できます。こうした点を考慮すると、ビット演算子を使用することに問題はないと考えられるかもしれません。

AND 真値表

aで3列、bで1列、最後に(a^b)で1列。


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


テストを通過しました。これは完全に有効なJavaです。


OR 真値表


aで3列、bで1列、最後に(a v b)で1列。


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


このテストも通過したのに、なぜ「&&」と「||」を好むのでしょうか?


真理値表の画像は以下を使用して生成されました。 真実値表ツール ...から web.standfor.edu.


問題:段落動作


本当の問題はビット演算子(&, |)とブール演算子(&&, ||)の動作の違いです。

ブール演算子はショートカット演算子であり、必要な部分のみを評価します。

例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


このコードではビット演算子が使用されているため、両方のブール条件が評価されます。

  • 인수!= ゼロ
  • 引数。長さ () > 23

このようにすると、引数がnullの場合に私のコードがNullPointerExceptionを発生させます。両方のブール条件を評価する必要があるため、引数がnullの場合でも常にargs.lengthチェックが実行されるからです。


ブール演算子のショート回路評価


&&を使用する場合 例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


その引数を知った瞬間!= nullがfalseと評価されると、条件式の評価は停止します。

右側を評価する必要はありません。

右側の条件の結果が何であれ、ブール式の結果はfalseになります。


しかし、本番コードではこのようなことは絶対に起こりません。


これは非常に簡単に犯す可能性のあるミスであり、静的解析ツールが常に検出できるとは限りません。

次のGoogle Dorkを使用して、このパターンの公開事例が見つかるかどうかを確認しました。

ファイル形式: “! の場合 Java=null &”
この検索により、Androidの一部コードがルートウィンドウコンテナに持ち込まれました。
ISDocument = Intent!= null & Intent.isDocument()


ビット演算子を使用して値をマスキングするケースが多いため、コードレビューを通過できるコードタイプです。ただしこの場合、結果は上記のif文の例と同じです。intentが常にnullの場合、NullPointerExceptionが発生します。

私たちはしばしば防御的な方法でコーディングし、重複コードを書くため、この構文を使用しないことが多いです。`== null` はほとんどのユースケースで重複する可能性があります。

これはプログラマーが本番コードで作成したエラーです。

検索結果がどれほど最新かはわかりませんが、検索を実行した際にGoogle、Amazon、Apache...そして私のコードが含まれた結果が表示されました。

最近、プルリクエスト内のオープンソースプロジェクトの一つで、まさにこのエラーを解決する必要がありました。

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


これを調べる方法


いくつかの静的解析ツールでサンプルコードを確認した際、この隠された自己破壊コードを発見したものは一つもありませんでした。

Secure Code Warriorチームとして、私たちはこの問題を解決できる非常にシンプルなセンセイレシピを作成し、レビューしました。

ビット演算子は完全に有効であり、代入で頻繁に使用されるため、if文の使用事例とビット演算子&を使用した問題のあるコードの発見に焦点を当てました。

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


これは正規表現を使用して条件式として使用される際に「&」と一致します(例:if文内)。

この問題を解決するために、私たちは再び正規表現を使用しました。今回はQuickFixのsed関数を使用して、表現式内の&を&&にグローバルに置換しました。

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


エンドノート

ここではビット演算子の最も一般的な誤用、つまりブール演算子が実際に意図されている場合について説明します。

例えば、入力例のような他の状況が発生する可能性がありますが、レシピを作成する際には偽陽性の識別を避ける必要があります。そうしないと、レシピが無視されたり無効化されたりします。私たちは最も頻繁に発生する状況に適合するレシピを作成します。Senseiが進化するにつれ、より多くの条件を網羅するために検索機能に特定の機能を追加する予定です。

現在の形態で見ると、このレシピは多くの実際の使用事例を特定できます。最も重要なのは、私のプロジェクトで報告された内容です。

注記: チャーリー・エリクセン、マティユ・カリ、ロビン・クレアハウト、ブライソン・アクス、ネイサン・デスメット、ダウニー・ロバーズショーテンなどのコード戦士たちがこの例とレシピのレビューに貢献しました。ご協力ありがとうございました。


---


IntelliJ内で「環境設定\プラグイン」(Mac)または「設定\プラグイン」(Windows)を使用してSenseiをインストールした後、「センセイ セキュリティコード」を検索するだけです。

Secure Code Warrior `sensei`リポジトリには、これらのブログ記事(この記事を含む)に関する多くのソースコードとレシピがあります。

https://github.com/securecodewarrior/sensei-blog-examples

先生についてもっと知る


リソースを見る
リソースを見る

このブログ記事では、一般的なJavaコーディングミス(条件演算子の代わりにビット演算子を使用)、これによりコードが脆弱になるエラー、Senseiを使用して問題を解決・検出する方法について見ていきます。

もっと興味がありますか?

アラン・リチャードソンは、20年以上にわたり、開発者として、またテスターからテスト責任者まで、あらゆるレベルのテストに携わってきたプロフェッショナルなIT経験を持っています。アラン・リチャードソンは、Secure Code Warrior のデベロッパーリレーションズの責任者として、チームと直接連携し、高品質で安全なコードの開発を促進しています。また、「Dear Evil Tester」や「Java For Testers」など4冊の著書があります。また、テクニカルWebテストやSelenium WebDriver with Javaを学ぶためのオンライントレーニングcourses を作成しています。アランは、SeleniumSimplified.com、EvilTester.com、JavaForTesters.com、CompendiumDev.co.ukに執筆やトレーニングビデオを掲載している。

もっと詳しく

セキュアコードウォリアーは、ソフトウェア開発ライフサイクル全体を通じてコードを保護し、サイバーセキュリティを最優先とする文化を組織に根付かせるために存在します。AppSec管理者、開発者、CISO、あるいはセキュリティに関わるあらゆる立場の方々に対し、組織が安全でないコードに関連するリスクを軽減できるよう支援します。

デモ予約
共有対象:
リンクトインのブランドソーシャルx ロゴ
作成者
アラン・リチャードソン
2021年02月07日掲載

アラン・リチャードソンは、20年以上にわたり、開発者として、またテスターからテスト責任者まで、あらゆるレベルのテストに携わってきたプロフェッショナルなIT経験を持っています。アラン・リチャードソンは、Secure Code Warrior のデベロッパーリレーションズの責任者として、チームと直接連携し、高品質で安全なコードの開発を促進しています。また、「Dear Evil Tester」や「Java For Testers」など4冊の著書があります。また、テクニカルWebテストやSelenium WebDriver with Javaを学ぶためのオンライントレーニングcourses を作成しています。アランは、SeleniumSimplified.com、EvilTester.com、JavaForTesters.com、CompendiumDev.co.ukに執筆やトレーニングビデオを掲載している。

共有対象:
リンクトインのブランドソーシャルx ロゴ

Java問題 - ビット単位演算子とブール演算子

「Java Gotcha」 - 誤って実装しやすい一般的なミスパターンです。

Javaでうっかり陥りやすい非常に単純な問題の一つは、ブール比較演算子の代わりにビット単位演算子を使用してしまうことです。

例えば、本当に「&&」を使おうとしたときに、単純な入力ミスによって「&」を使う可能性があります。

コードをレビューする際に一般的に学ぶヒューリスティックは以下の通りです。

「&」または「|」を条件式で使用することは意図されたものではない可能性があります。

このブログ記事では、ヒューリスティックを検討し、このコーディング問題を特定して解決する方法を探ります。


何が問題なんだ?ビット単位の演算はブール値で正常に動作します。


ブール値と共にビット演算子を使用することは完全に有効であるため、Javaは構文エラーを報告しません。

ビット単位の論理和(|)とビット単位の論理積(&)の両方について真理値表を探索するためにJUnitテストを構成すると、ビット演算子の出力が真理値表と一致していることが確認できます。こうした点を考慮すると、ビット演算子を使用することに問題はないと考えられるかもしれません。

AND 真値表

aで3列、bで1列、最後に(a^b)で1列。


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


テストを通過しました。これは完全に有効なJavaです。


OR 真値表


aで3列、bで1列、最後に(a v b)で1列。


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


このテストも通過したのに、なぜ「&&」と「||」を好むのでしょうか?


真理値表の画像は以下を使用して生成されました。 真実値表ツール ...から web.standfor.edu.


問題:段落動作


本当の問題はビット演算子(&, |)とブール演算子(&&, ||)の動作の違いです。

ブール演算子はショートカット演算子であり、必要な部分のみを評価します。

例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


このコードではビット演算子が使用されているため、両方のブール条件が評価されます。

  • 인수!= ゼロ
  • 引数。長さ () > 23

このようにすると、引数がnullの場合に私のコードがNullPointerExceptionを発生させます。両方のブール条件を評価する必要があるため、引数がnullの場合でも常にargs.lengthチェックが実行されるからです。


ブール演算子のショート回路評価


&&を使用する場合 例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


その引数を知った瞬間!= nullがfalseと評価されると、条件式の評価は停止します。

右側を評価する必要はありません。

右側の条件の結果が何であれ、ブール式の結果はfalseになります。


しかし、本番コードではこのようなことは絶対に起こりません。


これは非常に簡単に犯す可能性のあるミスであり、静的解析ツールが常に検出できるとは限りません。

次のGoogle Dorkを使用して、このパターンの公開事例が見つかるかどうかを確認しました。

ファイル形式: “! の場合 Java=null &”
この検索により、Androidの一部コードがルートウィンドウコンテナに持ち込まれました。
ISDocument = Intent!= null & Intent.isDocument()


ビット演算子を使用して値をマスキングするケースが多いため、コードレビューを通過できるコードタイプです。ただしこの場合、結果は上記のif文の例と同じです。intentが常にnullの場合、NullPointerExceptionが発生します。

私たちはしばしば防御的な方法でコーディングし、重複コードを書くため、この構文を使用しないことが多いです。`== null` はほとんどのユースケースで重複する可能性があります。

これはプログラマーが本番コードで作成したエラーです。

検索結果がどれほど最新かはわかりませんが、検索を実行した際にGoogle、Amazon、Apache...そして私のコードが含まれた結果が表示されました。

最近、プルリクエスト内のオープンソースプロジェクトの一つで、まさにこのエラーを解決する必要がありました。

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


これを調べる方法


いくつかの静的解析ツールでサンプルコードを確認した際、この隠された自己破壊コードを発見したものは一つもありませんでした。

Secure Code Warriorチームとして、私たちはこの問題を解決できる非常にシンプルなセンセイレシピを作成し、レビューしました。

ビット演算子は完全に有効であり、代入で頻繁に使用されるため、if文の使用事例とビット演算子&を使用した問題のあるコードの発見に焦点を当てました。

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


これは正規表現を使用して条件式として使用される際に「&」と一致します(例:if文内)。

この問題を解決するために、私たちは再び正規表現を使用しました。今回はQuickFixのsed関数を使用して、表現式内の&を&&にグローバルに置換しました。

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


エンドノート

ここではビット演算子の最も一般的な誤用、つまりブール演算子が実際に意図されている場合について説明します。

例えば、入力例のような他の状況が発生する可能性がありますが、レシピを作成する際には偽陽性の識別を避ける必要があります。そうしないと、レシピが無視されたり無効化されたりします。私たちは最も頻繁に発生する状況に適合するレシピを作成します。Senseiが進化するにつれ、より多くの条件を網羅するために検索機能に特定の機能を追加する予定です。

現在の形態で見ると、このレシピは多くの実際の使用事例を特定できます。最も重要なのは、私のプロジェクトで報告された内容です。

注記: チャーリー・エリクセン、マティユ・カリ、ロビン・クレアハウト、ブライソン・アクス、ネイサン・デスメット、ダウニー・ロバーズショーテンなどのコード戦士たちがこの例とレシピのレビューに貢献しました。ご協力ありがとうございました。


---


IntelliJ内で「環境設定\プラグイン」(Mac)または「設定\プラグイン」(Windows)を使用してSenseiをインストールした後、「センセイ セキュリティコード」を検索するだけです。

Secure Code Warrior `sensei`リポジトリには、これらのブログ記事(この記事を含む)に関する多くのソースコードとレシピがあります。

https://github.com/securecodewarrior/sensei-blog-examples

先生についてもっと知る


リソースを見る
リソースを見る

レポートをダウンロードするには、以下のフォームにご記入ください。

当社製品および/または関連するセキュリティコーディングのトピックに関する情報をお送りするため、お客様の同意を求めます。当社は常に、お客様の個人情報を最大限の注意を払って取り扱い、マーケティング目的で他社に販売することは一切ありません。

提出
SCW成功アイコン
SCWエラーアイコン
フォームを送信するには「Analytics」クッキーを有効にしてください。完了後、いつでも再度無効にできます。

Java問題 - ビット単位演算子とブール演算子

「Java Gotcha」 - 誤って実装しやすい一般的なミスパターンです。

Javaでうっかり陥りやすい非常に単純な問題の一つは、ブール比較演算子の代わりにビット単位演算子を使用してしまうことです。

例えば、本当に「&&」を使おうとしたときに、単純な入力ミスによって「&」を使う可能性があります。

コードをレビューする際に一般的に学ぶヒューリスティックは以下の通りです。

「&」または「|」を条件式で使用することは意図されたものではない可能性があります。

このブログ記事では、ヒューリスティックを検討し、このコーディング問題を特定して解決する方法を探ります。


何が問題なんだ?ビット単位の演算はブール値で正常に動作します。


ブール値と共にビット演算子を使用することは完全に有効であるため、Javaは構文エラーを報告しません。

ビット単位の論理和(|)とビット単位の論理積(&)の両方について真理値表を探索するためにJUnitテストを構成すると、ビット演算子の出力が真理値表と一致していることが確認できます。こうした点を考慮すると、ビット演算子を使用することに問題はないと考えられるかもしれません。

AND 真値表

aで3列、bで1列、最後に(a^b)で1列。


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


テストを通過しました。これは完全に有効なJavaです。


OR 真値表


aで3列、bで1列、最後に(a v b)で1列。


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


このテストも通過したのに、なぜ「&&」と「||」を好むのでしょうか?


真理値表の画像は以下を使用して生成されました。 真実値表ツール ...から web.standfor.edu.


問題:段落動作


本当の問題はビット演算子(&, |)とブール演算子(&&, ||)の動作の違いです。

ブール演算子はショートカット演算子であり、必要な部分のみを評価します。

例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


このコードではビット演算子が使用されているため、両方のブール条件が評価されます。

  • 인수!= ゼロ
  • 引数。長さ () > 23

このようにすると、引数がnullの場合に私のコードがNullPointerExceptionを発生させます。両方のブール条件を評価する必要があるため、引数がnullの場合でも常にargs.lengthチェックが実行されるからです。


ブール演算子のショート回路評価


&&を使用する場合 例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


その引数を知った瞬間!= nullがfalseと評価されると、条件式の評価は停止します。

右側を評価する必要はありません。

右側の条件の結果が何であれ、ブール式の結果はfalseになります。


しかし、本番コードではこのようなことは絶対に起こりません。


これは非常に簡単に犯す可能性のあるミスであり、静的解析ツールが常に検出できるとは限りません。

次のGoogle Dorkを使用して、このパターンの公開事例が見つかるかどうかを確認しました。

ファイル形式: “! の場合 Java=null &”
この検索により、Androidの一部コードがルートウィンドウコンテナに持ち込まれました。
ISDocument = Intent!= null & Intent.isDocument()


ビット演算子を使用して値をマスキングするケースが多いため、コードレビューを通過できるコードタイプです。ただしこの場合、結果は上記のif文の例と同じです。intentが常にnullの場合、NullPointerExceptionが発生します。

私たちはしばしば防御的な方法でコーディングし、重複コードを書くため、この構文を使用しないことが多いです。`== null` はほとんどのユースケースで重複する可能性があります。

これはプログラマーが本番コードで作成したエラーです。

検索結果がどれほど最新かはわかりませんが、検索を実行した際にGoogle、Amazon、Apache...そして私のコードが含まれた結果が表示されました。

最近、プルリクエスト内のオープンソースプロジェクトの一つで、まさにこのエラーを解決する必要がありました。

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


これを調べる方法


いくつかの静的解析ツールでサンプルコードを確認した際、この隠された自己破壊コードを発見したものは一つもありませんでした。

Secure Code Warriorチームとして、私たちはこの問題を解決できる非常にシンプルなセンセイレシピを作成し、レビューしました。

ビット演算子は完全に有効であり、代入で頻繁に使用されるため、if文の使用事例とビット演算子&を使用した問題のあるコードの発見に焦点を当てました。

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


これは正規表現を使用して条件式として使用される際に「&」と一致します(例:if文内)。

この問題を解決するために、私たちは再び正規表現を使用しました。今回はQuickFixのsed関数を使用して、表現式内の&を&&にグローバルに置換しました。

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


エンドノート

ここではビット演算子の最も一般的な誤用、つまりブール演算子が実際に意図されている場合について説明します。

例えば、入力例のような他の状況が発生する可能性がありますが、レシピを作成する際には偽陽性の識別を避ける必要があります。そうしないと、レシピが無視されたり無効化されたりします。私たちは最も頻繁に発生する状況に適合するレシピを作成します。Senseiが進化するにつれ、より多くの条件を網羅するために検索機能に特定の機能を追加する予定です。

現在の形態で見ると、このレシピは多くの実際の使用事例を特定できます。最も重要なのは、私のプロジェクトで報告された内容です。

注記: チャーリー・エリクセン、マティユ・カリ、ロビン・クレアハウト、ブライソン・アクス、ネイサン・デスメット、ダウニー・ロバーズショーテンなどのコード戦士たちがこの例とレシピのレビューに貢献しました。ご協力ありがとうございました。


---


IntelliJ内で「環境設定\プラグイン」(Mac)または「設定\プラグイン」(Windows)を使用してSenseiをインストールした後、「センセイ セキュリティコード」を検索するだけです。

Secure Code Warrior `sensei`リポジトリには、これらのブログ記事(この記事を含む)に関する多くのソースコードとレシピがあります。

https://github.com/securecodewarrior/sensei-blog-examples

先生についてもっと知る


ウェビナーを見る
はじめに
もっと詳しく

以下のリンクをクリックし、このリソースのPDFをダウンロードしてください。

セキュアコードウォリアーは、ソフトウェア開発ライフサイクル全体を通じてコードを保護し、サイバーセキュリティを最優先とする文化を組織に根付かせるために存在します。AppSec管理者、開発者、CISO、あるいはセキュリティに関わるあらゆる立場の方々に対し、組織が安全でないコードに関連するリスクを軽減できるよう支援します。

レポートを見るデモ予約
リソースを見る
共有対象:
リンクトインのブランドソーシャルx ロゴ
もっと興味がありますか?

共有対象:
リンクトインのブランドソーシャルx ロゴ
作成者
アラン・リチャードソン
2021年02月07日掲載

アラン・リチャードソンは、20年以上にわたり、開発者として、またテスターからテスト責任者まで、あらゆるレベルのテストに携わってきたプロフェッショナルなIT経験を持っています。アラン・リチャードソンは、Secure Code Warrior のデベロッパーリレーションズの責任者として、チームと直接連携し、高品質で安全なコードの開発を促進しています。また、「Dear Evil Tester」や「Java For Testers」など4冊の著書があります。また、テクニカルWebテストやSelenium WebDriver with Javaを学ぶためのオンライントレーニングcourses を作成しています。アランは、SeleniumSimplified.com、EvilTester.com、JavaForTesters.com、CompendiumDev.co.ukに執筆やトレーニングビデオを掲載している。

共有対象:
リンクトインのブランドソーシャルx ロゴ

Java問題 - ビット単位演算子とブール演算子

「Java Gotcha」 - 誤って実装しやすい一般的なミスパターンです。

Javaでうっかり陥りやすい非常に単純な問題の一つは、ブール比較演算子の代わりにビット単位演算子を使用してしまうことです。

例えば、本当に「&&」を使おうとしたときに、単純な入力ミスによって「&」を使う可能性があります。

コードをレビューする際に一般的に学ぶヒューリスティックは以下の通りです。

「&」または「|」を条件式で使用することは意図されたものではない可能性があります。

このブログ記事では、ヒューリスティックを検討し、このコーディング問題を特定して解決する方法を探ります。


何が問題なんだ?ビット単位の演算はブール値で正常に動作します。


ブール値と共にビット演算子を使用することは完全に有効であるため、Javaは構文エラーを報告しません。

ビット単位の論理和(|)とビット単位の論理積(&)の両方について真理値表を探索するためにJUnitテストを構成すると、ビット演算子の出力が真理値表と一致していることが確認できます。こうした点を考慮すると、ビット演算子を使用することに問題はないと考えられるかもしれません。

AND 真値表

aで3列、bで1列、最後に(a^b)で1列。


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


テストを通過しました。これは完全に有効なJavaです。


OR 真値表


aで3列、bで1列、最後に(a v b)で1列。


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


このテストも通過したのに、なぜ「&&」と「||」を好むのでしょうか?


真理値表の画像は以下を使用して生成されました。 真実値表ツール ...から web.standfor.edu.


問題:段落動作


本当の問題はビット演算子(&, |)とブール演算子(&&, ||)の動作の違いです。

ブール演算子はショートカット演算子であり、必要な部分のみを評価します。

例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


このコードではビット演算子が使用されているため、両方のブール条件が評価されます。

  • 인수!= ゼロ
  • 引数。長さ () > 23

このようにすると、引数がnullの場合に私のコードがNullPointerExceptionを発生させます。両方のブール条件を評価する必要があるため、引数がnullの場合でも常にargs.lengthチェックが実行されるからです。


ブール演算子のショート回路評価


&&を使用する場合 例:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


その引数を知った瞬間!= nullがfalseと評価されると、条件式の評価は停止します。

右側を評価する必要はありません。

右側の条件の結果が何であれ、ブール式の結果はfalseになります。


しかし、本番コードではこのようなことは絶対に起こりません。


これは非常に簡単に犯す可能性のあるミスであり、静的解析ツールが常に検出できるとは限りません。

次のGoogle Dorkを使用して、このパターンの公開事例が見つかるかどうかを確認しました。

ファイル形式: “! の場合 Java=null &”
この検索により、Androidの一部コードがルートウィンドウコンテナに持ち込まれました。
ISDocument = Intent!= null & Intent.isDocument()


ビット演算子を使用して値をマスキングするケースが多いため、コードレビューを通過できるコードタイプです。ただしこの場合、結果は上記のif文の例と同じです。intentが常にnullの場合、NullPointerExceptionが発生します。

私たちはしばしば防御的な方法でコーディングし、重複コードを書くため、この構文を使用しないことが多いです。`== null` はほとんどのユースケースで重複する可能性があります。

これはプログラマーが本番コードで作成したエラーです。

検索結果がどれほど最新かはわかりませんが、検索を実行した際にGoogle、Amazon、Apache...そして私のコードが含まれた結果が表示されました。

最近、プルリクエスト内のオープンソースプロジェクトの一つで、まさにこのエラーを解決する必要がありました。

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


これを調べる方法


いくつかの静的解析ツールでサンプルコードを確認した際、この隠された自己破壊コードを発見したものは一つもありませんでした。

Secure Code Warriorチームとして、私たちはこの問題を解決できる非常にシンプルなセンセイレシピを作成し、レビューしました。

ビット演算子は完全に有効であり、代入で頻繁に使用されるため、if文の使用事例とビット演算子&を使用した問題のあるコードの発見に焦点を当てました。

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


これは正規表現を使用して条件式として使用される際に「&」と一致します(例:if文内)。

この問題を解決するために、私たちは再び正規表現を使用しました。今回はQuickFixのsed関数を使用して、表現式内の&を&&にグローバルに置換しました。

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


エンドノート

ここではビット演算子の最も一般的な誤用、つまりブール演算子が実際に意図されている場合について説明します。

例えば、入力例のような他の状況が発生する可能性がありますが、レシピを作成する際には偽陽性の識別を避ける必要があります。そうしないと、レシピが無視されたり無効化されたりします。私たちは最も頻繁に発生する状況に適合するレシピを作成します。Senseiが進化するにつれ、より多くの条件を網羅するために検索機能に特定の機能を追加する予定です。

現在の形態で見ると、このレシピは多くの実際の使用事例を特定できます。最も重要なのは、私のプロジェクトで報告された内容です。

注記: チャーリー・エリクセン、マティユ・カリ、ロビン・クレアハウト、ブライソン・アクス、ネイサン・デスメット、ダウニー・ロバーズショーテンなどのコード戦士たちがこの例とレシピのレビューに貢献しました。ご協力ありがとうございました。


---


IntelliJ内で「環境設定\プラグイン」(Mac)または「設定\プラグイン」(Windows)を使用してSenseiをインストールした後、「センセイ セキュリティコード」を検索するだけです。

Secure Code Warrior `sensei`リポジトリには、これらのブログ記事(この記事を含む)に関する多くのソースコードとレシピがあります。

https://github.com/securecodewarrior/sensei-blog-examples

先生についてもっと知る


目次

PDFダウンロード
リソースを見る
もっと興味がありますか?

アラン・リチャードソンは、20年以上にわたり、開発者として、またテスターからテスト責任者まで、あらゆるレベルのテストに携わってきたプロフェッショナルなIT経験を持っています。アラン・リチャードソンは、Secure Code Warrior のデベロッパーリレーションズの責任者として、チームと直接連携し、高品質で安全なコードの開発を促進しています。また、「Dear Evil Tester」や「Java For Testers」など4冊の著書があります。また、テクニカルWebテストやSelenium WebDriver with Javaを学ぶためのオンライントレーニングcourses を作成しています。アランは、SeleniumSimplified.com、EvilTester.com、JavaForTesters.com、CompendiumDev.co.ukに執筆やトレーニングビデオを掲載している。

もっと詳しく

セキュアコードウォリアーは、ソフトウェア開発ライフサイクル全体を通じてコードを保護し、サイバーセキュリティを最優先とする文化を組織に根付かせるために存在します。AppSec管理者、開発者、CISO、あるいはセキュリティに関わるあらゆる立場の方々に対し、組織が安全でないコードに関連するリスクを軽減できるよう支援します。

デモ予約ダウンロード
共有対象:
リンクトインのブランドソーシャルx ロゴ
リソースハブ

始めるのに役立つリソース

もっと多くの投稿
リソースハブ

始めるのに役立つリソース

もっと多くの投稿