Blog

Java Gotchas - Opérateurs bitwise ou booléens

February 7, 2021
Alan Richardson

Java Gotchas - Opérateurs bitwise ou booléens

> « Java Gotcha » - un modèle d'erreur courant facile à implémenter accidentellement.

Un piège Java assez simple dans lequel tomber accidentellement est le suivant : utiliser un opérateur bit à bit au lieu d'un opérateur de comparaison booléen.

Par exemple, une simple erreur de saisie peut entraîner l'écriture de « & » alors que vous vouliez vraiment écrire « && ».

Une heuristique courante que nous apprenons lors de la révision du code est la suivante :

> « & » ou « | » utilisé dans une instruction conditionnelle n'est probablement pas prévu.

Dans cet article de blog, nous allons explorer l'heuristique et identifier les moyens d'identifier et de résoudre ce problème de codage.


Quel est le problème ? Les opérations au niveau du bit fonctionnent correctement avec les booléens


L'utilisation d'opérateurs bitwise avec des booléens est parfaitement valide. Java ne signalera donc 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é. Compte tenu de cela, nous pourrions penser que l'utilisation d'opérateurs Bitwise n'est pas un problème.

ET Truth Table

Three columns on with a, one with b, and the last with (a^b)


@Test
annulez BitwiseOperatorsAndTruthTable () {
assertions.assertEquals (vrai, vrai et vrai) ;
Assertions.assertEquals (faux, vrai et faux) ;
Assertions.assertEquals (faux, faux et vrai) ;
Assertions.assertEquals (faux, faux et faux) ;
}


Le test est réussi, c'est du Java parfaitement valide.


OR Truth Table


Three columns on with a, one with b, and the last with (a v b)


@Test
annulez BitwiseOperatorsorTruthTable () {
assertions.assertEquals (vrai, vrai | vrai) ;
Assertions.assertEquals (vrai, vrai | faux) ;
Assertions.assertEquals (vrai, faux | vrai) ;
Assertions.assertEquals (faux, faux | faux) ;
}


Ce test passe également, pourquoi préférons-nous « &&'et « ||' ?


Les images de la table de vérité ont été créées à l'aide du outil de table de vérité à partir de web.standfor.edu.


Problème : Fonctionnement en court-circuit


Le véritable problème est la différence de comportement entre les opérateurs bitwise (&, |) et booléens (&&, ||).

Un opérateur booléen est un opérateur de court-circuit qui n'évalue que ce dont il a besoin.

p. ex.

si (args) ! = null et 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é :

  • des chiffons ! = nul
  • args.length () > 23

Cela laisse mon code ouvert à une NullPointerException si args est nul car nous effectuerons toujours la vérification de args.length, même lorsque args est nul car les deux conditions booléennes doivent être évaluées.


Évaluation des courts-circuits par les opérateurs booléens


Lorsqu'un && est utilisé, par exemple

si (args) ! = null && args.length () > 23) {
System.out.println (args) ;
}


Dès que nous saurons ça, Args ! = null donne la valeur False lorsque l'évaluation de l'expression de 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 n'arriverait jamais dans le code de production


Il s'agit d'une erreur assez facile à commettre et 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 :

type de fichier : java si « ! =nul & »
Cette recherche a permis de récupérer du code d'Android dans le RootWindowContainer
IsDocument = intention ! = null et Intent.isDocument ()


C'est le type de code qui peut passer une revue de code car nous utilisons souvent des 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 d'instruction if ci-dessus. Si l'intention est nulle, une exception NullPointerException sera levée.

Très souvent, nous nous en tirons avec cette construction car nous codons souvent de manière défensive et écrivons du code redondant. Le chèque pour ! = null peut être redondant 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 je l'ai exécutée, des résultats contenant du code provenant de : Google, Amazon, Apache... et moi étaient renvoyés.

Un récent demande d'extraction sur l'un de mes projets open source était de corriger exactement cette erreur.

si (tapez ! =null et tapez .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é.

En tant qu'équipe de Secure Code Warrior, nous avons créé et révisé une recette Sensei assez simple qui pourrait répondre à ce problème.

Les opérateurs Bitwise étant parfaitement valides et souvent utilisés dans les affectations, nous nous sommes concentrés sur le cas d'utilisation des instructions if et sur l'utilisation de Bitwise & pour trouver le code problématique.

recherche :
expression :
N'importe lequel des :
- dans :
état : {}
valeur :
CaseSensitive : faux
correspond à : « .* » et . * »


Cela utilise une expression régulière pour correspondre à « & » lorsqu'elle est utilisée comme expression de condition, par exemple dans une instruction if.

Pour résoudre ce problème, nous nous sommes à nouveau appuyés sur des expressions régulières. Cette fois, utilisez la fonction sed du QuickFix pour remplacer globalement le & dans l'expression par &&.

Correctifs disponibles :
- nom : « Remplacer l'opérateur AND au niveau du bit par l'opérateur ET logique »
actions :
- réécrire :
à : « {{#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 réellement prévu.

Dans d'autres situations, cela peut survenir, par exemple l'exemple d'affectation, mais lors de la rédaction de recettes, nous devons essayer d'éviter une identification faussement positive, sinon les recettes seront ignorées ou désactivées. Nous élaborons des recettes qui correspondent aux événements les plus courants. Au fur et à mesure de l'évolution de Sensei, nous pourrions ajouter une spécificité supplémentaire à la fonctionnalité de recherche pour couvrir davantage de conditions correspondantes.

Dans sa forme actuelle, cette recette permettrait d'identifier de nombreux cas d'utilisation actuels, et le plus important, celui qui a été signalé dans mon projet.

REMARQUE : De nombreux experts du code ont contribué à cet exemple et à cette critique de recette : Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Merci pour ton aide.


---


Vous pouvez installer Sensei depuis IntelliJ en utilisant « Préférences \ Plugins » (Mac) ou « Paramètres \ Plugins » (Windows), puis recherchez simplement « Sensei Secure Code »

Nous avons beaucoup de code source et de recettes pour ces articles de blog (y compris celui-ci) dans le référentiel « sensei-blog-examples » du compte GitHub de Secure Code Warrior.

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

En savoir plus sur Sensei


Slogan

Govern AI-driven development before it ships

Measure AI-assisted risk, enforce secure coding policy at commit, and accelerate secure delivery across your SDLC.

book a demo
Slogan

Explore more blogs

Lorem ipsum diam quis enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis eu volutpat odio facilisis.

browse all
Case Study
Filter Label
This is some text inside of a div block.

Supercharged Security Awareness: How Tournaments are Inspiring Developers at Erste Group

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Learn More
Case Study
Filter Label
This is some text inside of a div block.

Security as culture: How Blue Prism cultivates world-class secure developers

Learn how Blue Prism, the global leader in intelligent automation for the enterprise, used Secure Code Warrior's agile learning platform to create a security-first culture with their developers, achieve their business goals, and ship secure code at speed

Learn More
Case Study
Filter Label
This is some text inside of a div block.

One Culture of Security: How Sage built their security champions program with agile secure code learning

Discover how Sage enhanced security with a flexible, relationship-focused approach, creating 200+ security champions and achieving measurable risk reduction.

Learn More
Blog
Filter Label
This is some text inside of a div block.

Enabler 7: Developer Recognition

Recognition fuels participation. Enabler 7 celebrates developer achievement loudly, with rewards and exclusive swag that mark real, earned secure coding wins.

Learn More
Blog
Filter Label
This is some text inside of a div block.

Named in the Gartner® Hype Cycle™ for Application Security 2026

Secure Code Warrior is named in the Gartner® Hype Cycle™ for Application Security, 2026 for Agentic Coding Security and Secure Coding Training. Here's why.

Learn More
Blog
Filter Label
This is some text inside of a div block.

Are you a CISO or Engineering Leader worried about the Security and Cost of LLM code generation?

Review the SCW AI Trust Index, our proprietary LLM benchmarking data, before going all-in on an AI model.

Learn More

Secure AI-driven development before it ships

See developer risk, enforce policy, and prevent vulnerabilities across your software development lifecycle.

Réserver une démo
trust score
No items found.