Gotchas de Java - Operadores Bitwise vs Boolean
Gotchas de Java - Operadores Bitwise vs Boolean
> "Java Gotcha" - un patrón de error común que es fácil de implementar accidentalmente.
Un Gotcha de Java bastante sencillo en el que se puede caer accidentalmente es: utilizar un operador Bitwise en lugar de un operador de Comparación Booleana.
Por ejemplo, un simple error tipográfico puede hacer que se escriba "&" cuando en realidad se quería escribir "&&".
Una heurística común que aprendemos al revisar el código es:
> "&" o "|" cuando se utiliza en una declaración condicional probablemente no se pretende.
En esta entrada del blog, exploraremos la heurística e identificaremos las formas en que podemos identificar y solucionar este problema de codificación.
¿Cuál es el problema? Las operaciones Bitwise funcionan bien con los booleanos
El uso de operadores Bitwise con booleanos es perfectamente válido, por lo que Java no informará de un error de sintaxis.
Si construyo una prueba JUnit para explorar una tabla de verdad para ambos operadores Bitwise OR (|) y Bitwise AND (&) entonces veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Dado esto, podríamos pensar que el uso de los operadores Bitwise no es un problema.
Tabla de verdad AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
La prueba pasa, esto es Java perfectamente válido.
Tabla de verdad de OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Esta prueba también pasa, ¿por qué preferimos "&&'y "||'?
Las imágenes de la tabla de verdad se crearon con la herramienta herramienta de tabla de verdad de web.standfor.edu.
Problema: Funcionamiento en cortocircuito
El verdadero problema es la diferencia de comportamiento entre los operadores Bitwise (&, |) y Boolean (&&, ||).
Un operador booleano es un operador de cortocircuito y sólo evalúa lo necesario.
Por ejemplo
if (args != null & args.length() > 23) {
System.out.println(args);
}
En el código anterior, ambas condiciones booleanas se evaluarán, porque se ha utilizado el operador Bitwise:
- args != null
- args.length() > 23
Esto deja mi código abierto a una NullPointerException si args es null porque siempre realizaremos la comprobación de args.length, incluso cuando args es null porque ambas condiciones booleanas tienen que ser evaluadas.
Operadores booleanos Evaluación de cortocircuitos
Cuando se utiliza un &&, por ejemplo
if (args != null && args.length() > 23) {
System.out.println(args);
}
Tan pronto como sepamos que args != null se evalúa como falso, la evaluación de la expresión de la condición se detiene.
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 esto nunca ocurriría en el código de producción
Este es un error bastante fácil de cometer y no siempre es detectado por las herramientas de análisis estático.
Utilicé el siguiente Google Dork para ver si podía encontrar algún ejemplo público de este patrón:
filetype:java if "!=null & "
Esta búsqueda trajo un código de Android en el RootWindowContainer
isDocument = intent != null & intent.isDocument()
Este es el tipo de código que podría pasar una revisión de código porque a menudo usamos operadores Bitwise en las sentencias de asignación para enmascarar valores. Pero en este caso, el resultado es el mismo que el ejemplo de la sentencia if anterior. Si la intención es alguna vez nula, entonces se lanzará una NullPointerException.
Muy a menudo nos libramos de esta construcción porque solemos codificar a la defensiva y escribir código redundante. La comprobación de != null puede ser redundante en la mayoría de los casos de uso.
Este es un error cometido por los programadores en el código de producción.
No sé cómo de actuales son los resultados de la búsqueda, pero cuando ejecuté la búsqueda había resultados de vuelta con código de: Google, Amazon, Apache... y yo.
Un reciente pull request en uno de mis proyectos de código abierto fue para solucionar exactamente este error.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Cómo encontrarlo
Cuando comprobé mi código de muestra en unos cuantos analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.
Como equipo en Secure Code Warrior, creamos y revisamos una receta bastante simple de Sensei que podría recoger esto.
Dado que los operadores Bitwise son perfectamente válidos, y se utilizan a menudo en las asignaciones, nos centramos en el caso de uso de las sentencias if, y en el uso de Bitwise &, para encontrar el código problemático.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Utiliza una expresión regular para que coincida con " & " cuando se utiliza como expresión de condición, por ejemplo, en una sentencia if.
Para solucionarlo, volvimos a recurrir a las expresiones regulares. Esta vez usando la función sed en el QuickFix para reemplazar globalmente el & en la expresión con &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notas finales
Esto cubre el uso erróneo más común de un operador Bitwise, es decir, cuando se pretendía un operador Booleano.
Hay otras situaciones en las que esto podría surgir, por ejemplo, el ejemplo de la asignación, pero al escribir las recetas tenemos que intentar evitar la identificación falsa-positiva, de lo contrario las recetas serán ignoradas o desactivadas. Construimos las recetas para que coincidan con las ocurrencias más comunes. A medida que Sensei evolucione, es posible que añadamos más especificidad a la función de búsqueda para cubrir más condiciones de coincidencia.
En su forma actual, esta receta identificaría muchos de los casos de uso en vivo, y lo más importante, el que fue reportado en mi proyecto.
NOTA: Unos cuantos guerreros del código han contribuido a este ejemplo y a la revisión de la receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por su ayuda.
---
Puedes instalar Sensei desde IntelliJ usando "Preferencias \N-Plugins" (Mac) o "Ajustes \N-Plugins" (Windows) y luego sólo busca "sensei secure code"
Tenemos un montón de código fuente y recetas para estas entradas del blog (incluyendo esta) en el repositorio `sensei-blog-examples` en la cuenta de GitHub de Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples


En esta entrada del blog echamos un vistazo a un error común de codificación en Java (usar un operador bitwise en lugar de un operador condicional), el error que hace que nuestro código sea vulnerable, y cómo podemos usar Sensei para arreglar y detectar el problema.
Alan Richardson cuenta con más de veinte años de experiencia profesional en TI, trabajando como desarrollador y en todos los niveles de la jerarquía de pruebas, desde probador hasta jefe de pruebas. Jefe de Relaciones con los Desarrolladores en Secure Code Warrior, trabaja directamente con los equipos, para mejorar el desarrollo de un código seguro de calidad. Alan es autor de cuatro libros, entre ellos "Dear Evil Tester" y "Java For Testers". Alan también ha creado una formación en línea courses para ayudar a la gente a aprender las pruebas técnicas de la web y Selenium WebDriver con Java. Alan publica sus escritos y vídeos de formación en SeleniumSimplified.com, EvilTester.com, JavaForTesters.com, y CompendiumDev.co.uk.

Secure Code Warrior está a disposición de su organización para ayudarle a proteger el código a lo largo de todo el ciclo de vida de desarrollo de software y crear una cultura en la que la ciberseguridad sea una prioridad. Tanto si es director de AppSec, desarrollador, CISO o cualquier persona implicada en la seguridad, podemos ayudar a su organización a reducir los riesgos asociados a un código inseguro.
Reservar una demostraciónAlan Richardson cuenta con más de veinte años de experiencia profesional en TI, trabajando como desarrollador y en todos los niveles de la jerarquía de pruebas, desde probador hasta jefe de pruebas. Jefe de Relaciones con los Desarrolladores en Secure Code Warrior, trabaja directamente con los equipos, para mejorar el desarrollo de un código seguro de calidad. Alan es autor de cuatro libros, entre ellos "Dear Evil Tester" y "Java For Testers". Alan también ha creado una formación en línea courses para ayudar a la gente a aprender las pruebas técnicas de la web y Selenium WebDriver con Java. Alan publica sus escritos y vídeos de formación en SeleniumSimplified.com, EvilTester.com, JavaForTesters.com, y CompendiumDev.co.uk.


Gotchas de Java - Operadores Bitwise vs Boolean
> "Java Gotcha" - un patrón de error común que es fácil de implementar accidentalmente.
Un Gotcha de Java bastante sencillo en el que se puede caer accidentalmente es: utilizar un operador Bitwise en lugar de un operador de Comparación Booleana.
Por ejemplo, un simple error tipográfico puede hacer que se escriba "&" cuando en realidad se quería escribir "&&".
Una heurística común que aprendemos al revisar el código es:
> "&" o "|" cuando se utiliza en una declaración condicional probablemente no se pretende.
En esta entrada del blog, exploraremos la heurística e identificaremos las formas en que podemos identificar y solucionar este problema de codificación.
¿Cuál es el problema? Las operaciones Bitwise funcionan bien con los booleanos
El uso de operadores Bitwise con booleanos es perfectamente válido, por lo que Java no informará de un error de sintaxis.
Si construyo una prueba JUnit para explorar una tabla de verdad para ambos operadores Bitwise OR (|) y Bitwise AND (&) entonces veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Dado esto, podríamos pensar que el uso de los operadores Bitwise no es un problema.
Tabla de verdad AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
La prueba pasa, esto es Java perfectamente válido.
Tabla de verdad de OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Esta prueba también pasa, ¿por qué preferimos "&&'y "||'?
Las imágenes de la tabla de verdad se crearon con la herramienta herramienta de tabla de verdad de web.standfor.edu.
Problema: Funcionamiento en cortocircuito
El verdadero problema es la diferencia de comportamiento entre los operadores Bitwise (&, |) y Boolean (&&, ||).
Un operador booleano es un operador de cortocircuito y sólo evalúa lo necesario.
Por ejemplo
if (args != null & args.length() > 23) {
System.out.println(args);
}
En el código anterior, ambas condiciones booleanas se evaluarán, porque se ha utilizado el operador Bitwise:
- args != null
- args.length() > 23
Esto deja mi código abierto a una NullPointerException si args es null porque siempre realizaremos la comprobación de args.length, incluso cuando args es null porque ambas condiciones booleanas tienen que ser evaluadas.
Operadores booleanos Evaluación de cortocircuitos
Cuando se utiliza un &&, por ejemplo
if (args != null && args.length() > 23) {
System.out.println(args);
}
Tan pronto como sepamos que args != null se evalúa como falso, la evaluación de la expresión de la condición se detiene.
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 esto nunca ocurriría en el código de producción
Este es un error bastante fácil de cometer y no siempre es detectado por las herramientas de análisis estático.
Utilicé el siguiente Google Dork para ver si podía encontrar algún ejemplo público de este patrón:
filetype:java if "!=null & "
Esta búsqueda trajo un código de Android en el RootWindowContainer
isDocument = intent != null & intent.isDocument()
Este es el tipo de código que podría pasar una revisión de código porque a menudo usamos operadores Bitwise en las sentencias de asignación para enmascarar valores. Pero en este caso, el resultado es el mismo que el ejemplo de la sentencia if anterior. Si la intención es alguna vez nula, entonces se lanzará una NullPointerException.
Muy a menudo nos libramos de esta construcción porque solemos codificar a la defensiva y escribir código redundante. La comprobación de != null puede ser redundante en la mayoría de los casos de uso.
Este es un error cometido por los programadores en el código de producción.
No sé cómo de actuales son los resultados de la búsqueda, pero cuando ejecuté la búsqueda había resultados de vuelta con código de: Google, Amazon, Apache... y yo.
Un reciente pull request en uno de mis proyectos de código abierto fue para solucionar exactamente este error.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Cómo encontrarlo
Cuando comprobé mi código de muestra en unos cuantos analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.
Como equipo en Secure Code Warrior, creamos y revisamos una receta bastante simple de Sensei que podría recoger esto.
Dado que los operadores Bitwise son perfectamente válidos, y se utilizan a menudo en las asignaciones, nos centramos en el caso de uso de las sentencias if, y en el uso de Bitwise &, para encontrar el código problemático.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Utiliza una expresión regular para que coincida con " & " cuando se utiliza como expresión de condición, por ejemplo, en una sentencia if.
Para solucionarlo, volvimos a recurrir a las expresiones regulares. Esta vez usando la función sed en el QuickFix para reemplazar globalmente el & en la expresión con &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notas finales
Esto cubre el uso erróneo más común de un operador Bitwise, es decir, cuando se pretendía un operador Booleano.
Hay otras situaciones en las que esto podría surgir, por ejemplo, el ejemplo de la asignación, pero al escribir las recetas tenemos que intentar evitar la identificación falsa-positiva, de lo contrario las recetas serán ignoradas o desactivadas. Construimos las recetas para que coincidan con las ocurrencias más comunes. A medida que Sensei evolucione, es posible que añadamos más especificidad a la función de búsqueda para cubrir más condiciones de coincidencia.
En su forma actual, esta receta identificaría muchos de los casos de uso en vivo, y lo más importante, el que fue reportado en mi proyecto.
NOTA: Unos cuantos guerreros del código han contribuido a este ejemplo y a la revisión de la receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por su ayuda.
---
Puedes instalar Sensei desde IntelliJ usando "Preferencias \N-Plugins" (Mac) o "Ajustes \N-Plugins" (Windows) y luego sólo busca "sensei secure code"
Tenemos un montón de código fuente y recetas para estas entradas del blog (incluyendo esta) en el repositorio `sensei-blog-examples` en la cuenta de GitHub de Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples

Gotchas de Java - Operadores Bitwise vs Boolean
> "Java Gotcha" - un patrón de error común que es fácil de implementar accidentalmente.
Un Gotcha de Java bastante sencillo en el que se puede caer accidentalmente es: utilizar un operador Bitwise en lugar de un operador de Comparación Booleana.
Por ejemplo, un simple error tipográfico puede hacer que se escriba "&" cuando en realidad se quería escribir "&&".
Una heurística común que aprendemos al revisar el código es:
> "&" o "|" cuando se utiliza en una declaración condicional probablemente no se pretende.
En esta entrada del blog, exploraremos la heurística e identificaremos las formas en que podemos identificar y solucionar este problema de codificación.
¿Cuál es el problema? Las operaciones Bitwise funcionan bien con los booleanos
El uso de operadores Bitwise con booleanos es perfectamente válido, por lo que Java no informará de un error de sintaxis.
Si construyo una prueba JUnit para explorar una tabla de verdad para ambos operadores Bitwise OR (|) y Bitwise AND (&) entonces veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Dado esto, podríamos pensar que el uso de los operadores Bitwise no es un problema.
Tabla de verdad AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
La prueba pasa, esto es Java perfectamente válido.
Tabla de verdad de OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Esta prueba también pasa, ¿por qué preferimos "&&'y "||'?
Las imágenes de la tabla de verdad se crearon con la herramienta herramienta de tabla de verdad de web.standfor.edu.
Problema: Funcionamiento en cortocircuito
El verdadero problema es la diferencia de comportamiento entre los operadores Bitwise (&, |) y Boolean (&&, ||).
Un operador booleano es un operador de cortocircuito y sólo evalúa lo necesario.
Por ejemplo
if (args != null & args.length() > 23) {
System.out.println(args);
}
En el código anterior, ambas condiciones booleanas se evaluarán, porque se ha utilizado el operador Bitwise:
- args != null
- args.length() > 23
Esto deja mi código abierto a una NullPointerException si args es null porque siempre realizaremos la comprobación de args.length, incluso cuando args es null porque ambas condiciones booleanas tienen que ser evaluadas.
Operadores booleanos Evaluación de cortocircuitos
Cuando se utiliza un &&, por ejemplo
if (args != null && args.length() > 23) {
System.out.println(args);
}
Tan pronto como sepamos que args != null se evalúa como falso, la evaluación de la expresión de la condición se detiene.
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 esto nunca ocurriría en el código de producción
Este es un error bastante fácil de cometer y no siempre es detectado por las herramientas de análisis estático.
Utilicé el siguiente Google Dork para ver si podía encontrar algún ejemplo público de este patrón:
filetype:java if "!=null & "
Esta búsqueda trajo un código de Android en el RootWindowContainer
isDocument = intent != null & intent.isDocument()
Este es el tipo de código que podría pasar una revisión de código porque a menudo usamos operadores Bitwise en las sentencias de asignación para enmascarar valores. Pero en este caso, el resultado es el mismo que el ejemplo de la sentencia if anterior. Si la intención es alguna vez nula, entonces se lanzará una NullPointerException.
Muy a menudo nos libramos de esta construcción porque solemos codificar a la defensiva y escribir código redundante. La comprobación de != null puede ser redundante en la mayoría de los casos de uso.
Este es un error cometido por los programadores en el código de producción.
No sé cómo de actuales son los resultados de la búsqueda, pero cuando ejecuté la búsqueda había resultados de vuelta con código de: Google, Amazon, Apache... y yo.
Un reciente pull request en uno de mis proyectos de código abierto fue para solucionar exactamente este error.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Cómo encontrarlo
Cuando comprobé mi código de muestra en unos cuantos analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.
Como equipo en Secure Code Warrior, creamos y revisamos una receta bastante simple de Sensei que podría recoger esto.
Dado que los operadores Bitwise son perfectamente válidos, y se utilizan a menudo en las asignaciones, nos centramos en el caso de uso de las sentencias if, y en el uso de Bitwise &, para encontrar el código problemático.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Utiliza una expresión regular para que coincida con " & " cuando se utiliza como expresión de condición, por ejemplo, en una sentencia if.
Para solucionarlo, volvimos a recurrir a las expresiones regulares. Esta vez usando la función sed en el QuickFix para reemplazar globalmente el & en la expresión con &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notas finales
Esto cubre el uso erróneo más común de un operador Bitwise, es decir, cuando se pretendía un operador Booleano.
Hay otras situaciones en las que esto podría surgir, por ejemplo, el ejemplo de la asignación, pero al escribir las recetas tenemos que intentar evitar la identificación falsa-positiva, de lo contrario las recetas serán ignoradas o desactivadas. Construimos las recetas para que coincidan con las ocurrencias más comunes. A medida que Sensei evolucione, es posible que añadamos más especificidad a la función de búsqueda para cubrir más condiciones de coincidencia.
En su forma actual, esta receta identificaría muchos de los casos de uso en vivo, y lo más importante, el que fue reportado en mi proyecto.
NOTA: Unos cuantos guerreros del código han contribuido a este ejemplo y a la revisión de la receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por su ayuda.
---
Puedes instalar Sensei desde IntelliJ usando "Preferencias \N-Plugins" (Mac) o "Ajustes \N-Plugins" (Windows) y luego sólo busca "sensei secure code"
Tenemos un montón de código fuente y recetas para estas entradas del blog (incluyendo esta) en el repositorio `sensei-blog-examples` en la cuenta de GitHub de Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples

Haga clic en el siguiente enlace y descargue el PDF de este recurso.
Secure Code Warrior está a disposición de su organización para ayudarle a proteger el código a lo largo de todo el ciclo de vida de desarrollo de software y crear una cultura en la que la ciberseguridad sea una prioridad. Tanto si es director de AppSec, desarrollador, CISO o cualquier persona implicada en la seguridad, podemos ayudar a su organización a reducir los riesgos asociados a un código inseguro.
Ver el informeReservar una demostraciónAlan Richardson cuenta con más de veinte años de experiencia profesional en TI, trabajando como desarrollador y en todos los niveles de la jerarquía de pruebas, desde probador hasta jefe de pruebas. Jefe de Relaciones con los Desarrolladores en Secure Code Warrior, trabaja directamente con los equipos, para mejorar el desarrollo de un código seguro de calidad. Alan es autor de cuatro libros, entre ellos "Dear Evil Tester" y "Java For Testers". Alan también ha creado una formación en línea courses para ayudar a la gente a aprender las pruebas técnicas de la web y Selenium WebDriver con Java. Alan publica sus escritos y vídeos de formación en SeleniumSimplified.com, EvilTester.com, JavaForTesters.com, y CompendiumDev.co.uk.
Gotchas de Java - Operadores Bitwise vs Boolean
> "Java Gotcha" - un patrón de error común que es fácil de implementar accidentalmente.
Un Gotcha de Java bastante sencillo en el que se puede caer accidentalmente es: utilizar un operador Bitwise en lugar de un operador de Comparación Booleana.
Por ejemplo, un simple error tipográfico puede hacer que se escriba "&" cuando en realidad se quería escribir "&&".
Una heurística común que aprendemos al revisar el código es:
> "&" o "|" cuando se utiliza en una declaración condicional probablemente no se pretende.
En esta entrada del blog, exploraremos la heurística e identificaremos las formas en que podemos identificar y solucionar este problema de codificación.
¿Cuál es el problema? Las operaciones Bitwise funcionan bien con los booleanos
El uso de operadores Bitwise con booleanos es perfectamente válido, por lo que Java no informará de un error de sintaxis.
Si construyo una prueba JUnit para explorar una tabla de verdad para ambos operadores Bitwise OR (|) y Bitwise AND (&) entonces veremos que las salidas del operador Bitwise coinciden con la tabla de verdad. Dado esto, podríamos pensar que el uso de los operadores Bitwise no es un problema.
Tabla de verdad AND

@Test
void bitwiseOperatorsAndTruthTable(){
Assertions.assertEquals(true, true & true);
Assertions.assertEquals(false, true & false);
Assertions.assertEquals(false, false & true);
Assertions.assertEquals(false, false & false);
}
La prueba pasa, esto es Java perfectamente válido.
Tabla de verdad de OR

@Test
void bitwiseOperatorsOrTruthTable(){
Assertions.assertEquals(true, true | true);
Assertions.assertEquals(true, true | false);
Assertions.assertEquals(true, false | true);
Assertions.assertEquals(false, false | false);
}
Esta prueba también pasa, ¿por qué preferimos "&&'y "||'?
Las imágenes de la tabla de verdad se crearon con la herramienta herramienta de tabla de verdad de web.standfor.edu.
Problema: Funcionamiento en cortocircuito
El verdadero problema es la diferencia de comportamiento entre los operadores Bitwise (&, |) y Boolean (&&, ||).
Un operador booleano es un operador de cortocircuito y sólo evalúa lo necesario.
Por ejemplo
if (args != null & args.length() > 23) {
System.out.println(args);
}
En el código anterior, ambas condiciones booleanas se evaluarán, porque se ha utilizado el operador Bitwise:
- args != null
- args.length() > 23
Esto deja mi código abierto a una NullPointerException si args es null porque siempre realizaremos la comprobación de args.length, incluso cuando args es null porque ambas condiciones booleanas tienen que ser evaluadas.
Operadores booleanos Evaluación de cortocircuitos
Cuando se utiliza un &&, por ejemplo
if (args != null && args.length() > 23) {
System.out.println(args);
}
Tan pronto como sepamos que args != null se evalúa como falso, la evaluación de la expresión de la condición se detiene.
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 esto nunca ocurriría en el código de producción
Este es un error bastante fácil de cometer y no siempre es detectado por las herramientas de análisis estático.
Utilicé el siguiente Google Dork para ver si podía encontrar algún ejemplo público de este patrón:
filetype:java if "!=null & "
Esta búsqueda trajo un código de Android en el RootWindowContainer
isDocument = intent != null & intent.isDocument()
Este es el tipo de código que podría pasar una revisión de código porque a menudo usamos operadores Bitwise en las sentencias de asignación para enmascarar valores. Pero en este caso, el resultado es el mismo que el ejemplo de la sentencia if anterior. Si la intención es alguna vez nula, entonces se lanzará una NullPointerException.
Muy a menudo nos libramos de esta construcción porque solemos codificar a la defensiva y escribir código redundante. La comprobación de != null puede ser redundante en la mayoría de los casos de uso.
Este es un error cometido por los programadores en el código de producción.
No sé cómo de actuales son los resultados de la búsqueda, pero cuando ejecuté la búsqueda había resultados de vuelta con código de: Google, Amazon, Apache... y yo.
Un reciente pull request en uno de mis proyectos de código abierto fue para solucionar exactamente este error.
if(type!=null & type.trim().length()>0){
acceptMediaTypeDefinitionsList.add(type.trim());
}
Cómo encontrarlo
Cuando comprobé mi código de muestra en unos cuantos analizadores estáticos, ninguno de ellos detectó este código de autodestrucción oculto.
Como equipo en Secure Code Warrior, creamos y revisamos una receta bastante simple de Sensei que podría recoger esto.
Dado que los operadores Bitwise son perfectamente válidos, y se utilizan a menudo en las asignaciones, nos centramos en el caso de uso de las sentencias if, y en el uso de Bitwise &, para encontrar el código problemático.
search:
expression:
anyOf:
- in:
condition: {}
value:
caseSensitive: false
matches: ".* & .*"
Utiliza una expresión regular para que coincida con " & " cuando se utiliza como expresión de condición, por ejemplo, en una sentencia if.
Para solucionarlo, volvimos a recurrir a las expresiones regulares. Esta vez usando la función sed en el QuickFix para reemplazar globalmente el & en la expresión con &&.
availableFixes:
- name: "Replace bitwise AND operator to logical AND operator"
actions:
- rewrite:
to: "{{#sed}}s/&/&&/g,{{{ . }}}{{/sed}}"
Notas finales
Esto cubre el uso erróneo más común de un operador Bitwise, es decir, cuando se pretendía un operador Booleano.
Hay otras situaciones en las que esto podría surgir, por ejemplo, el ejemplo de la asignación, pero al escribir las recetas tenemos que intentar evitar la identificación falsa-positiva, de lo contrario las recetas serán ignoradas o desactivadas. Construimos las recetas para que coincidan con las ocurrencias más comunes. A medida que Sensei evolucione, es posible que añadamos más especificidad a la función de búsqueda para cubrir más condiciones de coincidencia.
En su forma actual, esta receta identificaría muchos de los casos de uso en vivo, y lo más importante, el que fue reportado en mi proyecto.
NOTA: Unos cuantos guerreros del código han contribuido a este ejemplo y a la revisión de la receta: Charlie Eriksen, Matthieu Calie, Robin Claerhaut, Brysen Ackx, Nathan Desmet, Downey Robersscheuten. Gracias por su ayuda.
---
Puedes instalar Sensei desde IntelliJ usando "Preferencias \N-Plugins" (Mac) o "Ajustes \N-Plugins" (Windows) y luego sólo busca "sensei secure code"
Tenemos un montón de código fuente y recetas para estas entradas del blog (incluyendo esta) en el repositorio `sensei-blog-examples` en la cuenta de GitHub de Secure Code Warrior .
https://github.com/securecodewarrior/sensei-blog-examples
Índice
Alan Richardson cuenta con más de veinte años de experiencia profesional en TI, trabajando como desarrollador y en todos los niveles de la jerarquía de pruebas, desde probador hasta jefe de pruebas. Jefe de Relaciones con los Desarrolladores en Secure Code Warrior, trabaja directamente con los equipos, para mejorar el desarrollo de un código seguro de calidad. Alan es autor de cuatro libros, entre ellos "Dear Evil Tester" y "Java For Testers". Alan también ha creado una formación en línea courses para ayudar a la gente a aprender las pruebas técnicas de la web y Selenium WebDriver con Java. Alan publica sus escritos y vídeos de formación en SeleniumSimplified.com, EvilTester.com, JavaForTesters.com, y CompendiumDev.co.uk.

Secure Code Warrior está a disposición de su organización para ayudarle a proteger el código a lo largo de todo el ciclo de vida de desarrollo de software y crear una cultura en la que la ciberseguridad sea una prioridad. Tanto si es director de AppSec, desarrollador, CISO o cualquier persona implicada en la seguridad, podemos ayudar a su organización a reducir los riesgos asociados a un código inseguro.
Reservar una demostraciónDescargarRecursos para empezar
Panorama de la gestión de riesgos de los promotores
La gestión de riesgos del desarrollador es un enfoque holístico y proactivo de la seguridad de las aplicaciones, centrado en quienes contribuyen al código y no en los bits y bytes de la propia capa de la aplicación.
Seguridad desde el diseño: Definición de las mejores prácticas, capacitación de los desarrolladores y evaluación comparativa de los resultados de la seguridad preventiva
En este documento de investigación, los cofundadores Secure Code Warrior , Pieter Danhieux y el Dr. Matias Madou, Ph.D., junto con los expertos colaboradores, Chris Inglis, ex Director Nacional Cibernético de EE.UU. (ahora Asesor Estratégico de Paladin Capital Group), y Devin Lynch, Director Senior, Paladin Global Institute, revelarán los hallazgos clave de más de veinte entrevistas en profundidad con líderes de seguridad empresarial, incluyendo CISOs, un VP de Seguridad de Aplicaciones y profesionales de seguridad de software.
Evaluación comparativa de las competencias en materia de seguridad: optimización del diseño seguro en la empresa
Encontrar datos significativos sobre el éxito de las iniciativas Secure-by-Design es notoriamente difícil. Los responsables de la seguridad de la información se enfrentan a menudo al reto de demostrar el rendimiento de la inversión (ROI) y el valor empresarial de las actividades de los programas de seguridad, tanto a nivel de las personas como de la empresa. Por no mencionar que a las empresas les resulta especialmente difícil obtener información sobre cómo se comparan sus organizaciones con los estándares actuales del sector. La Estrategia Nacional de Ciberseguridad del Presidente desafió a las partes interesadas a "adoptar la seguridad y la resiliencia desde el diseño". La clave para que las iniciativas de seguridad por diseño funcionen no es sólo dotar a los desarrolladores de las habilidades necesarias para garantizar un código seguro, sino también garantizar a los reguladores que esas habilidades están en su lugar. En esta presentación, compartimos una miríada de datos cualitativos y cuantitativos, derivados de múltiples fuentes primarias, incluidos puntos de datos internos recogidos de más de 250.000 desarrolladores, opiniones de clientes basadas en datos y estudios públicos. Aprovechando esta agregación de puntos de datos, pretendemos comunicar una visión del estado actual de las iniciativas Secure-by-Design en múltiples verticales. El informe detalla por qué este espacio está actualmente infrautilizado, el impacto significativo que un programa de mejora de las competencias puede tener en la mitigación de los riesgos de ciberseguridad y el potencial para eliminar categorías de vulnerabilidades de un código base.
Servicios profesionales - Acelerar con experiencia
El equipo de servicios de estrategia de programas (PSS) de Secure Code Warriorle ayuda a crear, mejorar y optimizar su programa de codificación segura. Tanto si empieza de cero como si está perfeccionando su enfoque, nuestros expertos le proporcionarán orientación personalizada.
Recursos para empezar
Revelado: Cómo define el sector cibernético la seguridad por diseño
En nuestro último libro blanco, nuestros cofundadores, Pieter Danhieux y el doctor Matias Madou, se sentaron con más de veinte líderes de seguridad empresarial, incluidos CISO, líderes de AppSec y profesionales de la seguridad, para averiguar las piezas clave de este rompecabezas y descubrir la realidad detrás del movimiento Secure by Design. Se trata de una ambición compartida por todos los equipos de seguridad, pero no de un libro de jugadas compartido.
¿Vibe Coding va a convertir tu código en una fiesta de fraternidad?
Vibe Coding es como una fiesta de fraternidad universitaria, y la IA es la pieza central de todos los festejos, el barril. Es muy divertido dar rienda suelta a la creatividad y ver adónde te lleva tu imaginación, pero después de unas cuantas borracheras, beber (o usar IA) con moderación es, sin duda, la solución más segura a largo plazo.