Java Gotchas - Opérateurs booléens et opérateurs bitwise
Java Gotchas - Opérateurs booléens et opérateurs bitwise
> "Java Gotcha" - un modèle d'erreur courant qu'il est facile de mettre en œuvre accidentellement.
Une erreur Java assez simple à commettre accidentellement est l'utilisation d'un opérateur Bitwise au lieu d'un opérateur de comparaison booléen.
Par exemple, une simple erreur de frappe peut conduire à écrire "&" alors que vous vouliez en réalité écrire "&&".
Une heuristique courante que nous apprenons lors de l'examen du code est la suivante :
> Les mots "&" ou "|" utilisés dans une déclaration conditionnelle ne sont probablement pas destinés à être utilisés.
Dans cet article de blog, nous allons explorer l'heuristique et identifier les moyens d'identifier et de corriger ce problème de codage.
Quel est le problème ? Les opérations bitwise fonctionnent bien avec les booléens
L'utilisation des opérateurs Bitwise avec les booléens est parfaitement valide, de sorte que Java ne signale pas d'erreur de syntaxe.
Si je construis un test JUnit pour explorer une table de vérité à la fois pour Bitwise OR (|) et Bitwise AND (&), nous verrons que les sorties de l'opérateur Bitwise correspondent à la table de vérité. Dans ces conditions, nous pourrions penser que l'utilisation des opérateurs bitwise n'est pas un problème.
Table de vérité AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Le test est réussi, il s'agit d'un Java parfaitement valide.
Table de vérité OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Ce test est également réussi, pourquoi préférons-nous "&&" et "||" ?
Les images de la table de vérité ont été créées à l'aide de l'outil outil de table de vérité à partir de web.standfor.edu.
Problème : Fonctionnement en court-circuit
Le vrai problème est la différence de comportement entre les opérateurs binaires (&, |) et booléens (&&, ||).
Un opérateur booléen est un opérateur de court-circuit et n'évalue que ce qui est nécessaire.
par exemple
if (args != null & args.length() > 23) {
System.out.println(args);
}
Dans le code ci-dessus, les deux conditions booléennes seront évaluées, car l'opérateur Bitwise a été utilisé :
- args != null
- args.length() > 23
Cela expose mon code à une NullPointerException si args est nul car nous allons toujours vérifier la longueur de args, même si args est nul car les deux conditions booléennes doivent être évaluées.
Opérateurs booléens Évaluation des courts-circuits
Lorsqu'un && est utilisé, par exemple
if (args != null && args.length() > 23) {
System.out.println(args);
}
Dès que nous savons que l'expression args != null est évaluée à false, l'évaluation de l'expression de la condition s'arrête.
Nous n'avons pas besoin d'évaluer le côté droit.
Quel que soit le résultat de la condition du côté droit, la valeur finale de l'expression booléenne sera fausse.
Mais cela ne se produirait jamais dans un code de production
Il s'agit d'une erreur assez facile à commettre, qui n'est pas toujours détectée par les outils d'analyse statique.
J'ai utilisé le Google Dork suivant pour voir si je pouvais trouver des exemples publics de ce modèle :
filetype:java if "!=null & "
Cette recherche a permis de retrouver du code d'Android dans le RootWindowContainer
isDocument = intent != null & intent.isDocument()
C'est le type de code qui pourrait passer un examen de code parce que nous utilisons souvent les opérateurs Bitwise dans les instructions d'affectation pour masquer les valeurs. Mais dans ce cas, le résultat est le même que dans l'exemple de l'instruction if ci-dessus. Si intent est null, une exception NullPointerException sera levée.
Très souvent, nous nous en sortons avec cette construction parce que nous codons souvent de manière défensive et écrivons du code redondant. La vérification de != null peut être redondante dans la plupart des cas d'utilisation.
Il s'agit d'une erreur commise par les programmeurs dans le code de production.
Je ne sais pas si les résultats de la recherche sont à jour, mais lorsque j'ai lancé la recherche, j'ai obtenu des résultats avec du code provenant de Google, Amazon, Apache... et de moi.
Une récente demande d'extension sur l'un de mes projets open source visait à résoudre exactement cette erreur.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Comment le trouver
Lorsque j'ai vérifié mon exemple de code dans quelques analyseurs statiques, aucun d'entre eux n'a détecté ce code d'autodestruction caché.
L'équipe de Secure Code Warrior a créé et examiné une recette assez simple de Sensei qui pourrait répondre à ce besoin.
Les opérateurs Bitwise étant parfaitement valables et souvent utilisés dans les affectations, nous nous sommes concentrés sur l'utilisation des instructions if et sur l'utilisation de Bitwise &, pour trouver le code problématique.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Cette fonction utilise une expression régulière pour faire correspondre " & " lorsqu'elle est utilisée comme expression de condition, par exemple dans une instruction if.
Pour y remédier, nous nous sommes à nouveau appuyés sur les expressions régulières. Cette fois-ci, nous avons utilisé la fonction sed de QuickFix pour remplacer globalement le & de l'expression par &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notes de fin
Cela couvre l'utilisation abusive la plus courante d'un opérateur bitwise, c'est-à-dire lorsqu'un opérateur booléen était en fait prévu.
Il existe d'autres situations où cela pourrait se produire, par exemple dans l'exemple de l'affectation, mais lorsque nous écrivons des recettes, nous devons essayer d'éviter les identifications faussement positives, faute de quoi les recettes seront ignorées ou désactivées. Nous élaborons des recettes qui correspondent aux occurrences les plus courantes. Au fur et à mesure de l'évolution de Sensei , nous pourrons ajouter des spécificités supplémentaires à la fonctionnalité de recherche afin de couvrir davantage de conditions de correspondance.
Dans sa forme actuelle, cette recette permettrait d'identifier de nombreux cas d'utilisation en direct, et surtout celui qui a été rapporté dans le cadre de mon projet.
NOTE : Quelques guerriers du code ont contribué à cet exemple et à la révision de la recette - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Merci pour votre aide.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Préférences \NPlugins" (Mac) ou "Paramètres \NPlugins" (Windows) puis en recherchant "sensei secure code".
Nous avons beaucoup de code source et de recettes pour ces articles de blog (y compris celui-ci) dans le dépôt `sensei-blog-examples` dans le compte GitHub Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples


Dans cet article de blog, nous examinons une erreur de codage Java courante (l'utilisation d'un opérateur bitwise au lieu d'un opérateur conditionnel), l'erreur qui rend notre code vulnérable et la manière dont nous pouvons utiliser Sensei pour corriger et détecter le problème.
Alan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.
Réservez une démonstrationAlan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.


Java Gotchas - Opérateurs booléens et opérateurs bitwise
> "Java Gotcha" - un modèle d'erreur courant qu'il est facile de mettre en œuvre accidentellement.
Une erreur Java assez simple à commettre accidentellement est l'utilisation d'un opérateur Bitwise au lieu d'un opérateur de comparaison booléen.
Par exemple, une simple erreur de frappe peut conduire à écrire "&" alors que vous vouliez en réalité écrire "&&".
Une heuristique courante que nous apprenons lors de l'examen du code est la suivante :
> Les mots "&" ou "|" utilisés dans une déclaration conditionnelle ne sont probablement pas destinés à être utilisés.
Dans cet article de blog, nous allons explorer l'heuristique et identifier les moyens d'identifier et de corriger ce problème de codage.
Quel est le problème ? Les opérations bitwise fonctionnent bien avec les booléens
L'utilisation des opérateurs Bitwise avec les booléens est parfaitement valide, de sorte que Java ne signale pas d'erreur de syntaxe.
Si je construis un test JUnit pour explorer une table de vérité à la fois pour Bitwise OR (|) et Bitwise AND (&), nous verrons que les sorties de l'opérateur Bitwise correspondent à la table de vérité. Dans ces conditions, nous pourrions penser que l'utilisation des opérateurs bitwise n'est pas un problème.
Table de vérité AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Le test est réussi, il s'agit d'un Java parfaitement valide.
Table de vérité OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Ce test est également réussi, pourquoi préférons-nous "&&" et "||" ?
Les images de la table de vérité ont été créées à l'aide de l'outil outil de table de vérité à partir de web.standfor.edu.
Problème : Fonctionnement en court-circuit
Le vrai problème est la différence de comportement entre les opérateurs binaires (&, |) et booléens (&&, ||).
Un opérateur booléen est un opérateur de court-circuit et n'évalue que ce qui est nécessaire.
par exemple
if (args != null & args.length() > 23) {
System.out.println(args);
}
Dans le code ci-dessus, les deux conditions booléennes seront évaluées, car l'opérateur Bitwise a été utilisé :
- args != null
- args.length() > 23
Cela expose mon code à une NullPointerException si args est nul car nous allons toujours vérifier la longueur de args, même si args est nul car les deux conditions booléennes doivent être évaluées.
Opérateurs booléens Évaluation des courts-circuits
Lorsqu'un && est utilisé, par exemple
if (args != null && args.length() > 23) {
System.out.println(args);
}
Dès que nous savons que l'expression args != null est évaluée à false, l'évaluation de l'expression de la condition s'arrête.
Nous n'avons pas besoin d'évaluer le côté droit.
Quel que soit le résultat de la condition du côté droit, la valeur finale de l'expression booléenne sera fausse.
Mais cela ne se produirait jamais dans un code de production
Il s'agit d'une erreur assez facile à commettre, qui n'est pas toujours détectée par les outils d'analyse statique.
J'ai utilisé le Google Dork suivant pour voir si je pouvais trouver des exemples publics de ce modèle :
filetype:java if "!=null & "
Cette recherche a permis de retrouver du code d'Android dans le RootWindowContainer
isDocument = intent != null & intent.isDocument()
C'est le type de code qui pourrait passer un examen de code parce que nous utilisons souvent les opérateurs Bitwise dans les instructions d'affectation pour masquer les valeurs. Mais dans ce cas, le résultat est le même que dans l'exemple de l'instruction if ci-dessus. Si intent est null, une exception NullPointerException sera levée.
Très souvent, nous nous en sortons avec cette construction parce que nous codons souvent de manière défensive et écrivons du code redondant. La vérification de != null peut être redondante dans la plupart des cas d'utilisation.
Il s'agit d'une erreur commise par les programmeurs dans le code de production.
Je ne sais pas si les résultats de la recherche sont à jour, mais lorsque j'ai lancé la recherche, j'ai obtenu des résultats avec du code provenant de Google, Amazon, Apache... et de moi.
Une récente demande d'extension sur l'un de mes projets open source visait à résoudre exactement cette erreur.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Comment le trouver
Lorsque j'ai vérifié mon exemple de code dans quelques analyseurs statiques, aucun d'entre eux n'a détecté ce code d'autodestruction caché.
L'équipe de Secure Code Warrior a créé et examiné une recette assez simple de Sensei qui pourrait répondre à ce besoin.
Les opérateurs Bitwise étant parfaitement valables et souvent utilisés dans les affectations, nous nous sommes concentrés sur l'utilisation des instructions if et sur l'utilisation de Bitwise &, pour trouver le code problématique.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Cette fonction utilise une expression régulière pour faire correspondre " & " lorsqu'elle est utilisée comme expression de condition, par exemple dans une instruction if.
Pour y remédier, nous nous sommes à nouveau appuyés sur les expressions régulières. Cette fois-ci, nous avons utilisé la fonction sed de QuickFix pour remplacer globalement le & de l'expression par &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notes de fin
Cela couvre l'utilisation abusive la plus courante d'un opérateur bitwise, c'est-à-dire lorsqu'un opérateur booléen était en fait prévu.
Il existe d'autres situations où cela pourrait se produire, par exemple dans l'exemple de l'affectation, mais lorsque nous écrivons des recettes, nous devons essayer d'éviter les identifications faussement positives, faute de quoi les recettes seront ignorées ou désactivées. Nous élaborons des recettes qui correspondent aux occurrences les plus courantes. Au fur et à mesure de l'évolution de Sensei , nous pourrons ajouter des spécificités supplémentaires à la fonctionnalité de recherche afin de couvrir davantage de conditions de correspondance.
Dans sa forme actuelle, cette recette permettrait d'identifier de nombreux cas d'utilisation en direct, et surtout celui qui a été rapporté dans le cadre de mon projet.
NOTE : Quelques guerriers du code ont contribué à cet exemple et à la révision de la recette - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Merci pour votre aide.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Préférences \NPlugins" (Mac) ou "Paramètres \NPlugins" (Windows) puis en recherchant "sensei secure code".
Nous avons beaucoup de code source et de recettes pour ces articles de blog (y compris celui-ci) dans le dépôt `sensei-blog-examples` dans le compte GitHub Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples

Java Gotchas - Opérateurs booléens et opérateurs bitwise
> "Java Gotcha" - un modèle d'erreur courant qu'il est facile de mettre en œuvre accidentellement.
Une erreur Java assez simple à commettre accidentellement est l'utilisation d'un opérateur Bitwise au lieu d'un opérateur de comparaison booléen.
Par exemple, une simple erreur de frappe peut conduire à écrire "&" alors que vous vouliez en réalité écrire "&&".
Une heuristique courante que nous apprenons lors de l'examen du code est la suivante :
> Les mots "&" ou "|" utilisés dans une déclaration conditionnelle ne sont probablement pas destinés à être utilisés.
Dans cet article de blog, nous allons explorer l'heuristique et identifier les moyens d'identifier et de corriger ce problème de codage.
Quel est le problème ? Les opérations bitwise fonctionnent bien avec les booléens
L'utilisation des opérateurs Bitwise avec les booléens est parfaitement valide, de sorte que Java ne signale pas d'erreur de syntaxe.
Si je construis un test JUnit pour explorer une table de vérité à la fois pour Bitwise OR (|) et Bitwise AND (&), nous verrons que les sorties de l'opérateur Bitwise correspondent à la table de vérité. Dans ces conditions, nous pourrions penser que l'utilisation des opérateurs bitwise n'est pas un problème.
Table de vérité AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Le test est réussi, il s'agit d'un Java parfaitement valide.
Table de vérité OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Ce test est également réussi, pourquoi préférons-nous "&&" et "||" ?
Les images de la table de vérité ont été créées à l'aide de l'outil outil de table de vérité à partir de web.standfor.edu.
Problème : Fonctionnement en court-circuit
Le vrai problème est la différence de comportement entre les opérateurs binaires (&, |) et booléens (&&, ||).
Un opérateur booléen est un opérateur de court-circuit et n'évalue que ce qui est nécessaire.
par exemple
if (args != null & args.length() > 23) {
System.out.println(args);
}
Dans le code ci-dessus, les deux conditions booléennes seront évaluées, car l'opérateur Bitwise a été utilisé :
- args != null
- args.length() > 23
Cela expose mon code à une NullPointerException si args est nul car nous allons toujours vérifier la longueur de args, même si args est nul car les deux conditions booléennes doivent être évaluées.
Opérateurs booléens Évaluation des courts-circuits
Lorsqu'un && est utilisé, par exemple
if (args != null && args.length() > 23) {
System.out.println(args);
}
Dès que nous savons que l'expression args != null est évaluée à false, l'évaluation de l'expression de la condition s'arrête.
Nous n'avons pas besoin d'évaluer le côté droit.
Quel que soit le résultat de la condition du côté droit, la valeur finale de l'expression booléenne sera fausse.
Mais cela ne se produirait jamais dans un code de production
Il s'agit d'une erreur assez facile à commettre, qui n'est pas toujours détectée par les outils d'analyse statique.
J'ai utilisé le Google Dork suivant pour voir si je pouvais trouver des exemples publics de ce modèle :
filetype:java if "!=null & "
Cette recherche a permis de retrouver du code d'Android dans le RootWindowContainer
isDocument = intent != null & intent.isDocument()
C'est le type de code qui pourrait passer un examen de code parce que nous utilisons souvent les opérateurs Bitwise dans les instructions d'affectation pour masquer les valeurs. Mais dans ce cas, le résultat est le même que dans l'exemple de l'instruction if ci-dessus. Si intent est null, une exception NullPointerException sera levée.
Très souvent, nous nous en sortons avec cette construction parce que nous codons souvent de manière défensive et écrivons du code redondant. La vérification de != null peut être redondante dans la plupart des cas d'utilisation.
Il s'agit d'une erreur commise par les programmeurs dans le code de production.
Je ne sais pas si les résultats de la recherche sont à jour, mais lorsque j'ai lancé la recherche, j'ai obtenu des résultats avec du code provenant de Google, Amazon, Apache... et de moi.
Une récente demande d'extension sur l'un de mes projets open source visait à résoudre exactement cette erreur.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Comment le trouver
Lorsque j'ai vérifié mon exemple de code dans quelques analyseurs statiques, aucun d'entre eux n'a détecté ce code d'autodestruction caché.
L'équipe de Secure Code Warrior a créé et examiné une recette assez simple de Sensei qui pourrait répondre à ce besoin.
Les opérateurs Bitwise étant parfaitement valables et souvent utilisés dans les affectations, nous nous sommes concentrés sur l'utilisation des instructions if et sur l'utilisation de Bitwise &, pour trouver le code problématique.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Cette fonction utilise une expression régulière pour faire correspondre " & " lorsqu'elle est utilisée comme expression de condition, par exemple dans une instruction if.
Pour y remédier, nous nous sommes à nouveau appuyés sur les expressions régulières. Cette fois-ci, nous avons utilisé la fonction sed de QuickFix pour remplacer globalement le & de l'expression par &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notes de fin
Cela couvre l'utilisation abusive la plus courante d'un opérateur bitwise, c'est-à-dire lorsqu'un opérateur booléen était en fait prévu.
Il existe d'autres situations où cela pourrait se produire, par exemple dans l'exemple de l'affectation, mais lorsque nous écrivons des recettes, nous devons essayer d'éviter les identifications faussement positives, faute de quoi les recettes seront ignorées ou désactivées. Nous élaborons des recettes qui correspondent aux occurrences les plus courantes. Au fur et à mesure de l'évolution de Sensei , nous pourrons ajouter des spécificités supplémentaires à la fonctionnalité de recherche afin de couvrir davantage de conditions de correspondance.
Dans sa forme actuelle, cette recette permettrait d'identifier de nombreux cas d'utilisation en direct, et surtout celui qui a été rapporté dans le cadre de mon projet.
NOTE : Quelques guerriers du code ont contribué à cet exemple et à la révision de la recette - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Merci pour votre aide.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Préférences \NPlugins" (Mac) ou "Paramètres \NPlugins" (Windows) puis en recherchant "sensei secure code".
Nous avons beaucoup de code source et de recettes pour ces articles de blog (y compris celui-ci) dans le dépôt `sensei-blog-examples` dans le compte GitHub Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples

Cliquez sur le lien ci-dessous et téléchargez le PDF de cette ressource.
Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.
Voir le rapportRéservez une démonstrationAlan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.
Java Gotchas - Opérateurs booléens et opérateurs bitwise
> "Java Gotcha" - un modèle d'erreur courant qu'il est facile de mettre en œuvre accidentellement.
Une erreur Java assez simple à commettre accidentellement est l'utilisation d'un opérateur Bitwise au lieu d'un opérateur de comparaison booléen.
Par exemple, une simple erreur de frappe peut conduire à écrire "&" alors que vous vouliez en réalité écrire "&&".
Une heuristique courante que nous apprenons lors de l'examen du code est la suivante :
> Les mots "&" ou "|" utilisés dans une déclaration conditionnelle ne sont probablement pas destinés à être utilisés.
Dans cet article de blog, nous allons explorer l'heuristique et identifier les moyens d'identifier et de corriger ce problème de codage.
Quel est le problème ? Les opérations bitwise fonctionnent bien avec les booléens
L'utilisation des opérateurs Bitwise avec les booléens est parfaitement valide, de sorte que Java ne signale pas d'erreur de syntaxe.
Si je construis un test JUnit pour explorer une table de vérité à la fois pour Bitwise OR (|) et Bitwise AND (&), nous verrons que les sorties de l'opérateur Bitwise correspondent à la table de vérité. Dans ces conditions, nous pourrions penser que l'utilisation des opérateurs bitwise n'est pas un problème.
Table de vérité AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
Le test est réussi, il s'agit d'un Java parfaitement valide.
Table de vérité OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Ce test est également réussi, pourquoi préférons-nous "&&" et "||" ?
Les images de la table de vérité ont été créées à l'aide de l'outil outil de table de vérité à partir de web.standfor.edu.
Problème : Fonctionnement en court-circuit
Le vrai problème est la différence de comportement entre les opérateurs binaires (&, |) et booléens (&&, ||).
Un opérateur booléen est un opérateur de court-circuit et n'évalue que ce qui est nécessaire.
par exemple
if (args != null & args.length() > 23) {
System.out.println(args);
}
Dans le code ci-dessus, les deux conditions booléennes seront évaluées, car l'opérateur Bitwise a été utilisé :
- args != null
- args.length() > 23
Cela expose mon code à une NullPointerException si args est nul car nous allons toujours vérifier la longueur de args, même si args est nul car les deux conditions booléennes doivent être évaluées.
Opérateurs booléens Évaluation des courts-circuits
Lorsqu'un && est utilisé, par exemple
if (args != null && args.length() > 23) {
System.out.println(args);
}
Dès que nous savons que l'expression args != null est évaluée à false, l'évaluation de l'expression de la condition s'arrête.
Nous n'avons pas besoin d'évaluer le côté droit.
Quel que soit le résultat de la condition du côté droit, la valeur finale de l'expression booléenne sera fausse.
Mais cela ne se produirait jamais dans un code de production
Il s'agit d'une erreur assez facile à commettre, qui n'est pas toujours détectée par les outils d'analyse statique.
J'ai utilisé le Google Dork suivant pour voir si je pouvais trouver des exemples publics de ce modèle :
filetype:java if "!=null & "
Cette recherche a permis de retrouver du code d'Android dans le RootWindowContainer
isDocument = intent != null & intent.isDocument()
C'est le type de code qui pourrait passer un examen de code parce que nous utilisons souvent les opérateurs Bitwise dans les instructions d'affectation pour masquer les valeurs. Mais dans ce cas, le résultat est le même que dans l'exemple de l'instruction if ci-dessus. Si intent est null, une exception NullPointerException sera levée.
Très souvent, nous nous en sortons avec cette construction parce que nous codons souvent de manière défensive et écrivons du code redondant. La vérification de != null peut être redondante dans la plupart des cas d'utilisation.
Il s'agit d'une erreur commise par les programmeurs dans le code de production.
Je ne sais pas si les résultats de la recherche sont à jour, mais lorsque j'ai lancé la recherche, j'ai obtenu des résultats avec du code provenant de Google, Amazon, Apache... et de moi.
Une récente demande d'extension sur l'un de mes projets open source visait à résoudre exactement cette erreur.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Comment le trouver
Lorsque j'ai vérifié mon exemple de code dans quelques analyseurs statiques, aucun d'entre eux n'a détecté ce code d'autodestruction caché.
L'équipe de Secure Code Warrior a créé et examiné une recette assez simple de Sensei qui pourrait répondre à ce besoin.
Les opérateurs Bitwise étant parfaitement valables et souvent utilisés dans les affectations, nous nous sommes concentrés sur l'utilisation des instructions if et sur l'utilisation de Bitwise &, pour trouver le code problématique.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Cette fonction utilise une expression régulière pour faire correspondre " & " lorsqu'elle est utilisée comme expression de condition, par exemple dans une instruction if.
Pour y remédier, nous nous sommes à nouveau appuyés sur les expressions régulières. Cette fois-ci, nous avons utilisé la fonction sed de QuickFix pour remplacer globalement le & de l'expression par &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notes de fin
Cela couvre l'utilisation abusive la plus courante d'un opérateur bitwise, c'est-à-dire lorsqu'un opérateur booléen était en fait prévu.
Il existe d'autres situations où cela pourrait se produire, par exemple dans l'exemple de l'affectation, mais lorsque nous écrivons des recettes, nous devons essayer d'éviter les identifications faussement positives, faute de quoi les recettes seront ignorées ou désactivées. Nous élaborons des recettes qui correspondent aux occurrences les plus courantes. Au fur et à mesure de l'évolution de Sensei , nous pourrons ajouter des spécificités supplémentaires à la fonctionnalité de recherche afin de couvrir davantage de conditions de correspondance.
Dans sa forme actuelle, cette recette permettrait d'identifier de nombreux cas d'utilisation en direct, et surtout celui qui a été rapporté dans le cadre de mon projet.
NOTE : Quelques guerriers du code ont contribué à cet exemple et à la révision de la recette - Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Merci pour votre aide.
---
Vous pouvez installer Sensei à partir d'IntelliJ en utilisant "Préférences \NPlugins" (Mac) ou "Paramètres \NPlugins" (Windows) puis en recherchant "sensei secure code".
Nous avons beaucoup de code source et de recettes pour ces articles de blog (y compris celui-ci) dans le dépôt `sensei-blog-examples` dans le compte GitHub Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples
Table des matières
Alan Richardson a plus de vingt ans d'expérience professionnelle dans le domaine des technologies de l'information. Il a travaillé en tant que développeur et à tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs à l'adresse Secure Code Warrior, il travaille directement avec les équipes pour améliorer le développement de codes sécurisés de qualité. Alan est l'auteur de quatre livres, dont "Dear Evil Tester" et "Java For Testers". Alan a également créé une formation en ligne courses pour aider les gens à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses écrits et ses vidéos de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Secure Code Warrior est là pour vous aider à sécuriser le code tout au long du cycle de vie du développement logiciel et à créer une culture dans laquelle la cybersécurité est une priorité. Que vous soyez responsable AppSec, développeur, CISO ou toute autre personne impliquée dans la sécurité, nous pouvons aider votre organisation à réduire les risques associés à un code non sécurisé.
Réservez une démonstrationTéléchargerRessources pour vous aider à démarrer
Aperçu de la gestion des risques pour les développeurs
La gestion des risques pour les développeurs est une approche holistique et proactive de la sécurité des applications, axée sur les contributeurs au code plutôt que sur les bits et les octets de la couche d'application elle-même.
Sécurité dès la conception : Définir les meilleures pratiques, permettre aux développeurs et évaluer les résultats de la sécurité préventive
Dans ce document de recherche, les cofondateurs de Secure Code Warrior , Pieter Danhieux et Matias Madou, Ph.D., ainsi que des contributeurs experts, Chris Inglis, ancien directeur national américain de la cybernétique (aujourd'hui conseiller stratégique du Paladin Capital Group), et Devin Lynch, directeur principal du Paladin Global Institute, révèleront les principales conclusions de plus de vingt entretiens approfondis avec des responsables de la sécurité des entreprises, y compris des RSSI, un vice-président de la sécurité des applications et des professionnels de la sécurité des logiciels.
Évaluation comparative des compétences en matière de sécurité : Rationalisation de la conception sécurisée dans l'entreprise
Il est notoirement difficile de trouver des données significatives sur le succès des initiatives Secure-by-Design. Les RSSI sont souvent confrontés à des difficultés lorsqu'ils tentent de prouver le retour sur investissement (ROI) et la valeur commerciale des activités du programme de sécurité, tant au niveau des personnes que de l'entreprise. De plus, il est particulièrement difficile pour les entreprises d'obtenir des informations sur la façon dont leurs organisations sont comparées aux normes actuelles du secteur. La stratégie nationale de cybersécurité du président a mis les parties prenantes au défi d'"adopter la sécurité et la résilience dès la conception". Pour que les initiatives de conception sécurisée fonctionnent, il faut non seulement donner aux développeurs les compétences nécessaires pour assurer la sécurité du code, mais aussi garantir aux régulateurs que ces compétences sont en place. Dans cette présentation, nous partageons une myriade de données qualitatives et quantitatives, dérivées de sources primaires multiples, y compris des points de données internes collectés auprès de plus de 250 000 développeurs, des informations sur les clients basées sur des données, et des études publiques. En nous appuyant sur cette agrégation de points de données, nous visons à communiquer une vision de l'état actuel des initiatives Secure-by-Design dans de multiples secteurs verticaux. Le rapport explique en détail pourquoi cet espace est actuellement sous-utilisé, l'impact significatif qu'un programme de perfectionnement réussi peut avoir sur l'atténuation des risques de cybersécurité, et le potentiel d'élimination des catégories de vulnérabilités d'une base de code.
Services professionnels - Accélérer grâce à l'expertise
L'équipe des services de stratégie de programme (PSS) de Secure Code Warriorvous aide à construire, améliorer et optimiser votre programme de codage sécurisé. Que vous partiez de zéro ou que vous affiniez votre approche, nos experts vous fournissent des conseils sur mesure.
Ressources pour vous aider à démarrer
Révélation : Comment l'industrie du cyberespace définit la notion de "Secure by Design" (sécurité dès la conception)
Dans notre dernier livre blanc, nos cofondateurs, Pieter Danhieux et Matias Madou, Ph.D., ont rencontré plus de vingt responsables de la sécurité d'entreprise, notamment des RSSI, des responsables AppSec et des professionnels de la sécurité, afin d'identifier les principales pièces de ce puzzle et de découvrir la réalité qui se cache derrière le mouvement Secure by Design. Il s'agit d'une ambition partagée par les équipes de sécurité, mais il n'y a pas de manuel de jeu commun.
Vibe Coding va-t-il transformer votre base de code en une fête de fraternité ?
Le codage vibratoire est comme une fête de fraternité universitaire, et l'IA est la pièce maîtresse de toutes les festivités, le tonneau. C'est très amusant de se laisser aller, d'être créatif et de voir où votre imagination peut vous mener, mais après quelques barils, boire (ou utiliser l'IA) avec modération est sans aucun doute la solution la plus sûre à long terme.