Iconos SCW
héroe bg sin separador
Blog

Java Gotchas - Operadores bit a bit o booleanos

Alan Richardson
Publicado el 07 de febrero de 2021
Última actualización el 8 de marzo de 2026

Java Gotchas - Operadores bit a bit o booleanos

« Java Gotcha »: un modelo de error común fácil de implementar accidentalmente.

Una trampa bastante simple en Java en la que se puede caer accidentalmente es la siguiente: utilizar un operador bit a bit en lugar de un operador de comparación booleano.

Por ejemplo, un simple error al escribir puede hacer que se escriba «&» cuando realmente se quería escribir «&&».

Una heurística habitual que aprendemos al revisar el código es la siguiente:

« & » o « | » utilizado en una instrucción condicional probablemente no esté previsto.

En este artículo del blog, exploraremos la heurística e identificaremos formas de detectar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones a nivel de bits funcionan correctamente con los booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido. Por lo tanto, Java no señalará ningún error de sintaxis.

Si construyo una prueba JUnit para explorar una tabla de verdad tanto para Bitwise OR (|) como para Bitwise AND (&), veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Teniendo esto en cuenta, podríamos pensar que el uso de operadores Bitwise no es un problema.

Tabla de verdad ET

Tres columnas una con a, otra con b, y la última con (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) ;
}


La prueba ha sido satisfactoria, es Java perfectamente válido.


Tabla de verdad de OR


Tres columnas sobre con a, una con b, y la última con (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) ;
}


Esta prueba también pasa, ¿por qué preferimos « &&» y « ||»?


Las imágenes de la tabla de verdad se crearon utilizando la herramienta de tabla de verdad a partir de web.standfor.edu.


Problema: Funcionamiento en cortocircuito


El verdadero problema es la diferencia de comportamiento entre los operadores bit a bit (&, |) y los operadores booleanos (&&, ||).

Un operador booleano es un operador de cortocircuito que solo evalúa lo que necesita.

p. ej.

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


En el código anterior, se evaluarán las dos condiciones booleanas, ya que se ha utilizado el operador bit a bit:

  • ¡Des chiffons! = Nulo
  • args.length () > 23

Esto deja mi código expuesto a una excepción NullPointerException si args es nulo, ya que siempre realizaremos la comprobación de args.length, incluso cuando args sea nulo, ya que ambas condiciones booleanas deben evaluarse.


Evaluación de cortocircuitos mediante operadores booleanos


Cuando se utiliza &&, por ejemplo

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


En cuanto lo sepamos, Args ! = null devuelve el valor False cuando se detiene la evaluación de la expresión de condición.

No necesitamos evaluar el lado derecho.

Sea cual sea el resultado de la condición del lado derecho, el valor final de la expresión booleana será falso.


Pero eso nunca ocurriría en el código de producción.


Se trata de un error bastante fácil de cometer y que no siempre es detectado por las herramientas de análisis estático.

He utilizado el siguiente Google Dork para ver si podía encontrar ejemplos públicos de este modelo:

tipo de archivo: java si «! =nul &»
Esta búsqueda permitió recuperar código de Android en RootWindowContainer
IsDocument = intention ! = null e Intent.isDocument ()


Este es el tipo de código que puede pasar una revisión de código, ya que a menudo utilizamos operadores bit a bit en las instrucciones de asignación para ocultar los valores. Pero en este caso, el resultado es el mismo que en el ejemplo de instrucción if anterior. Si la intención es nula, se lanzará una excepción NullPointerException.

Muy a menudo, nos salimos con la nuestra con esta construcción porque solemos programar de forma defensiva y escribimos código redundante. La comprobación de ! = null puede ser redundante en la mayoría de los casos de uso.

Se trata de un error cometido por los programadores en el código de producción.

No sé si los resultados de la búsqueda están actualizados, pero cuando la ejecuté, se mostraron resultados que contenían código procedente de: Google, Amazon, Apache... y yo.

Una reciente solicitud de extracción en uno de mis proyectos de código abierto consistía precisamente en corregir este error.

si (tapez ! =null et tapez .trim () .length () >0) {
AcceptMediaTypeDefinitionsList.add (type.trim ()) ;
}


¿Cómo encontrarlo?


Cuando comprobé mi ejemplo de código en varios analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta Sensei sencilla que podría dar respuesta a este problema.

Dado que los operadores bit a bit son perfectamente válidos y se utilizan a menudo en las asignaciones, nos hemos centrado en el caso de uso de las instrucciones if y en el uso de Bitwise & para encontrar el código problemático.

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


Utiliza una expresión regular para coincidir con «&» cuando se utiliza como expresión de condición, por ejemplo, en una instrucción if.

Para resolver este problema, volvimos a recurrir a las expresiones regulares. Esta vez, utilice la función sed de QuickFix para sustituir globalmente el & de la expresión por &&.

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}} »


Notas finales

Esto cubre el uso indebido más común de un operador bit a bit, es decir, cuando realmente se esperaba un operador booleano.

En otras situaciones, esto puede ocurrir, por ejemplo, en el caso de la asignación, pero al redactar las recetas, debemos intentar evitar una identificación falsamente positiva, ya que, de lo contrario, las recetas se ignorarán o desactivarán. Elaboramos recetas que se corresponden con los eventos más habituales. A medida que Sensei evolucione, podríamos añadir una especificidad adicional a la función de búsqueda para cubrir más condiciones correspondientes.

En su forma actual, esta receta permitiría identificar numerosos casos de uso actuales y, lo que es más importante, el que se ha señalado en mi proyecto.

NOTA: Numerosos expertos en código han contribuido a este ejemplo y a esta crítica de receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por tu ayuda.


---


Puede instalar Sensei IntelliJ utilizando «Preferencias \ Complementos» (Mac) o «Configuración \ Complementos» (Windows) y, a continuación, simplemente busqueSensei Code».

Tenemos mucho código fuente y recetas para estos artículos de blog (incluido este) en el repositoriosensei de la cuenta GitHub de Secure Code Warrior.

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

Más información sobre Sensei


Mostrar el recurso
Mostrar el recurso

En este artículo del blog, analizamos un error común en la codificación Java (el uso de un operador a nivel de bit en lugar de un operador condicional), el error al que expone nuestro código y cómo podemos utilizar Sensei corregir y detectar el problema.

¿Desea obtener más información?

Alan Richardson possède plus de vingt ans d'expérience professionnelle en informatique. Il a travaillé en tant que développeur et a occupé tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs chez Secure Code Warrior, il travaille directement avec les équipes, pour améliorer le développement d'un code sécurisé de qualité. Alan est l'auteur de quatre livres, dont « Dear Evil Tester » et « Java For Testers ». Alan a également créé des cours de formation en ligne pour aider les utilisateurs à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses vidéos d'écriture et de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Más información

Secure Code Warrior aquí para ayudar a su organización a proteger el código a lo largo de todo el ciclo de desarrollo de software y a crear una cultura en la que la ciberseguridad sea una prioridad. Tanto si es responsable de la seguridad de las aplicaciones, desarrollador, responsable de la seguridad informática o cualquier otra persona involucrada en la seguridad, podemos ayudar a su organización a reducir los riesgos asociados a un código no seguro.

Reserve una demostración
Compartir en:
marcas de LinkedInSocialx logotipo
Autor
Alan Richardson
Publicado el 07 de febrero de 2021

Alan Richardson possède plus de vingt ans d'expérience professionnelle en informatique. Il a travaillé en tant que développeur et a occupé tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs chez Secure Code Warrior, il travaille directement avec les équipes, pour améliorer le développement d'un code sécurisé de qualité. Alan est l'auteur de quatre livres, dont « Dear Evil Tester » et « Java For Testers ». Alan a également créé des cours de formation en ligne pour aider les utilisateurs à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses vidéos d'écriture et de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Compartir en:
marcas de LinkedInSocialx logotipo

Java Gotchas - Operadores bit a bit o booleanos

« Java Gotcha »: un modelo de error común fácil de implementar accidentalmente.

Una trampa bastante simple en Java en la que se puede caer accidentalmente es la siguiente: utilizar un operador bit a bit en lugar de un operador de comparación booleano.

Por ejemplo, un simple error al escribir puede hacer que se escriba «&» cuando realmente se quería escribir «&&».

Una heurística habitual que aprendemos al revisar el código es la siguiente:

« & » o « | » utilizado en una instrucción condicional probablemente no esté previsto.

En este artículo del blog, exploraremos la heurística e identificaremos formas de detectar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones a nivel de bits funcionan correctamente con los booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido. Por lo tanto, Java no señalará ningún error de sintaxis.

Si construyo una prueba JUnit para explorar una tabla de verdad tanto para Bitwise OR (|) como para Bitwise AND (&), veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Teniendo esto en cuenta, podríamos pensar que el uso de operadores Bitwise no es un problema.

Tabla de verdad ET

Tres columnas una con a, otra con b, y la última con (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) ;
}


La prueba ha sido satisfactoria, es Java perfectamente válido.


Tabla de verdad de OR


Tres columnas sobre con a, una con b, y la última con (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) ;
}


Esta prueba también pasa, ¿por qué preferimos « &&» y « ||»?


Las imágenes de la tabla de verdad se crearon utilizando la herramienta de tabla de verdad a partir de web.standfor.edu.


Problema: Funcionamiento en cortocircuito


El verdadero problema es la diferencia de comportamiento entre los operadores bit a bit (&, |) y los operadores booleanos (&&, ||).

Un operador booleano es un operador de cortocircuito que solo evalúa lo que necesita.

p. ej.

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


En el código anterior, se evaluarán las dos condiciones booleanas, ya que se ha utilizado el operador bit a bit:

  • ¡Des chiffons! = Nulo
  • args.length () > 23

Esto deja mi código expuesto a una excepción NullPointerException si args es nulo, ya que siempre realizaremos la comprobación de args.length, incluso cuando args sea nulo, ya que ambas condiciones booleanas deben evaluarse.


Evaluación de cortocircuitos mediante operadores booleanos


Cuando se utiliza &&, por ejemplo

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


En cuanto lo sepamos, Args ! = null devuelve el valor False cuando se detiene la evaluación de la expresión de condición.

No necesitamos evaluar el lado derecho.

Sea cual sea el resultado de la condición del lado derecho, el valor final de la expresión booleana será falso.


Pero eso nunca ocurriría en el código de producción.


Se trata de un error bastante fácil de cometer y que no siempre es detectado por las herramientas de análisis estático.

He utilizado el siguiente Google Dork para ver si podía encontrar ejemplos públicos de este modelo:

tipo de archivo: java si «! =nul &»
Esta búsqueda permitió recuperar código de Android en RootWindowContainer
IsDocument = intention ! = null e Intent.isDocument ()


Este es el tipo de código que puede pasar una revisión de código, ya que a menudo utilizamos operadores bit a bit en las instrucciones de asignación para ocultar los valores. Pero en este caso, el resultado es el mismo que en el ejemplo de instrucción if anterior. Si la intención es nula, se lanzará una excepción NullPointerException.

Muy a menudo, nos salimos con la nuestra con esta construcción porque solemos programar de forma defensiva y escribimos código redundante. La comprobación de ! = null puede ser redundante en la mayoría de los casos de uso.

Se trata de un error cometido por los programadores en el código de producción.

No sé si los resultados de la búsqueda están actualizados, pero cuando la ejecuté, se mostraron resultados que contenían código procedente de: Google, Amazon, Apache... y yo.

Una reciente solicitud de extracción en uno de mis proyectos de código abierto consistía precisamente en corregir este error.

si (tapez ! =null et tapez .trim () .length () >0) {
AcceptMediaTypeDefinitionsList.add (type.trim ()) ;
}


¿Cómo encontrarlo?


Cuando comprobé mi ejemplo de código en varios analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta Sensei sencilla que podría dar respuesta a este problema.

Dado que los operadores bit a bit son perfectamente válidos y se utilizan a menudo en las asignaciones, nos hemos centrado en el caso de uso de las instrucciones if y en el uso de Bitwise & para encontrar el código problemático.

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


Utiliza una expresión regular para coincidir con «&» cuando se utiliza como expresión de condición, por ejemplo, en una instrucción if.

Para resolver este problema, volvimos a recurrir a las expresiones regulares. Esta vez, utilice la función sed de QuickFix para sustituir globalmente el & de la expresión por &&.

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}} »


Notas finales

Esto cubre el uso indebido más común de un operador bit a bit, es decir, cuando realmente se esperaba un operador booleano.

En otras situaciones, esto puede ocurrir, por ejemplo, en el caso de la asignación, pero al redactar las recetas, debemos intentar evitar una identificación falsamente positiva, ya que, de lo contrario, las recetas se ignorarán o desactivarán. Elaboramos recetas que se corresponden con los eventos más habituales. A medida que Sensei evolucione, podríamos añadir una especificidad adicional a la función de búsqueda para cubrir más condiciones correspondientes.

En su forma actual, esta receta permitiría identificar numerosos casos de uso actuales y, lo que es más importante, el que se ha señalado en mi proyecto.

NOTA: Numerosos expertos en código han contribuido a este ejemplo y a esta crítica de receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por tu ayuda.


---


Puede instalar Sensei IntelliJ utilizando «Preferencias \ Complementos» (Mac) o «Configuración \ Complementos» (Windows) y, a continuación, simplemente busqueSensei Code».

Tenemos mucho código fuente y recetas para estos artículos de blog (incluido este) en el repositoriosensei de la cuenta GitHub de Secure Code Warrior.

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

Más información sobre Sensei


Mostrar el recurso
Mostrar el recurso

Rellene el siguiente formulario para descargar el informe.

Nos gustaría obtener su autorización para enviarle información sobre nuestros productos y/o sobre temas relacionados con la codificación segura. Siempre trataremos sus datos personales con el mayor cuidado y nunca los venderemos a otras empresas con fines de marketing.

Enviar
Icono de éxito de SCW
Icono de error scw
Para enviar el formulario, active las cookies «Analytics». No dude en desactivarlas de nuevo una vez que haya terminado.

Java Gotchas - Operadores bit a bit o booleanos

« Java Gotcha »: un modelo de error común fácil de implementar accidentalmente.

Una trampa bastante simple en Java en la que se puede caer accidentalmente es la siguiente: utilizar un operador bit a bit en lugar de un operador de comparación booleano.

Por ejemplo, un simple error al escribir puede hacer que se escriba «&» cuando realmente se quería escribir «&&».

Una heurística habitual que aprendemos al revisar el código es la siguiente:

« & » o « | » utilizado en una instrucción condicional probablemente no esté previsto.

En este artículo del blog, exploraremos la heurística e identificaremos formas de detectar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones a nivel de bits funcionan correctamente con los booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido. Por lo tanto, Java no señalará ningún error de sintaxis.

Si construyo una prueba JUnit para explorar una tabla de verdad tanto para Bitwise OR (|) como para Bitwise AND (&), veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Teniendo esto en cuenta, podríamos pensar que el uso de operadores Bitwise no es un problema.

Tabla de verdad ET

Tres columnas una con a, otra con b, y la última con (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) ;
}


La prueba ha sido satisfactoria, es Java perfectamente válido.


Tabla de verdad de OR


Tres columnas sobre con a, una con b, y la última con (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) ;
}


Esta prueba también pasa, ¿por qué preferimos « &&» y « ||»?


Las imágenes de la tabla de verdad se crearon utilizando la herramienta de tabla de verdad a partir de web.standfor.edu.


Problema: Funcionamiento en cortocircuito


El verdadero problema es la diferencia de comportamiento entre los operadores bit a bit (&, |) y los operadores booleanos (&&, ||).

Un operador booleano es un operador de cortocircuito que solo evalúa lo que necesita.

p. ej.

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


En el código anterior, se evaluarán las dos condiciones booleanas, ya que se ha utilizado el operador bit a bit:

  • ¡Des chiffons! = Nulo
  • args.length () > 23

Esto deja mi código expuesto a una excepción NullPointerException si args es nulo, ya que siempre realizaremos la comprobación de args.length, incluso cuando args sea nulo, ya que ambas condiciones booleanas deben evaluarse.


Evaluación de cortocircuitos mediante operadores booleanos


Cuando se utiliza &&, por ejemplo

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


En cuanto lo sepamos, Args ! = null devuelve el valor False cuando se detiene la evaluación de la expresión de condición.

No necesitamos evaluar el lado derecho.

Sea cual sea el resultado de la condición del lado derecho, el valor final de la expresión booleana será falso.


Pero eso nunca ocurriría en el código de producción.


Se trata de un error bastante fácil de cometer y que no siempre es detectado por las herramientas de análisis estático.

He utilizado el siguiente Google Dork para ver si podía encontrar ejemplos públicos de este modelo:

tipo de archivo: java si «! =nul &»
Esta búsqueda permitió recuperar código de Android en RootWindowContainer
IsDocument = intention ! = null e Intent.isDocument ()


Este es el tipo de código que puede pasar una revisión de código, ya que a menudo utilizamos operadores bit a bit en las instrucciones de asignación para ocultar los valores. Pero en este caso, el resultado es el mismo que en el ejemplo de instrucción if anterior. Si la intención es nula, se lanzará una excepción NullPointerException.

Muy a menudo, nos salimos con la nuestra con esta construcción porque solemos programar de forma defensiva y escribimos código redundante. La comprobación de ! = null puede ser redundante en la mayoría de los casos de uso.

Se trata de un error cometido por los programadores en el código de producción.

No sé si los resultados de la búsqueda están actualizados, pero cuando la ejecuté, se mostraron resultados que contenían código procedente de: Google, Amazon, Apache... y yo.

Una reciente solicitud de extracción en uno de mis proyectos de código abierto consistía precisamente en corregir este error.

si (tapez ! =null et tapez .trim () .length () >0) {
AcceptMediaTypeDefinitionsList.add (type.trim ()) ;
}


¿Cómo encontrarlo?


Cuando comprobé mi ejemplo de código en varios analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta Sensei sencilla que podría dar respuesta a este problema.

Dado que los operadores bit a bit son perfectamente válidos y se utilizan a menudo en las asignaciones, nos hemos centrado en el caso de uso de las instrucciones if y en el uso de Bitwise & para encontrar el código problemático.

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


Utiliza una expresión regular para coincidir con «&» cuando se utiliza como expresión de condición, por ejemplo, en una instrucción if.

Para resolver este problema, volvimos a recurrir a las expresiones regulares. Esta vez, utilice la función sed de QuickFix para sustituir globalmente el & de la expresión por &&.

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}} »


Notas finales

Esto cubre el uso indebido más común de un operador bit a bit, es decir, cuando realmente se esperaba un operador booleano.

En otras situaciones, esto puede ocurrir, por ejemplo, en el caso de la asignación, pero al redactar las recetas, debemos intentar evitar una identificación falsamente positiva, ya que, de lo contrario, las recetas se ignorarán o desactivarán. Elaboramos recetas que se corresponden con los eventos más habituales. A medida que Sensei evolucione, podríamos añadir una especificidad adicional a la función de búsqueda para cubrir más condiciones correspondientes.

En su forma actual, esta receta permitiría identificar numerosos casos de uso actuales y, lo que es más importante, el que se ha señalado en mi proyecto.

NOTA: Numerosos expertos en código han contribuido a este ejemplo y a esta crítica de receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por tu ayuda.


---


Puede instalar Sensei IntelliJ utilizando «Preferencias \ Complementos» (Mac) o «Configuración \ Complementos» (Windows) y, a continuación, simplemente busqueSensei Code».

Tenemos mucho código fuente y recetas para estos artículos de blog (incluido este) en el repositoriosensei de la cuenta GitHub de Secure Code Warrior.

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

Más información sobre Sensei


Ver el seminario web
Comience
Más información

Haga clic en el enlace siguiente y descargue el PDF de este recurso.

Secure Code Warrior aquí para ayudar a su organización a proteger el código a lo largo de todo el ciclo de desarrollo de software y a crear una cultura en la que la ciberseguridad sea una prioridad. Tanto si es responsable de la seguridad de las aplicaciones, desarrollador, responsable de la seguridad informática o cualquier otra persona involucrada en la seguridad, podemos ayudar a su organización a reducir los riesgos asociados a un código no seguro.

Mostrar el informeReserve una demostración
Descargar el PDF
Mostrar el recurso
Compartir en:
marcas de LinkedInSocialx logotipo
¿Desea obtener más información?

Compartir en:
marcas de LinkedInSocialx logotipo
Autor
Alan Richardson
Publicado el 07 de febrero de 2021

Alan Richardson possède plus de vingt ans d'expérience professionnelle en informatique. Il a travaillé en tant que développeur et a occupé tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs chez Secure Code Warrior, il travaille directement avec les équipes, pour améliorer le développement d'un code sécurisé de qualité. Alan est l'auteur de quatre livres, dont « Dear Evil Tester » et « Java For Testers ». Alan a également créé des cours de formation en ligne pour aider les utilisateurs à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses vidéos d'écriture et de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Compartir en:
marcas de LinkedInSocialx logotipo

Java Gotchas - Operadores bit a bit o booleanos

« Java Gotcha »: un modelo de error común fácil de implementar accidentalmente.

Una trampa bastante simple en Java en la que se puede caer accidentalmente es la siguiente: utilizar un operador bit a bit en lugar de un operador de comparación booleano.

Por ejemplo, un simple error al escribir puede hacer que se escriba «&» cuando realmente se quería escribir «&&».

Una heurística habitual que aprendemos al revisar el código es la siguiente:

« & » o « | » utilizado en una instrucción condicional probablemente no esté previsto.

En este artículo del blog, exploraremos la heurística e identificaremos formas de detectar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones a nivel de bits funcionan correctamente con los booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido. Por lo tanto, Java no señalará ningún error de sintaxis.

Si construyo una prueba JUnit para explorar una tabla de verdad tanto para Bitwise OR (|) como para Bitwise AND (&), veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Teniendo esto en cuenta, podríamos pensar que el uso de operadores Bitwise no es un problema.

Tabla de verdad ET

Tres columnas una con a, otra con b, y la última con (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) ;
}


La prueba ha sido satisfactoria, es Java perfectamente válido.


Tabla de verdad de OR


Tres columnas sobre con a, una con b, y la última con (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) ;
}


Esta prueba también pasa, ¿por qué preferimos « &&» y « ||»?


Las imágenes de la tabla de verdad se crearon utilizando la herramienta de tabla de verdad a partir de web.standfor.edu.


Problema: Funcionamiento en cortocircuito


El verdadero problema es la diferencia de comportamiento entre los operadores bit a bit (&, |) y los operadores booleanos (&&, ||).

Un operador booleano es un operador de cortocircuito que solo evalúa lo que necesita.

p. ej.

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


En el código anterior, se evaluarán las dos condiciones booleanas, ya que se ha utilizado el operador bit a bit:

  • ¡Des chiffons! = Nulo
  • args.length () > 23

Esto deja mi código expuesto a una excepción NullPointerException si args es nulo, ya que siempre realizaremos la comprobación de args.length, incluso cuando args sea nulo, ya que ambas condiciones booleanas deben evaluarse.


Evaluación de cortocircuitos mediante operadores booleanos


Cuando se utiliza &&, por ejemplo

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


En cuanto lo sepamos, Args ! = null devuelve el valor False cuando se detiene la evaluación de la expresión de condición.

No necesitamos evaluar el lado derecho.

Sea cual sea el resultado de la condición del lado derecho, el valor final de la expresión booleana será falso.


Pero eso nunca ocurriría en el código de producción.


Se trata de un error bastante fácil de cometer y que no siempre es detectado por las herramientas de análisis estático.

He utilizado el siguiente Google Dork para ver si podía encontrar ejemplos públicos de este modelo:

tipo de archivo: java si «! =nul &»
Esta búsqueda permitió recuperar código de Android en RootWindowContainer
IsDocument = intention ! = null e Intent.isDocument ()


Este es el tipo de código que puede pasar una revisión de código, ya que a menudo utilizamos operadores bit a bit en las instrucciones de asignación para ocultar los valores. Pero en este caso, el resultado es el mismo que en el ejemplo de instrucción if anterior. Si la intención es nula, se lanzará una excepción NullPointerException.

Muy a menudo, nos salimos con la nuestra con esta construcción porque solemos programar de forma defensiva y escribimos código redundante. La comprobación de ! = null puede ser redundante en la mayoría de los casos de uso.

Se trata de un error cometido por los programadores en el código de producción.

No sé si los resultados de la búsqueda están actualizados, pero cuando la ejecuté, se mostraron resultados que contenían código procedente de: Google, Amazon, Apache... y yo.

Una reciente solicitud de extracción en uno de mis proyectos de código abierto consistía precisamente en corregir este error.

si (tapez ! =null et tapez .trim () .length () >0) {
AcceptMediaTypeDefinitionsList.add (type.trim ()) ;
}


¿Cómo encontrarlo?


Cuando comprobé mi ejemplo de código en varios analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta Sensei sencilla que podría dar respuesta a este problema.

Dado que los operadores bit a bit son perfectamente válidos y se utilizan a menudo en las asignaciones, nos hemos centrado en el caso de uso de las instrucciones if y en el uso de Bitwise & para encontrar el código problemático.

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


Utiliza una expresión regular para coincidir con «&» cuando se utiliza como expresión de condición, por ejemplo, en una instrucción if.

Para resolver este problema, volvimos a recurrir a las expresiones regulares. Esta vez, utilice la función sed de QuickFix para sustituir globalmente el & de la expresión por &&.

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}} »


Notas finales

Esto cubre el uso indebido más común de un operador bit a bit, es decir, cuando realmente se esperaba un operador booleano.

En otras situaciones, esto puede ocurrir, por ejemplo, en el caso de la asignación, pero al redactar las recetas, debemos intentar evitar una identificación falsamente positiva, ya que, de lo contrario, las recetas se ignorarán o desactivarán. Elaboramos recetas que se corresponden con los eventos más habituales. A medida que Sensei evolucione, podríamos añadir una especificidad adicional a la función de búsqueda para cubrir más condiciones correspondientes.

En su forma actual, esta receta permitiría identificar numerosos casos de uso actuales y, lo que es más importante, el que se ha señalado en mi proyecto.

NOTA: Numerosos expertos en código han contribuido a este ejemplo y a esta crítica de receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por tu ayuda.


---


Puede instalar Sensei IntelliJ utilizando «Preferencias \ Complementos» (Mac) o «Configuración \ Complementos» (Windows) y, a continuación, simplemente busqueSensei Code».

Tenemos mucho código fuente y recetas para estos artículos de blog (incluido este) en el repositoriosensei de la cuenta GitHub de Secure Code Warrior.

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

Más información sobre Sensei


Índice

Descargar el PDF
Mostrar el recurso
¿Desea obtener más información?

Alan Richardson possède plus de vingt ans d'expérience professionnelle en informatique. Il a travaillé en tant que développeur et a occupé tous les niveaux de la hiérarchie des tests, du testeur au responsable des tests. Responsable des relations avec les développeurs chez Secure Code Warrior, il travaille directement avec les équipes, pour améliorer le développement d'un code sécurisé de qualité. Alan est l'auteur de quatre livres, dont « Dear Evil Tester » et « Java For Testers ». Alan a également créé des cours de formation en ligne pour aider les utilisateurs à apprendre les tests techniques sur le Web et Selenium WebDriver avec Java. Alan publie ses vidéos d'écriture et de formation sur SeleniumSimplified.com, EvilTester.com, JavaForTesters.com et CompendiumDev.co.uk.

Más información

Secure Code Warrior aquí para ayudar a su organización a proteger el código a lo largo de todo el ciclo de desarrollo de software y a crear una cultura en la que la ciberseguridad sea una prioridad. Tanto si es responsable de la seguridad de las aplicaciones, desarrollador, responsable de la seguridad informática o cualquier otra persona involucrada en la seguridad, podemos ayudar a su organización a reducir los riesgos asociados a un código no seguro.

Reserve una demostraciónDescargar
Compartir en:
marcas de LinkedInSocialx logotipo
Centro de recursos

Recursos para ayudarle a empezar

Más publicaciones
Centro de recursos

Recursos para ayudarle a empezar

Más publicaciones