Java Gotchas - Bitweise vs. Boolesche Operatoren
Java Gotchas - Bitweise vs. Boolesche Operatoren
> "Java Gotcha" - ein häufiges Fehlermuster, das sich leicht versehentlich implementieren lässt.
Ein recht einfaches Java-Gotcha, in das man versehentlich hineinfallen kann, ist: die Verwendung eines Bitwise-Operators anstelle eines booleschen Vergleichsoperators.
z. B. kann ein einfacher Tippfehler dazu führen, dass Sie "&" schreiben, obwohl Sie eigentlich "&&" schreiben wollten.
Eine gängige Heuristik, die wir beim Überprüfen von Code lernen, ist:
> "&" oder "|" bei Verwendung in einer bedingten Anweisung ist wahrscheinlich nicht beabsichtigt.
In diesem Blog-Beitrag werden wir die Heuristik untersuchen und Wege aufzeigen, wie wir dieses Kodierungsproblem identifizieren und beheben können.
Wo liegt das Problem? Bitweise Operationen funktionieren gut mit Booleans
Die Verwendung von Bitwise-Operatoren mit Booleschen Operatoren ist durchaus zulässig, so dass Java keinen Syntaxfehler meldet.
Wenn ich einen JUnit-Test konstruiere, um eine Wahrheitstabelle sowohl für Bitweises ODER (|) als auch Bitweises UND (&) zu untersuchen, dann werden wir sehen, dass die Ausgaben des Bitweisen Operators mit der Wahrheitstabelle übereinstimmen. Angesichts dessen könnte man meinen, dass die Verwendung von Bitwise-Operatoren kein Problem darstellt.
AND-Wahrheitstabelle
@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Der Test ist bestanden, dies ist vollkommen gültiges Java.
OR-Wahrheitstabelle
@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Auch dieser Test besteht, warum bevorzugen wir "&&'und "||'?
Wahrheitstabellenbilder wurden mit dem Wahrheitstabellen-Werkzeug von web.standfor.edu.
Problem: Kurzschlussbetrieb
Das eigentliche Problem ist der Unterschied im Verhalten zwischen bitweisen (&, |) und booleschen (&&, ||) Operatoren.
Ein boolescher Operator ist ein Kurzschlussoperator und wertet nur so viel aus, wie er muss.
z.B.
if (args != null & args.length() > 23) {
System.out.println(args);
}
Im obigen Code werden beide booleschen Bedingungen ausgewertet, da der Bitwise-Operator verwendet wurde:
- args != null
- args.length() > 23
Das lässt meinen Code offen für eine NullPointerException, wenn args null ist, weil wir immer die Prüfung für args.length durchführen, auch wenn args null ist, weil beide booleschen Bedingungen ausgewertet werden müssen.
Boolesche Operatoren Kurzschlussauswertung
Wenn ein && verwendet wird, z. B.
if (args != null && args.length() > 23) {
System.out.println(args);
}
Sobald wir wissen, dass args != null zu false ausgewertet wird, stoppt die Auswertung des Bedingungsausdrucks.
Die rechte Seite brauchen wir nicht auszuwerten.
Unabhängig vom Ergebnis der Bedingung auf der rechten Seite ist der Endwert des booleschen Ausdrucks falsch.
Aber das würde im Produktionscode nie passieren
Dies ist ein ziemlich leicht zu begehender Fehler, der nicht immer von statischen Analysetools erkannt wird.
Ich habe den folgenden Google Dork verwendet, um zu sehen, ob ich irgendwelche öffentlichen Beispiele für dieses Muster finden kann:
filetype:java if "!=null & "
Diese Suche brachte etwas Code von Android im RootWindowContainer
isDocument = intent != null & intent.isDocument()
Dies ist die Art von Code, die eine Codeprüfung bestehen könnte, weil wir oft Bitwise-Operatoren in Zuweisungsanweisungen verwenden, um Werte zu maskieren. Aber in diesem Fall ist das Ergebnis das gleiche wie im obigen Beispiel der if-Anweisung. Wenn intent jemals null ist, dann wird eine NullPointerException geworfen.
Sehr oft kommen wir mit diesem Konstrukt davon, weil wir oft defensiv codieren und redundanten Code schreiben. Die Prüfung auf != null mag in den meisten Anwendungsfällen durchaus redundant sein.
Dies ist ein Fehler, der von Programmierern im Produktionscode gemacht wird.
Ich weiß nicht, wie aktuell die Ergebnisse für die Suche sind, aber als ich die Suche ausgeführt habe, gab es Ergebnisse zurück mit Code von: Google, Amazon, Apache... und mir.
Eine kürzliche Pull-Anfrage in einem meiner Open-Source-Projekte sollte genau diesen Fehler beheben.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Wie Sie das finden
Als ich meinen Beispielcode in ein paar statischen Analysatoren überprüft habe, hat keiner von ihnen diesen versteckten Selbstzerstörungscode gefunden.
Als Team auf Secure Code Warrior haben wir ein recht einfaches Sensei Rezept erstellt und überprüft, das dies auffangen kann.
Da Bitwise-Operatoren durchaus zulässig sind und häufig in Zuweisungen verwendet werden, haben wir uns auf den Anwendungsfall von if-Anweisungen und die Verwendung von Bitwise & konzentriert, um den problematischen Code zu finden.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Hier wird ein regulärer Ausdruck verwendet, um mit " & " übereinzustimmen, wenn er als Bedingungsausdruck verwendet wird. z. B. in einer if-Anweisung.
Um das zu beheben, haben wir wieder auf reguläre Ausdrücke zurückgegriffen. Diesmal mit der sed-Funktion im QuickFix, um das & im Ausdruck global durch && zu ersetzen.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Ende Anmerkungen
Dies deckt den häufigsten Missbrauch eines Bitwise-Operators ab, d. h. wenn eigentlich ein boolescher Operator beabsichtigt war.
Es gibt andere Situationen, in denen dies auftreten könnte, z. B. das Zuordnungsbeispiel, aber beim Schreiben von Rezepten müssen wir versuchen, eine falsch-positive Identifizierung zu vermeiden, sonst werden Rezepte ignoriert oder ausgeschaltet. Wir erstellen Rezepte, die den häufigsten Vorkommnissen entsprechen. Wenn sich Sensei weiterentwickelt, werden wir möglicherweise zusätzliche Spezifität in die Suchfunktion einbauen, um mehr passende Bedingungen abzudecken.
In seiner aktuellen Form würde dieses Rezept viele der Live-Anwendungsfälle identifizieren, und vor allem den, der in meinem Projekt berichtet wurde.
HINWEIS: Eine ganze Reihe von Code-Kriegern hat zu diesem Beispiel und der Rezeptüberprüfung beigetragen - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Vielen Dank für Ihre Hilfe.
---
Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Wir haben eine Menge Quellcode und Rezepte für diese Blog-Beiträge (einschließlich dieses Beitrags) im `sensei-blog-examples`-Repository im Secure Code Warrior GitHub-Konto.
https://github.com/securecodewarrior/sensei-blog-examples
In diesem Blogbeitrag werfen wir einen Blick auf einen häufigen Java-Codierungsfehler (die Verwendung eines bitweisen Operators anstelle eines bedingten Operators), den Fehler, für den unser Code dadurch anfällig ist, und wie wir Sensei verwenden können, um das Problem zu beheben und zu erkennen.
Alan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.
Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.
Demo buchenAlan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.
Java Gotchas - Bitweise vs. Boolesche Operatoren
> "Java Gotcha" - ein häufiges Fehlermuster, das sich leicht versehentlich implementieren lässt.
Ein recht einfaches Java-Gotcha, in das man versehentlich hineinfallen kann, ist: die Verwendung eines Bitwise-Operators anstelle eines booleschen Vergleichsoperators.
z. B. kann ein einfacher Tippfehler dazu führen, dass Sie "&" schreiben, obwohl Sie eigentlich "&&" schreiben wollten.
Eine gängige Heuristik, die wir beim Überprüfen von Code lernen, ist:
> "&" oder "|" bei Verwendung in einer bedingten Anweisung ist wahrscheinlich nicht beabsichtigt.
In diesem Blog-Beitrag werden wir die Heuristik untersuchen und Wege aufzeigen, wie wir dieses Kodierungsproblem identifizieren und beheben können.
Wo liegt das Problem? Bitweise Operationen funktionieren gut mit Booleans
Die Verwendung von Bitwise-Operatoren mit Booleschen Operatoren ist durchaus zulässig, so dass Java keinen Syntaxfehler meldet.
Wenn ich einen JUnit-Test konstruiere, um eine Wahrheitstabelle sowohl für Bitweises ODER (|) als auch Bitweises UND (&) zu untersuchen, dann werden wir sehen, dass die Ausgaben des Bitweisen Operators mit der Wahrheitstabelle übereinstimmen. Angesichts dessen könnte man meinen, dass die Verwendung von Bitwise-Operatoren kein Problem darstellt.
AND-Wahrheitstabelle
@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Der Test ist bestanden, dies ist vollkommen gültiges Java.
OR-Wahrheitstabelle
@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Auch dieser Test besteht, warum bevorzugen wir "&&'und "||'?
Wahrheitstabellenbilder wurden mit dem Wahrheitstabellen-Werkzeug von web.standfor.edu.
Problem: Kurzschlussbetrieb
Das eigentliche Problem ist der Unterschied im Verhalten zwischen bitweisen (&, |) und booleschen (&&, ||) Operatoren.
Ein boolescher Operator ist ein Kurzschlussoperator und wertet nur so viel aus, wie er muss.
z.B.
if (args != null & args.length() > 23) {
System.out.println(args);
}
Im obigen Code werden beide booleschen Bedingungen ausgewertet, da der Bitwise-Operator verwendet wurde:
- args != null
- args.length() > 23
Das lässt meinen Code offen für eine NullPointerException, wenn args null ist, weil wir immer die Prüfung für args.length durchführen, auch wenn args null ist, weil beide booleschen Bedingungen ausgewertet werden müssen.
Boolesche Operatoren Kurzschlussauswertung
Wenn ein && verwendet wird, z. B.
if (args != null && args.length() > 23) {
System.out.println(args);
}
Sobald wir wissen, dass args != null zu false ausgewertet wird, stoppt die Auswertung des Bedingungsausdrucks.
Die rechte Seite brauchen wir nicht auszuwerten.
Unabhängig vom Ergebnis der Bedingung auf der rechten Seite ist der Endwert des booleschen Ausdrucks falsch.
Aber das würde im Produktionscode nie passieren
Dies ist ein ziemlich leicht zu begehender Fehler, der nicht immer von statischen Analysetools erkannt wird.
Ich habe den folgenden Google Dork verwendet, um zu sehen, ob ich irgendwelche öffentlichen Beispiele für dieses Muster finden kann:
filetype:java if "!=null & "
Diese Suche brachte etwas Code von Android im RootWindowContainer
isDocument = intent != null & intent.isDocument()
Dies ist die Art von Code, die eine Codeprüfung bestehen könnte, weil wir oft Bitwise-Operatoren in Zuweisungsanweisungen verwenden, um Werte zu maskieren. Aber in diesem Fall ist das Ergebnis das gleiche wie im obigen Beispiel der if-Anweisung. Wenn intent jemals null ist, dann wird eine NullPointerException geworfen.
Sehr oft kommen wir mit diesem Konstrukt davon, weil wir oft defensiv codieren und redundanten Code schreiben. Die Prüfung auf != null mag in den meisten Anwendungsfällen durchaus redundant sein.
Dies ist ein Fehler, der von Programmierern im Produktionscode gemacht wird.
Ich weiß nicht, wie aktuell die Ergebnisse für die Suche sind, aber als ich die Suche ausgeführt habe, gab es Ergebnisse zurück mit Code von: Google, Amazon, Apache... und mir.
Eine kürzliche Pull-Anfrage in einem meiner Open-Source-Projekte sollte genau diesen Fehler beheben.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Wie Sie das finden
Als ich meinen Beispielcode in ein paar statischen Analysatoren überprüft habe, hat keiner von ihnen diesen versteckten Selbstzerstörungscode gefunden.
Als Team auf Secure Code Warrior haben wir ein recht einfaches Sensei Rezept erstellt und überprüft, das dies auffangen kann.
Da Bitwise-Operatoren durchaus zulässig sind und häufig in Zuweisungen verwendet werden, haben wir uns auf den Anwendungsfall von if-Anweisungen und die Verwendung von Bitwise & konzentriert, um den problematischen Code zu finden.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Hier wird ein regulärer Ausdruck verwendet, um mit " & " übereinzustimmen, wenn er als Bedingungsausdruck verwendet wird. z. B. in einer if-Anweisung.
Um das zu beheben, haben wir wieder auf reguläre Ausdrücke zurückgegriffen. Diesmal mit der sed-Funktion im QuickFix, um das & im Ausdruck global durch && zu ersetzen.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Ende Anmerkungen
Dies deckt den häufigsten Missbrauch eines Bitwise-Operators ab, d. h. wenn eigentlich ein boolescher Operator beabsichtigt war.
Es gibt andere Situationen, in denen dies auftreten könnte, z. B. das Zuordnungsbeispiel, aber beim Schreiben von Rezepten müssen wir versuchen, eine falsch-positive Identifizierung zu vermeiden, sonst werden Rezepte ignoriert oder ausgeschaltet. Wir erstellen Rezepte, die den häufigsten Vorkommnissen entsprechen. Wenn sich Sensei weiterentwickelt, werden wir möglicherweise zusätzliche Spezifität in die Suchfunktion einbauen, um mehr passende Bedingungen abzudecken.
In seiner aktuellen Form würde dieses Rezept viele der Live-Anwendungsfälle identifizieren, und vor allem den, der in meinem Projekt berichtet wurde.
HINWEIS: Eine ganze Reihe von Code-Kriegern hat zu diesem Beispiel und der Rezeptüberprüfung beigetragen - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Vielen Dank für Ihre Hilfe.
---
Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Wir haben eine Menge Quellcode und Rezepte für diese Blog-Beiträge (einschließlich dieses Beitrags) im `sensei-blog-examples`-Repository im Secure Code Warrior GitHub-Konto.
https://github.com/securecodewarrior/sensei-blog-examples
Java Gotchas - Bitweise vs. Boolesche Operatoren
> "Java Gotcha" - ein häufiges Fehlermuster, das sich leicht versehentlich implementieren lässt.
Ein recht einfaches Java-Gotcha, in das man versehentlich hineinfallen kann, ist: die Verwendung eines Bitwise-Operators anstelle eines booleschen Vergleichsoperators.
z. B. kann ein einfacher Tippfehler dazu führen, dass Sie "&" schreiben, obwohl Sie eigentlich "&&" schreiben wollten.
Eine gängige Heuristik, die wir beim Überprüfen von Code lernen, ist:
> "&" oder "|" bei Verwendung in einer bedingten Anweisung ist wahrscheinlich nicht beabsichtigt.
In diesem Blog-Beitrag werden wir die Heuristik untersuchen und Wege aufzeigen, wie wir dieses Kodierungsproblem identifizieren und beheben können.
Wo liegt das Problem? Bitweise Operationen funktionieren gut mit Booleans
Die Verwendung von Bitwise-Operatoren mit Booleschen Operatoren ist durchaus zulässig, so dass Java keinen Syntaxfehler meldet.
Wenn ich einen JUnit-Test konstruiere, um eine Wahrheitstabelle sowohl für Bitweises ODER (|) als auch Bitweises UND (&) zu untersuchen, dann werden wir sehen, dass die Ausgaben des Bitweisen Operators mit der Wahrheitstabelle übereinstimmen. Angesichts dessen könnte man meinen, dass die Verwendung von Bitwise-Operatoren kein Problem darstellt.
AND-Wahrheitstabelle
@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Der Test ist bestanden, dies ist vollkommen gültiges Java.
OR-Wahrheitstabelle
@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Auch dieser Test besteht, warum bevorzugen wir "&&'und "||'?
Wahrheitstabellenbilder wurden mit dem Wahrheitstabellen-Werkzeug von web.standfor.edu.
Problem: Kurzschlussbetrieb
Das eigentliche Problem ist der Unterschied im Verhalten zwischen bitweisen (&, |) und booleschen (&&, ||) Operatoren.
Ein boolescher Operator ist ein Kurzschlussoperator und wertet nur so viel aus, wie er muss.
z.B.
if (args != null & args.length() > 23) {
System.out.println(args);
}
Im obigen Code werden beide booleschen Bedingungen ausgewertet, da der Bitwise-Operator verwendet wurde:
- args != null
- args.length() > 23
Das lässt meinen Code offen für eine NullPointerException, wenn args null ist, weil wir immer die Prüfung für args.length durchführen, auch wenn args null ist, weil beide booleschen Bedingungen ausgewertet werden müssen.
Boolesche Operatoren Kurzschlussauswertung
Wenn ein && verwendet wird, z. B.
if (args != null && args.length() > 23) {
System.out.println(args);
}
Sobald wir wissen, dass args != null zu false ausgewertet wird, stoppt die Auswertung des Bedingungsausdrucks.
Die rechte Seite brauchen wir nicht auszuwerten.
Unabhängig vom Ergebnis der Bedingung auf der rechten Seite ist der Endwert des booleschen Ausdrucks falsch.
Aber das würde im Produktionscode nie passieren
Dies ist ein ziemlich leicht zu begehender Fehler, der nicht immer von statischen Analysetools erkannt wird.
Ich habe den folgenden Google Dork verwendet, um zu sehen, ob ich irgendwelche öffentlichen Beispiele für dieses Muster finden kann:
filetype:java if "!=null & "
Diese Suche brachte etwas Code von Android im RootWindowContainer
isDocument = intent != null & intent.isDocument()
Dies ist die Art von Code, die eine Codeprüfung bestehen könnte, weil wir oft Bitwise-Operatoren in Zuweisungsanweisungen verwenden, um Werte zu maskieren. Aber in diesem Fall ist das Ergebnis das gleiche wie im obigen Beispiel der if-Anweisung. Wenn intent jemals null ist, dann wird eine NullPointerException geworfen.
Sehr oft kommen wir mit diesem Konstrukt davon, weil wir oft defensiv codieren und redundanten Code schreiben. Die Prüfung auf != null mag in den meisten Anwendungsfällen durchaus redundant sein.
Dies ist ein Fehler, der von Programmierern im Produktionscode gemacht wird.
Ich weiß nicht, wie aktuell die Ergebnisse für die Suche sind, aber als ich die Suche ausgeführt habe, gab es Ergebnisse zurück mit Code von: Google, Amazon, Apache... und mir.
Eine kürzliche Pull-Anfrage in einem meiner Open-Source-Projekte sollte genau diesen Fehler beheben.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Wie Sie das finden
Als ich meinen Beispielcode in ein paar statischen Analysatoren überprüft habe, hat keiner von ihnen diesen versteckten Selbstzerstörungscode gefunden.
Als Team auf Secure Code Warrior haben wir ein recht einfaches Sensei Rezept erstellt und überprüft, das dies auffangen kann.
Da Bitwise-Operatoren durchaus zulässig sind und häufig in Zuweisungen verwendet werden, haben wir uns auf den Anwendungsfall von if-Anweisungen und die Verwendung von Bitwise & konzentriert, um den problematischen Code zu finden.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Hier wird ein regulärer Ausdruck verwendet, um mit " & " übereinzustimmen, wenn er als Bedingungsausdruck verwendet wird. z. B. in einer if-Anweisung.
Um das zu beheben, haben wir wieder auf reguläre Ausdrücke zurückgegriffen. Diesmal mit der sed-Funktion im QuickFix, um das & im Ausdruck global durch && zu ersetzen.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Ende Anmerkungen
Dies deckt den häufigsten Missbrauch eines Bitwise-Operators ab, d. h. wenn eigentlich ein boolescher Operator beabsichtigt war.
Es gibt andere Situationen, in denen dies auftreten könnte, z. B. das Zuordnungsbeispiel, aber beim Schreiben von Rezepten müssen wir versuchen, eine falsch-positive Identifizierung zu vermeiden, sonst werden Rezepte ignoriert oder ausgeschaltet. Wir erstellen Rezepte, die den häufigsten Vorkommnissen entsprechen. Wenn sich Sensei weiterentwickelt, werden wir möglicherweise zusätzliche Spezifität in die Suchfunktion einbauen, um mehr passende Bedingungen abzudecken.
In seiner aktuellen Form würde dieses Rezept viele der Live-Anwendungsfälle identifizieren, und vor allem den, der in meinem Projekt berichtet wurde.
HINWEIS: Eine ganze Reihe von Code-Kriegern hat zu diesem Beispiel und der Rezeptüberprüfung beigetragen - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Vielen Dank für Ihre Hilfe.
---
Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Wir haben eine Menge Quellcode und Rezepte für diese Blog-Beiträge (einschließlich dieses Beitrags) im `sensei-blog-examples`-Repository im Secure Code Warrior GitHub-Konto.
https://github.com/securecodewarrior/sensei-blog-examples
Klicken Sie auf den unten stehenden Link und laden Sie die PDF-Datei dieser Ressource herunter.
Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.
Bericht ansehenDemo buchenAlan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.
Java Gotchas - Bitweise vs. Boolesche Operatoren
> "Java Gotcha" - ein häufiges Fehlermuster, das sich leicht versehentlich implementieren lässt.
Ein recht einfaches Java-Gotcha, in das man versehentlich hineinfallen kann, ist: die Verwendung eines Bitwise-Operators anstelle eines booleschen Vergleichsoperators.
z. B. kann ein einfacher Tippfehler dazu führen, dass Sie "&" schreiben, obwohl Sie eigentlich "&&" schreiben wollten.
Eine gängige Heuristik, die wir beim Überprüfen von Code lernen, ist:
> "&" oder "|" bei Verwendung in einer bedingten Anweisung ist wahrscheinlich nicht beabsichtigt.
In diesem Blog-Beitrag werden wir die Heuristik untersuchen und Wege aufzeigen, wie wir dieses Kodierungsproblem identifizieren und beheben können.
Wo liegt das Problem? Bitweise Operationen funktionieren gut mit Booleans
Die Verwendung von Bitwise-Operatoren mit Booleschen Operatoren ist durchaus zulässig, so dass Java keinen Syntaxfehler meldet.
Wenn ich einen JUnit-Test konstruiere, um eine Wahrheitstabelle sowohl für Bitweises ODER (|) als auch Bitweises UND (&) zu untersuchen, dann werden wir sehen, dass die Ausgaben des Bitweisen Operators mit der Wahrheitstabelle übereinstimmen. Angesichts dessen könnte man meinen, dass die Verwendung von Bitwise-Operatoren kein Problem darstellt.
AND-Wahrheitstabelle
@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Der Test ist bestanden, dies ist vollkommen gültiges Java.
OR-Wahrheitstabelle
@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Auch dieser Test besteht, warum bevorzugen wir "&&'und "||'?
Wahrheitstabellenbilder wurden mit dem Wahrheitstabellen-Werkzeug von web.standfor.edu.
Problem: Kurzschlussbetrieb
Das eigentliche Problem ist der Unterschied im Verhalten zwischen bitweisen (&, |) und booleschen (&&, ||) Operatoren.
Ein boolescher Operator ist ein Kurzschlussoperator und wertet nur so viel aus, wie er muss.
z.B.
if (args != null & args.length() > 23) {
System.out.println(args);
}
Im obigen Code werden beide booleschen Bedingungen ausgewertet, da der Bitwise-Operator verwendet wurde:
- args != null
- args.length() > 23
Das lässt meinen Code offen für eine NullPointerException, wenn args null ist, weil wir immer die Prüfung für args.length durchführen, auch wenn args null ist, weil beide booleschen Bedingungen ausgewertet werden müssen.
Boolesche Operatoren Kurzschlussauswertung
Wenn ein && verwendet wird, z. B.
if (args != null && args.length() > 23) {
System.out.println(args);
}
Sobald wir wissen, dass args != null zu false ausgewertet wird, stoppt die Auswertung des Bedingungsausdrucks.
Die rechte Seite brauchen wir nicht auszuwerten.
Unabhängig vom Ergebnis der Bedingung auf der rechten Seite ist der Endwert des booleschen Ausdrucks falsch.
Aber das würde im Produktionscode nie passieren
Dies ist ein ziemlich leicht zu begehender Fehler, der nicht immer von statischen Analysetools erkannt wird.
Ich habe den folgenden Google Dork verwendet, um zu sehen, ob ich irgendwelche öffentlichen Beispiele für dieses Muster finden kann:
filetype:java if "!=null & "
Diese Suche brachte etwas Code von Android im RootWindowContainer
isDocument = intent != null & intent.isDocument()
Dies ist die Art von Code, die eine Codeprüfung bestehen könnte, weil wir oft Bitwise-Operatoren in Zuweisungsanweisungen verwenden, um Werte zu maskieren. Aber in diesem Fall ist das Ergebnis das gleiche wie im obigen Beispiel der if-Anweisung. Wenn intent jemals null ist, dann wird eine NullPointerException geworfen.
Sehr oft kommen wir mit diesem Konstrukt davon, weil wir oft defensiv codieren und redundanten Code schreiben. Die Prüfung auf != null mag in den meisten Anwendungsfällen durchaus redundant sein.
Dies ist ein Fehler, der von Programmierern im Produktionscode gemacht wird.
Ich weiß nicht, wie aktuell die Ergebnisse für die Suche sind, aber als ich die Suche ausgeführt habe, gab es Ergebnisse zurück mit Code von: Google, Amazon, Apache... und mir.
Eine kürzliche Pull-Anfrage in einem meiner Open-Source-Projekte sollte genau diesen Fehler beheben.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Wie Sie das finden
Als ich meinen Beispielcode in ein paar statischen Analysatoren überprüft habe, hat keiner von ihnen diesen versteckten Selbstzerstörungscode gefunden.
Als Team auf Secure Code Warrior haben wir ein recht einfaches Sensei Rezept erstellt und überprüft, das dies auffangen kann.
Da Bitwise-Operatoren durchaus zulässig sind und häufig in Zuweisungen verwendet werden, haben wir uns auf den Anwendungsfall von if-Anweisungen und die Verwendung von Bitwise & konzentriert, um den problematischen Code zu finden.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Hier wird ein regulärer Ausdruck verwendet, um mit " & " übereinzustimmen, wenn er als Bedingungsausdruck verwendet wird. z. B. in einer if-Anweisung.
Um das zu beheben, haben wir wieder auf reguläre Ausdrücke zurückgegriffen. Diesmal mit der sed-Funktion im QuickFix, um das & im Ausdruck global durch && zu ersetzen.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Ende Anmerkungen
Dies deckt den häufigsten Missbrauch eines Bitwise-Operators ab, d. h. wenn eigentlich ein boolescher Operator beabsichtigt war.
Es gibt andere Situationen, in denen dies auftreten könnte, z. B. das Zuordnungsbeispiel, aber beim Schreiben von Rezepten müssen wir versuchen, eine falsch-positive Identifizierung zu vermeiden, sonst werden Rezepte ignoriert oder ausgeschaltet. Wir erstellen Rezepte, die den häufigsten Vorkommnissen entsprechen. Wenn sich Sensei weiterentwickelt, werden wir möglicherweise zusätzliche Spezifität in die Suchfunktion einbauen, um mehr passende Bedingungen abzudecken.
In seiner aktuellen Form würde dieses Rezept viele der Live-Anwendungsfälle identifizieren, und vor allem den, der in meinem Projekt berichtet wurde.
HINWEIS: Eine ganze Reihe von Code-Kriegern hat zu diesem Beispiel und der Rezeptüberprüfung beigetragen - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Vielen Dank für Ihre Hilfe.
---
Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.
Wir haben eine Menge Quellcode und Rezepte für diese Blog-Beiträge (einschließlich dieses Beitrags) im `sensei-blog-examples`-Repository im Secure Code Warrior GitHub-Konto.
https://github.com/securecodewarrior/sensei-blog-examples
Inhaltsübersicht
Alan Richardson verfügt über mehr als zwanzig Jahre Berufserfahrung in der IT-Branche. Er arbeitete als Entwickler und auf jeder Ebene der Testhierarchie, vom Tester bis hin zum Head of Testing. Als Head of Developer Relations bei Secure Code Warrior arbeitet er direkt mit Teams zusammen, um die Entwicklung von hochwertigem, sicherem Code zu verbessern. Alan ist der Autor von vier Büchern, darunter "Dear Evil Tester" und "Java For Testers". Alan hat auch Online-Schulungen courses erstellt, um Menschen beim Erlernen von technischen Web-Tests und Selenium WebDriver mit Java zu helfen. Alan veröffentlicht seine Schriften und Schulungsvideos auf SeleniumSimplified.com, EvilTester.com, JavaForTesters.com und CompendiumDev.co.uk.
Secure Code Warrior ist für Ihr Unternehmen da, um Sie dabei zu unterstützen, Ihren Code über den gesamten Lebenszyklus der Softwareentwicklung hinweg zu sichern und eine Kultur zu schaffen, in der Cybersicherheit an erster Stelle steht. Ganz gleich, ob Sie AppSec-Manager, Entwickler, CISO oder ein anderer Sicherheitsverantwortlicher sind, wir können Ihrem Unternehmen helfen, die mit unsicherem Code verbundenen Risiken zu reduzieren.
Demo buchenHerunterladenRessourcen für den Einstieg
Benchmarking von Sicherheitskompetenzen: Optimierung von Secure-by-Design im Unternehmen
Die Secure-by-Design-Bewegung ist die Zukunft der sicheren Softwareentwicklung. Erfahren Sie mehr über die wichtigsten Elemente, die Unternehmen berücksichtigen müssen, wenn sie über eine Secure-by-Design-Initiative nachdenken.
DigitalOcean verringert Sicherheitsverschuldung mit Secure Code Warrior
DigitalOceans Einsatz von Secure Code Warrior hat die Sicherheitsverschuldung deutlich reduziert, so dass sich die Teams stärker auf Innovation und Produktivität konzentrieren können. Die verbesserte Sicherheit hat die Produktqualität und den Wettbewerbsvorteil des Unternehmens gestärkt. Mit Blick auf die Zukunft wird der SCW Trust Score dem Unternehmen helfen, seine Sicherheitspraktiken weiter zu verbessern und Innovationen voranzutreiben.
Ressourcen für den Einstieg
Trust Score zeigt den Wert von Secure-by-Design-Upskilling-Initiativen
Unsere Forschung hat gezeigt, dass Schulungen für sicheren Code funktionieren. Trust Score verwendet einen Algorithmus, der auf mehr als 20 Millionen Lerndaten aus der Arbeit von mehr als 250.000 Lernenden in über 600 Organisationen basiert, und zeigt, wie effektiv die Initiative ist, um Schwachstellen zu beseitigen und wie man sie noch effektiver gestalten kann.
Reaktive versus präventive Sicherheit: Prävention ist das bessere Heilmittel
Der Gedanke, Legacy-Code und -Systeme zur gleichen Zeit wie neuere Anwendungen mit präventiver Sicherheit auszustatten, kann entmutigend erscheinen, aber ein Secure-by-Design-Ansatz, der durch die Weiterbildung von Entwicklern durchgesetzt wird, kann die besten Sicherheitsverfahren auf diese Systeme anwenden. Dies ist für viele Unternehmen die beste Chance, ihre Sicherheitslage zu verbessern.
Die Vorteile eines Benchmarking der Sicherheitskompetenzen von Entwicklern
Der zunehmende Fokus auf sicheren Code und Secure-by-Design-Prinzipien erfordert, dass Entwickler von Beginn des SDLC an in Cybersicherheit geschult werden, wobei Tools wie Secure Code Warrior's Trust Score dabei helfen, ihre Fortschritte zu messen und zu verbessern.
Wesentlicher Erfolg für Enterprise Secure-by-Design-Initiativen
Unser jüngstes Forschungspapier „Benchmarking Security Skills: Streamlining Secure-by-Design in the Enterprise“ ist das Ergebnis einer umfassenden Analyse echter Secure-by-Design-Initiativen auf Unternehmensebene und der Ableitung von Best-Practice-Ansätzen auf Grundlage datengesteuerter Erkenntnisse.