Iconos SCW
héroe bg sin separador
Blog

Problema de Java: operadores bit a bit y operadores booleanos

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

Problema de Java: operadores bit a bit y operadores booleanos

«Java Gotcha»: es un patrón de errores comunes que se cometen fácilmente por descuido.

Uno de los errores más sencillos que se pueden cometer en Java es utilizar operadores bit a bit en lugar de operadores de comparación booleanos.

Por ejemplo, cuando realmente se quiere escribir «&&», es posible que, debido a un simple error tipográfico, se escriba «&».

Las heurísticas que se suelen aprender al revisar el código son las siguientes.

El uso de «&» o «|» en una condición puede no ser intencionado.

En esta entrada del blog, analizaremos la heurística y veremos cómo identificar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones bit a bit funcionan bien con booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido, por lo que Java no informa de ningún error sintáctico.

Si se configura una prueba JUnit para explorar las tablas de verdad tanto para OR bit a bit (|) como para AND bit a bit (&), se puede ver que la salida del operador bit a bit coincide con la tabla de verdad. Teniendo esto en cuenta, se podría pensar que el uso del operador bit a bit no supone ningún problema.

Y tabla de verdad

Tres columnas una con a, otra con b, y la última con (a^b)


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


Ha superado la prueba. Se trata de Java perfectamente válido.


OR tabla de verdad


Tres columnas sobre con a, una con b, y la última con (a v b)


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


Si también ha superado esta prueba, ¿por qué prefiere «&&» y «||»?


La imagen de la tabla de verdad se ha creado utilizando lo siguiente. Herramienta de tabla de verdad ... en web.standfor.edu.


Problema: funcionamiento del cortocircuito


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

El operador booleano es un operador de cortocircuito y solo evalúa lo necesario.

예:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


En este código se utiliza el operador bit a bit, por lo que se evalúan ambas condiciones booleanas.

  • ¡Adquisición! = Cero
  • Adquisición. Longitud () > 23

De esta manera, si el argumento es nulo, mi código se abre con NullPointerException. Esto se debe a que, dado que hay que evaluar ambas condiciones booleanas, siempre se realiza la comprobación de args.length, incluso si el argumento es nulo.


Evaluación de cortocircuitos de operadores booleanos


Cuando se utiliza &&, por ejemplo:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


¡Tan pronto como nos enteramos de esa adquisición! Si null se evalúa como falso, se detiene la evaluación de la expresión condicional.

No es necesario evaluar la derecha.

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


Sin embargo, en el código de producción esto nunca sucederá.


Este es un error muy fácil de cometer y no siempre se puede detectar con herramientas de análisis estático.

Se ha comprobado si se pueden encontrar casos públicos de este patrón utilizando Google Dork.

Formato de archivo: «! en caso de Java=null &»
Esta búsqueda ha traído parte del código de Android al contenedor raíz de Windows.
ISDocument = Intent!= null & Intent.isDocument ()


En la entrada, se suelen utilizar operadores binarios para enmascarar valores, por lo que se trata de un tipo de código que puede superar la revisión del código. Sin embargo, en este caso, el resultado es el mismo que en el ejemplo anterior de la instrucción if. Si la intención es siempre nula, se produce una excepción NullPointerException.

A menudo no utilizamos esta sintaxis porque programamos de forma defensiva y escribimos código duplicado. ¡Compruébelo! = null puede duplicarse en la mayoría de los casos de uso.

Este es un error cometido por el programador en el código de producción.

No sé cuán actualizados están los resultados de búsqueda, pero cuando realicé la búsqueda, aparecieron resultados de Google, Amazon, Apache... y mi código.

Recientemente, tuve que resolver exactamente este error en uno de mis proyectos de código abierto de Pull Request.

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


Cómo encontrar esto


Cuando se verificó el código de muestra en varios analizadores estáticos, ninguno detectó este código oculto de autodestrucción.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta muy sencilla de Sensei para resolver este problema.

Los operadores bit a bit son perfectamente válidos y se utilizan con frecuencia en las asignaciones, por lo que nos hemos centrado en los casos de uso de las sentencias if y en la búsqueda de código problemático utilizando el operador bit a bit &.

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


Esto coincide con «&» cuando se utiliza como expresión condicional con expresiones regulares (por ejemplo, en una sentencia if).

Para resolver este problema, volvimos a utilizar expresiones regulares. Esta vez, utilizamos la función sed de QuickFix para sustituir globalmente el símbolo & por && en la expresión.

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


Nota final

Aquí se trata del uso incorrecto más común del operador bit, es decir, cuando en realidad se pretende utilizar el operador booleano.

Por ejemplo, pueden darse otras situaciones, como ejemplos de admisión, pero al crear recetas hay que evitar la identificación de falsos positivos. De lo contrario, la receta se ignorará o se desactivará. Creamos recetas que se ajustan a las situaciones más frecuentes. A medida que Sensei evolucione, añadiremos funciones específicas a la búsqueda para abarcar más condiciones de coincidencia.

En su forma actual, esta receta permite identificar muchos casos de uso reales. Lo más importante es lo que se ha informado en mi proyecto.

Nota: Charlie Eriksen, Mathieu Calley, Robin Clairhaut, Bryson Ax, Nathan Desmet, Downey Robershoten y otros guerreros del código han contribuido a este ejemplo y a la revisión de la receta. Gracias por su ayuda.


---


Solo tienes que instalar Sensei en IntelliJ usando «Preferencias\Complementos» (Mac) o «Configuración\Complementos» (Windows) y buscar el «código de seguridad Sensei».

El repositorio `sensei` de Secure Code Warrior contiene gran cantidad de código fuente y recetas para estas entradas del blog (incluida esta).

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

Más información sobre Sensei


Ver recursos
Ver recursos

En esta entrada del blog, veremos los errores comunes en la programación Java (como usar operadores bit a bit en lugar de operadores condicionales), los errores que hacen que el código sea vulnerable y cómo usar Sensei para resolver y detectar estos problemas.

¿Le interesa saber más?

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.

Más información

Secure Code Warrior está aquí para ayudar a las organizaciones a proteger el código durante todo el ciclo de vida del desarrollo de software y a crear una cultura que priorice la ciberseguridad. Ya seas administrador de AppSec, desarrollador, CISO o cualquier persona relacionada con la seguridad, podemos ayudarte a reducir los riesgos asociados al código inseguro en tu organización.

Reserva de demostración
Destinatarios:
marcas de LinkedInSocialx logotipo
Autor
Alan Richardson
Publicado el 07 de febrero de 2021

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.

Destinatarios:
marcas de LinkedInSocialx logotipo

Problema de Java: operadores bit a bit y operadores booleanos

«Java Gotcha»: es un patrón de errores comunes que se cometen fácilmente por descuido.

Uno de los errores más sencillos que se pueden cometer en Java es utilizar operadores bit a bit en lugar de operadores de comparación booleanos.

Por ejemplo, cuando realmente se quiere escribir «&&», es posible que, debido a un simple error tipográfico, se escriba «&».

Las heurísticas que se suelen aprender al revisar el código son las siguientes.

El uso de «&» o «|» en una condición puede no ser intencionado.

En esta entrada del blog, analizaremos la heurística y veremos cómo identificar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones bit a bit funcionan bien con booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido, por lo que Java no informa de ningún error sintáctico.

Si se configura una prueba JUnit para explorar las tablas de verdad tanto para OR bit a bit (|) como para AND bit a bit (&), se puede ver que la salida del operador bit a bit coincide con la tabla de verdad. Teniendo esto en cuenta, se podría pensar que el uso del operador bit a bit no supone ningún problema.

Y tabla de verdad

Tres columnas una con a, otra con b, y la última con (a^b)


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


Ha superado la prueba. Se trata de Java perfectamente válido.


OR tabla de verdad


Tres columnas sobre con a, una con b, y la última con (a v b)


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


Si también ha superado esta prueba, ¿por qué prefiere «&&» y «||»?


La imagen de la tabla de verdad se ha creado utilizando lo siguiente. Herramienta de tabla de verdad ... en web.standfor.edu.


Problema: funcionamiento del cortocircuito


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

El operador booleano es un operador de cortocircuito y solo evalúa lo necesario.

예:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


En este código se utiliza el operador bit a bit, por lo que se evalúan ambas condiciones booleanas.

  • ¡Adquisición! = Cero
  • Adquisición. Longitud () > 23

De esta manera, si el argumento es nulo, mi código se abre con NullPointerException. Esto se debe a que, dado que hay que evaluar ambas condiciones booleanas, siempre se realiza la comprobación de args.length, incluso si el argumento es nulo.


Evaluación de cortocircuitos de operadores booleanos


Cuando se utiliza &&, por ejemplo:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


¡Tan pronto como nos enteramos de esa adquisición! Si null se evalúa como falso, se detiene la evaluación de la expresión condicional.

No es necesario evaluar la derecha.

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


Sin embargo, en el código de producción esto nunca sucederá.


Este es un error muy fácil de cometer y no siempre se puede detectar con herramientas de análisis estático.

Se ha comprobado si se pueden encontrar casos públicos de este patrón utilizando Google Dork.

Formato de archivo: «! en caso de Java=null &»
Esta búsqueda ha traído parte del código de Android al contenedor raíz de Windows.
ISDocument = Intent!= null & Intent.isDocument ()


En la entrada, se suelen utilizar operadores binarios para enmascarar valores, por lo que se trata de un tipo de código que puede superar la revisión del código. Sin embargo, en este caso, el resultado es el mismo que en el ejemplo anterior de la instrucción if. Si la intención es siempre nula, se produce una excepción NullPointerException.

A menudo no utilizamos esta sintaxis porque programamos de forma defensiva y escribimos código duplicado. ¡Compruébelo! = null puede duplicarse en la mayoría de los casos de uso.

Este es un error cometido por el programador en el código de producción.

No sé cuán actualizados están los resultados de búsqueda, pero cuando realicé la búsqueda, aparecieron resultados de Google, Amazon, Apache... y mi código.

Recientemente, tuve que resolver exactamente este error en uno de mis proyectos de código abierto de Pull Request.

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


Cómo encontrar esto


Cuando se verificó el código de muestra en varios analizadores estáticos, ninguno detectó este código oculto de autodestrucción.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta muy sencilla de Sensei para resolver este problema.

Los operadores bit a bit son perfectamente válidos y se utilizan con frecuencia en las asignaciones, por lo que nos hemos centrado en los casos de uso de las sentencias if y en la búsqueda de código problemático utilizando el operador bit a bit &.

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


Esto coincide con «&» cuando se utiliza como expresión condicional con expresiones regulares (por ejemplo, en una sentencia if).

Para resolver este problema, volvimos a utilizar expresiones regulares. Esta vez, utilizamos la función sed de QuickFix para sustituir globalmente el símbolo & por && en la expresión.

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


Nota final

Aquí se trata del uso incorrecto más común del operador bit, es decir, cuando en realidad se pretende utilizar el operador booleano.

Por ejemplo, pueden darse otras situaciones, como ejemplos de admisión, pero al crear recetas hay que evitar la identificación de falsos positivos. De lo contrario, la receta se ignorará o se desactivará. Creamos recetas que se ajustan a las situaciones más frecuentes. A medida que Sensei evolucione, añadiremos funciones específicas a la búsqueda para abarcar más condiciones de coincidencia.

En su forma actual, esta receta permite identificar muchos casos de uso reales. Lo más importante es lo que se ha informado en mi proyecto.

Nota: Charlie Eriksen, Mathieu Calley, Robin Clairhaut, Bryson Ax, Nathan Desmet, Downey Robershoten y otros guerreros del código han contribuido a este ejemplo y a la revisión de la receta. Gracias por su ayuda.


---


Solo tienes que instalar Sensei en IntelliJ usando «Preferencias\Complementos» (Mac) o «Configuración\Complementos» (Windows) y buscar el «código de seguridad Sensei».

El repositorio `sensei` de Secure Code Warrior contiene gran cantidad de código fuente y recetas para estas entradas del blog (incluida esta).

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

Más información sobre Sensei


Ver recursos
Ver recursos

Para descargar el informe, rellene el siguiente formulario.

Solicitamos su consentimiento para enviarle información sobre nuestros productos y/o temas relacionados con la codificación de seguridad. Siempre tratamos su información personal con el máximo cuidado y nunca la vendemos a otras empresas con fines de marketing.

Enviar
Icono de éxito de SCW
Icono de error scw
Para enviar el formulario, active la cookie «Analytics». Una vez completado, puede desactivarla en cualquier momento.

Problema de Java: operadores bit a bit y operadores booleanos

«Java Gotcha»: es un patrón de errores comunes que se cometen fácilmente por descuido.

Uno de los errores más sencillos que se pueden cometer en Java es utilizar operadores bit a bit en lugar de operadores de comparación booleanos.

Por ejemplo, cuando realmente se quiere escribir «&&», es posible que, debido a un simple error tipográfico, se escriba «&».

Las heurísticas que se suelen aprender al revisar el código son las siguientes.

El uso de «&» o «|» en una condición puede no ser intencionado.

En esta entrada del blog, analizaremos la heurística y veremos cómo identificar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones bit a bit funcionan bien con booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido, por lo que Java no informa de ningún error sintáctico.

Si se configura una prueba JUnit para explorar las tablas de verdad tanto para OR bit a bit (|) como para AND bit a bit (&), se puede ver que la salida del operador bit a bit coincide con la tabla de verdad. Teniendo esto en cuenta, se podría pensar que el uso del operador bit a bit no supone ningún problema.

Y tabla de verdad

Tres columnas una con a, otra con b, y la última con (a^b)


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


Ha superado la prueba. Se trata de Java perfectamente válido.


OR tabla de verdad


Tres columnas sobre con a, una con b, y la última con (a v b)


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


Si también ha superado esta prueba, ¿por qué prefiere «&&» y «||»?


La imagen de la tabla de verdad se ha creado utilizando lo siguiente. Herramienta de tabla de verdad ... en web.standfor.edu.


Problema: funcionamiento del cortocircuito


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

El operador booleano es un operador de cortocircuito y solo evalúa lo necesario.

예:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


En este código se utiliza el operador bit a bit, por lo que se evalúan ambas condiciones booleanas.

  • ¡Adquisición! = Cero
  • Adquisición. Longitud () > 23

De esta manera, si el argumento es nulo, mi código se abre con NullPointerException. Esto se debe a que, dado que hay que evaluar ambas condiciones booleanas, siempre se realiza la comprobación de args.length, incluso si el argumento es nulo.


Evaluación de cortocircuitos de operadores booleanos


Cuando se utiliza &&, por ejemplo:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


¡Tan pronto como nos enteramos de esa adquisición! Si null se evalúa como falso, se detiene la evaluación de la expresión condicional.

No es necesario evaluar la derecha.

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


Sin embargo, en el código de producción esto nunca sucederá.


Este es un error muy fácil de cometer y no siempre se puede detectar con herramientas de análisis estático.

Se ha comprobado si se pueden encontrar casos públicos de este patrón utilizando Google Dork.

Formato de archivo: «! en caso de Java=null &»
Esta búsqueda ha traído parte del código de Android al contenedor raíz de Windows.
ISDocument = Intent!= null & Intent.isDocument ()


En la entrada, se suelen utilizar operadores binarios para enmascarar valores, por lo que se trata de un tipo de código que puede superar la revisión del código. Sin embargo, en este caso, el resultado es el mismo que en el ejemplo anterior de la instrucción if. Si la intención es siempre nula, se produce una excepción NullPointerException.

A menudo no utilizamos esta sintaxis porque programamos de forma defensiva y escribimos código duplicado. ¡Compruébelo! = null puede duplicarse en la mayoría de los casos de uso.

Este es un error cometido por el programador en el código de producción.

No sé cuán actualizados están los resultados de búsqueda, pero cuando realicé la búsqueda, aparecieron resultados de Google, Amazon, Apache... y mi código.

Recientemente, tuve que resolver exactamente este error en uno de mis proyectos de código abierto de Pull Request.

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


Cómo encontrar esto


Cuando se verificó el código de muestra en varios analizadores estáticos, ninguno detectó este código oculto de autodestrucción.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta muy sencilla de Sensei para resolver este problema.

Los operadores bit a bit son perfectamente válidos y se utilizan con frecuencia en las asignaciones, por lo que nos hemos centrado en los casos de uso de las sentencias if y en la búsqueda de código problemático utilizando el operador bit a bit &.

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


Esto coincide con «&» cuando se utiliza como expresión condicional con expresiones regulares (por ejemplo, en una sentencia if).

Para resolver este problema, volvimos a utilizar expresiones regulares. Esta vez, utilizamos la función sed de QuickFix para sustituir globalmente el símbolo & por && en la expresión.

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


Nota final

Aquí se trata del uso incorrecto más común del operador bit, es decir, cuando en realidad se pretende utilizar el operador booleano.

Por ejemplo, pueden darse otras situaciones, como ejemplos de admisión, pero al crear recetas hay que evitar la identificación de falsos positivos. De lo contrario, la receta se ignorará o se desactivará. Creamos recetas que se ajustan a las situaciones más frecuentes. A medida que Sensei evolucione, añadiremos funciones específicas a la búsqueda para abarcar más condiciones de coincidencia.

En su forma actual, esta receta permite identificar muchos casos de uso reales. Lo más importante es lo que se ha informado en mi proyecto.

Nota: Charlie Eriksen, Mathieu Calley, Robin Clairhaut, Bryson Ax, Nathan Desmet, Downey Robershoten y otros guerreros del código han contribuido a este ejemplo y a la revisión de la receta. Gracias por su ayuda.


---


Solo tienes que instalar Sensei en IntelliJ usando «Preferencias\Complementos» (Mac) o «Configuración\Complementos» (Windows) y buscar el «código de seguridad Sensei».

El repositorio `sensei` de Secure Code Warrior contiene gran cantidad de código fuente y recetas para estas entradas del blog (incluida esta).

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

Más información sobre Sensei


Ver seminario web
Empezar
Más información

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

Secure Code Warrior está aquí para ayudar a las organizaciones a proteger el código durante todo el ciclo de vida del desarrollo de software y a crear una cultura que priorice la ciberseguridad. Ya seas administrador de AppSec, desarrollador, CISO o cualquier persona relacionada con la seguridad, podemos ayudarte a reducir los riesgos asociados al código inseguro en tu organización.

Ver informeReserva de demostración
Ver recursos
Destinatarios:
marcas de LinkedInSocialx logotipo
¿Le interesa saber más?

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

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.

Destinatarios:
marcas de LinkedInSocialx logotipo

Problema de Java: operadores bit a bit y operadores booleanos

«Java Gotcha»: es un patrón de errores comunes que se cometen fácilmente por descuido.

Uno de los errores más sencillos que se pueden cometer en Java es utilizar operadores bit a bit en lugar de operadores de comparación booleanos.

Por ejemplo, cuando realmente se quiere escribir «&&», es posible que, debido a un simple error tipográfico, se escriba «&».

Las heurísticas que se suelen aprender al revisar el código son las siguientes.

El uso de «&» o «|» en una condición puede no ser intencionado.

En esta entrada del blog, analizaremos la heurística y veremos cómo identificar y resolver este problema de codificación.


¿Cuál es el problema? Las operaciones bit a bit funcionan bien con booleanos.


El uso de operadores bit a bit con valores booleanos es perfectamente válido, por lo que Java no informa de ningún error sintáctico.

Si se configura una prueba JUnit para explorar las tablas de verdad tanto para OR bit a bit (|) como para AND bit a bit (&), se puede ver que la salida del operador bit a bit coincide con la tabla de verdad. Teniendo esto en cuenta, se podría pensar que el uso del operador bit a bit no supone ningún problema.

Y tabla de verdad

Tres columnas una con a, otra con b, y la última con (a^b)


@Test
무효 비트 연산자 및 진실 테이블 () {
어설션. 같음 어설션 (참, 참, 참);
어설션. 같음 어설션 (거짓, 참, 거짓);
어설션. 같음 어설션 (거짓, 거짓, 참);
어설션. 같음 어설션 (거짓, 거짓, 거짓);
}


Ha superado la prueba. Se trata de Java perfectamente válido.


OR tabla de verdad


Tres columnas sobre con a, una con b, y la última con (a v b)


@Test
무효 비트 연산자 또는 진실 테이블 () {
어설션. 어설션 같음 (참, 참 | 참);
어설션. 어설션 같음 (참, 참 | 거짓);
어설션. 같음 어설션 (참, 거짓 | 참);
어설션. 같음 어설션 (거짓, 거짓 | 거짓);
}


Si también ha superado esta prueba, ¿por qué prefiere «&&» y «||»?


La imagen de la tabla de verdad se ha creado utilizando lo siguiente. Herramienta de tabla de verdad ... en web.standfor.edu.


Problema: funcionamiento del cortocircuito


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

El operador booleano es un operador de cortocircuito y solo evalúa lo necesario.

예:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


En este código se utiliza el operador bit a bit, por lo que se evalúan ambas condiciones booleanas.

  • ¡Adquisición! = Cero
  • Adquisición. Longitud () > 23

De esta manera, si el argumento es nulo, mi código se abre con NullPointerException. Esto se debe a que, dado que hay que evaluar ambas condiciones booleanas, siempre se realiza la comprobación de args.length, incluso si el argumento es nulo.


Evaluación de cortocircuitos de operadores booleanos


Cuando se utiliza &&, por ejemplo:

만약 (격언!= null 및 인수. 길이 () > 23) {
시스템.out.printLN (args);
}


¡Tan pronto como nos enteramos de esa adquisición! Si null se evalúa como falso, se detiene la evaluación de la expresión condicional.

No es necesario evaluar la derecha.

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


Sin embargo, en el código de producción esto nunca sucederá.


Este es un error muy fácil de cometer y no siempre se puede detectar con herramientas de análisis estático.

Se ha comprobado si se pueden encontrar casos públicos de este patrón utilizando Google Dork.

Formato de archivo: «! en caso de Java=null &»
Esta búsqueda ha traído parte del código de Android al contenedor raíz de Windows.
ISDocument = Intent!= null & Intent.isDocument ()


En la entrada, se suelen utilizar operadores binarios para enmascarar valores, por lo que se trata de un tipo de código que puede superar la revisión del código. Sin embargo, en este caso, el resultado es el mismo que en el ejemplo anterior de la instrucción if. Si la intención es siempre nula, se produce una excepción NullPointerException.

A menudo no utilizamos esta sintaxis porque programamos de forma defensiva y escribimos código duplicado. ¡Compruébelo! = null puede duplicarse en la mayoría de los casos de uso.

Este es un error cometido por el programador en el código de producción.

No sé cuán actualizados están los resultados de búsqueda, pero cuando realicé la búsqueda, aparecieron resultados de Google, Amazon, Apache... y mi código.

Recientemente, tuve que resolver exactamente este error en uno de mis proyectos de código abierto de Pull Request.

만약 (입력!=null 및 type.trim (). 길이 () >0) {
미디어 유형 정의 목록을 승인합니다. 추가 (type.trim ());
}


Cómo encontrar esto


Cuando se verificó el código de muestra en varios analizadores estáticos, ninguno detectó este código oculto de autodestrucción.

Como equipo de Secure Code Warrior, hemos creado y revisado una receta muy sencilla de Sensei para resolver este problema.

Los operadores bit a bit son perfectamente válidos y se utilizan con frecuencia en las asignaciones, por lo que nos hemos centrado en los casos de uso de las sentencias if y en la búsqueda de código problemático utilizando el operador bit a bit &.

검색:
표현식:
다음 중 하나:
- 입력:
조건: {}
값:
대소문자 구분: 거짓
일치: “.* &.*”


Esto coincide con «&» cuando se utiliza como expresión condicional con expresiones regulares (por ejemplo, en una sentencia if).

Para resolver este problema, volvimos a utilizar expresiones regulares. Esta vez, utilizamos la función sed de QuickFix para sustituir globalmente el símbolo & por && en la expresión.

사용 가능한 수정 사항:
- 이름: “비트 AND 연산자를 논리 AND 연산자로 바꾸기”
조치:
- 다시 작성:
받는 사람: “{{#sed}} s/&/&/g, {{{.}}} {{/sed}}”


Nota final

Aquí se trata del uso incorrecto más común del operador bit, es decir, cuando en realidad se pretende utilizar el operador booleano.

Por ejemplo, pueden darse otras situaciones, como ejemplos de admisión, pero al crear recetas hay que evitar la identificación de falsos positivos. De lo contrario, la receta se ignorará o se desactivará. Creamos recetas que se ajustan a las situaciones más frecuentes. A medida que Sensei evolucione, añadiremos funciones específicas a la búsqueda para abarcar más condiciones de coincidencia.

En su forma actual, esta receta permite identificar muchos casos de uso reales. Lo más importante es lo que se ha informado en mi proyecto.

Nota: Charlie Eriksen, Mathieu Calley, Robin Clairhaut, Bryson Ax, Nathan Desmet, Downey Robershoten y otros guerreros del código han contribuido a este ejemplo y a la revisión de la receta. Gracias por su ayuda.


---


Solo tienes que instalar Sensei en IntelliJ usando «Preferencias\Complementos» (Mac) o «Configuración\Complementos» (Windows) y buscar el «código de seguridad Sensei».

El repositorio `sensei` de Secure Code Warrior contiene gran cantidad de código fuente y recetas para estas entradas del blog (incluida esta).

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

Más información sobre Sensei


Índice

Descargar PDF
Ver recursos
¿Le interesa saber más?

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.

Más información

Secure Code Warrior está aquí para ayudar a las organizaciones a proteger el código durante todo el ciclo de vida del desarrollo de software y a crear una cultura que priorice la ciberseguridad. Ya seas administrador de AppSec, desarrollador, CISO o cualquier persona relacionada con la seguridad, podemos ayudarte a reducir los riesgos asociados al código inseguro en tu organización.

Reserva de demostraciónDescargar
Destinatarios:
marcas de LinkedInSocialx logotipo
Centro de recursos

Recursos útiles para empezar

Más publicaciones
Centro de recursos

Recursos útiles para empezar

Más publicaciones