reconoce raros programacion pone ejemplos como caracteres agregar java unicode comments

raros - ¿Por qué se permite ejecutar código Java en comentarios con ciertos caracteres Unicode permitidos?



programacion en java pdf (8)

El siguiente código produce el resultado "¡Hola, mundo!" (No realmente, pruébalo).

public static void main(String... args) { // The comment below is not a typo. // /u000d System.out.println("Hello World!"); }

La razón de esto es que el compilador de Java analiza el carácter Unicode /u000d como una nueva línea y se transforma en:

public static void main(String... args) { // The comment below is not a typo. // System.out.println("Hello World!"); }

Por lo tanto, resulta en un comentario "ejecutado".

Dado que esto puede usarse para "ocultar" código malicioso o lo que sea que un programador malvado pueda concebir, ¿por qué está permitido en los comentarios ?

¿Por qué está permitido por la especificación de Java?


Como esto aún no se ha abordado, aquí hay una explicación de por qué la traducción de los escapes de Unicode ocurre antes de cualquier otro procesamiento del código fuente:

La idea detrás de esto era que permite traducciones sin pérdida del código fuente de Java entre diferentes codificaciones de caracteres. Hoy en día, existe un amplio soporte de Unicode, y esto no parece un problema, pero en aquel entonces no era fácil para un desarrollador de un país occidental recibir algún código fuente de su colega asiático que contenía caracteres asiáticos, hacer algunos cambios ( incluyendo compilarlo y probarlo) y devolver el resultado, todo sin dañar algo.

Por lo tanto, el código fuente de Java se puede escribir en cualquier codificación y permite una amplia gama de caracteres dentro de identificadores, caracteres y literales de String y comentarios. Luego, para transferirlo sin pérdidas, todos los caracteres no admitidos por la codificación de destino se reemplazan por sus escapes Unicode.

Este es un proceso reversible y el punto interesante es que la traducción puede hacerse mediante una herramienta que no necesita saber nada sobre la sintaxis del código fuente de Java ya que la regla de traducción no depende de ella. Esto funciona ya que la traducción a sus caracteres Unicode reales dentro del compilador también ocurre independientemente de la sintaxis del código fuente de Java. Implica que puede realizar un número arbitrario de pasos de traducción en ambas direcciones sin cambiar el significado del código fuente.

Esta es la razón de otra característica extraña que ni siquiera ha mencionado: la sintaxis /uuuuuuxxxx :

Cuando una herramienta de traducción escapa caracteres y encuentra una secuencia que ya es una secuencia escapada, debe insertar una u adicional en la secuencia, convirtiendo /ucafe en /uucafe . El significado no cambia, pero cuando se convierte en la otra dirección, la herramienta solo debe eliminar una u y reemplazar solo las secuencias que contienen una u por sus caracteres Unicode. De esa manera, incluso los escapes de Unicode se conservan en su forma original al convertir de un lado a otro. Supongo que nadie usó esa característica ...


El compilador no solo traduce los escapes de Unicode a los caracteres que representan antes de analizar un programa en tokens, sino que lo hace antes de descartar comentarios y espacios en blanco.

Este programa contiene un único escape Unicode (/ u000d), ubicado en su único comentario. Como te dice el comentario, este escape representa el carácter de salto de línea, y el compilador lo traduce debidamente antes de descartar el comentario .

Esto depende de la plataforma. En ciertas plataformas, como UNIX, funcionará; en otros, como Windows, no lo hará. Aunque la salida puede verse igual a simple vista, fácilmente podría causar problemas si se guardara en un archivo o se canalizara a otro programa para su posterior procesamiento.


El escape /u000d finaliza un comentario porque los escapes /u se convierten uniformemente a los caracteres Unicode correspondientes antes de que el programa se tokenice. Igualmente podría usar /u0057/u0057 lugar de // para comenzar un comentario.

Este es un error en su IDE, que debería resaltar la sintaxis de la línea para dejar en claro que /u000d finaliza el comentario.

Esto también es un error de diseño en el lenguaje. No se puede corregir ahora, porque eso rompería los programas que dependen de él. /u compilador debe convertir los escapes al carácter Unicode correspondiente solo en contextos donde eso "tiene sentido" (literales de cadena e identificadores, y probablemente en ningún otro lugar) o se les debería haber prohibido generar caracteres en el U + 0000– Rango 007F, o ambos. Cualquiera de esas semánticas habría evitado que el comentario fuera terminado por el escape /u000d , sin interferir con los casos en los que los escapes /u son útiles; tenga en cuenta que eso incluye el uso de escapes /u dentro de los comentarios como una forma de codificar comentarios -Guión latino, porque el editor de texto podría tener una visión más amplia de dónde son importantes los escapes que el compilador. (Sin embargo, no conozco ningún editor o IDE que muestre /u escapes como los caracteres correspondientes en ningún contexto).

Hay un error de diseño similar en la familia C, 1 donde la barra diagonal inversa-nueva línea se procesa antes de que se determinen los límites de comentario, por ejemplo

// this is a comment / this is still in the comment!

Menciono esto para ilustrar que resulta fácil cometer este error de diseño en particular, y no darme cuenta de que es un error hasta que sea demasiado tarde para corregirlo, si estás acostumbrado a pensar en la tokenización y analizar la forma en que piensan los programadores del compilador. sobre tokenización y análisis. Básicamente, si ya ha definido su gramática formal y luego a alguien se le ocurre un caso especial sintáctico: trigrafos, barra invertida-nueva línea, codificación de caracteres Unicode arbitrarios en archivos fuente limitados a ASCII, lo que sea, que necesita ser encajado, es más fácil agregue un pase de transformación antes del tokenizador que redefinir el tokenizador para prestar atención a dónde tiene sentido usar ese caso especial.

1 Para los pedantes: Soy consciente de que este aspecto de C fue 100% intencional, con la razón, no estoy inventando, que te permitiría forzar mecánicamente el código de ajuste forzado con líneas arbitrariamente largas en tarjetas perforadas. Todavía era una decisión de diseño incorrecta.


Esta fue una elección de diseño intencional que se remonta al diseño original de Java.

Para aquellas personas que preguntan "¿quién quiere escapar de Unicode en los comentarios?", Supongo que son personas cuya lengua materna utiliza el conjunto de caracteres latinos. En otras palabras, es inherente al diseño original de Java que la gente pueda usar caracteres Unicode arbitrarios donde sea legal en un programa Java, más típicamente en comentarios y cadenas.

Podría decirse que es una deficiencia en los programas (como IDE) que se utilizan para ver el texto fuente de que dichos programas no pueden interpretar los escapes de Unicode y mostrar el glifo correspondiente.


Estoy de acuerdo con @zwol en que esto es un error de diseño; pero lo critico aún más.

/u escape es útil en cadenas y char literales; y ese es el único lugar donde debería existir. Debe manejarse de la misma manera que otros escapes como /n ; y "/u000A" debe significar exactamente "/n" .

No tiene sentido tener /uxxxx en los comentarios, nadie puede leer eso.

Del mismo modo, no tiene sentido usar /uxxxx en otra parte del programa. La única excepción es probablemente en las API públicas que están obligadas a contener caracteres que no son ascii. ¿Cuál es la última vez que hemos visto eso?

Los diseñadores tuvieron sus razones en 1995, pero 20 años después, esta parece ser una elección incorrecta.

(pregunta para los lectores: ¿por qué esta pregunta sigue recibiendo nuevos votos? ¿Está vinculada esta pregunta desde algún lugar popular?)


La decodificación Unicode tiene lugar antes de cualquier otra traducción léxica. El beneficio clave de esto es que hace que sea trivial ir y venir entre ASCII y cualquier otra codificación. ¡Ni siquiera necesita saber dónde comienzan y terminan los comentarios!

Como se indicó en la Sección 3.3 de JLS, esto permite que cualquier herramienta basada en ASCII procese los archivos fuente:

[...] El lenguaje de programación Java especifica una forma estándar de transformar un programa escrito en Unicode en ASCII que cambia un programa en un formulario que puede ser procesado por herramientas basadas en ASCII. [...]

Esto proporciona una garantía fundamental para la independencia de la plataforma (independencia de los conjuntos de caracteres compatibles) que siempre ha sido un objetivo clave para la plataforma Java.

Ser capaz de escribir cualquier carácter Unicode en cualquier parte del archivo es una característica interesante, y especialmente importante en los comentarios, al documentar código en idiomas no latinos. El hecho de que pueda interferir con la semántica de manera tan sutil es solo un efecto secundario (desafortunado).

Hay muchos problemas con este tema y Java Puzzlers de Joshua Bloch y Neal Gafter incluyeron la siguiente variante:

¿Es este un programa legal de Java? Si es así, ¿qué imprime?

/u0070/u0075/u0062/u006c/u0069/u0063/u0020/u0020/u0020/u0020 /u0063/u006c/u0061/u0073/u0073/u0020/u0055/u0067/u006c/u0079 /u007b/u0070/u0075/u0062/u006c/u0069/u0063/u0020/u0020/u0020 /u0020/u0020/u0020/u0020/u0073/u0074/u0061/u0074/u0069/u0063 /u0076/u006f/u0069/u0064/u0020/u006d/u0061/u0069/u006e/u0028 /u0053/u0074/u0072/u0069/u006e/u0067/u005b/u005d/u0020/u0020 /u0020/u0020/u0020/u0020/u0061/u0072/u0067/u0073/u0029/u007b /u0053/u0079/u0073/u0074/u0065/u006d/u002e/u006f/u0075/u0074 /u002e/u0070/u0072/u0069/u006e/u0074/u006c/u006e/u0028/u0020 /u0022/u0048/u0065/u006c/u006c/u006f/u0020/u0077/u0022/u002b /u0022/u006f/u0072/u006c/u0064/u0022/u0029/u003b/u007d/u007d

(Este programa resulta ser un simple programa de "Hola mundo").

En la solución al rompecabezas, señalan lo siguiente:

Más en serio, este rompecabezas sirve para reforzar las lecciones de los tres anteriores: los escapes Unicode son esenciales cuando necesita insertar caracteres que no se pueden representar de otra manera en su programa. Evítelos en todos los demás casos.

Fuente: Java: ¿Ejecutar código en los comentarios?


Las únicas personas que pueden responder por qué se implementaron los escapes de Unicode tal como fueron son las personas que escribieron la especificación.

Una razón plausible para esto es que existía el deseo de permitir que todo el BMP fuera posible como caracteres del código fuente de Java. Sin embargo, esto presenta un problema:

  • Desea poder usar cualquier carácter BMP.
  • Desea poder ingresar cualquier carácter BMP razonablemente fácil. Una forma de hacerlo es con escapes Unicode.
  • Desea mantener la especificación léxica fácil de leer y escribir para los humanos, y razonablemente fácil de implementar también.

Esto es increíblemente difícil cuando los escapes de Unicode entran en juego: crea una carga completa de nuevas reglas lexer.

La salida fácil es hacer lexing en dos pasos: primero busque y reemplace todos los escapes de Unicode con el carácter que representa, y luego analice el documento resultante como si los escapes de Unicode no existieran.

La ventaja de esto es que es fácil de especificar, por lo que simplifica la especificación y es fácil de implementar.

La desventaja es, bueno, tu ejemplo.


Voy a agregar completamente el punto ineficazmente, solo porque no puedo evitarlo y no lo he visto aún, que la pregunta no es válida ya que contiene una premisa oculta que es incorrecta, a saber, que el código está en ¡un comentario!

En Java, el código fuente / u000d es equivalente en todos los sentidos a un carácter ASCII CR. Es un final de línea, simple y llano, donde sea que ocurra. El formato en la pregunta es engañoso, a lo que corresponde esa secuencia de caracteres sintácticamente es:

public static void main(String... args) { // The comment below is no typo. // System.out.println("Hello World!"); }

En mi humilde opinión, la respuesta más correcta es: el código se ejecuta porque no está en un comentario; Está en la línea siguiente. "Ejecutar código en comentarios" no está permitido en Java, como es de esperar.

Gran parte de la confusión se debe al hecho de que los resaltadores de sintaxis y los IDE no son lo suficientemente sofisticados como para tener en cuenta esta situación. No procesan los escapes de Unicode en absoluto, o lo hacen después de analizar el código en lugar de antes, como lo hace javac .