¿Existe un gato seguro?

¿Existe un gato seguro?

De vez en cuando sucede que obtengo un binario desde curl o desde el sistema de archivos local. En la mayoría de los casos, el terminal roto se puede arreglar conreiniciar. En otros casos, particularmente si el binario es grande, el terminal se quedará bloqueado durante varios minutos imprimiendo un resultado como este:

2c1

alias

c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;

Tengo tres preguntas con respecto a este escenario;

  1. ¿Qué significa 2c1 y por qué el terminal imprime esto?
  2. ¿Has visto a alguien caten la naturaleza protegiéndose contra este comportamiento no deseado en una sesión interactiva?
  3. ¿Tiene alguna sugerencia sobre cómo programar un gato de este tipo (en cee o golang)?

Mi instinto inicial fue incluir a cat en una función para detectar esto, pero pronto me di cuenta de que es bastante difícil hacerlo bien y que tendría numerosos casos extremos.

function cat() {
    # warn user if
    #   - argument 1 is a large  executable 
    #   - argument 1 to the previous command in the a pipe-chain looks like a large binary
    # abort if
    #   - session is interactive and we are able to detect 2c1 garbage
}

Una solución práctica podría ser usar siempre menos (con LESSPIPE) cuando se buscan entradas "inseguras", pero esta pregunta no se trata de buscapersonas. Soy consciente de que cada vez hay menos pipas. Los uso activamente todos los días. Quizás menos+menostuberíaes la solución a este problema, que los autores de menos implementaron hace unos 20-30 años enfrentando el mismo problema.

Sin embargo, cat se diferencia de un "buscapersonas" en más de un sentido... Principalmente, cat no es interactivo. Esto es significativo para mí.

La sugerencia sobre less+lesspipe es realmente buena (en mi humilde opinión) en términos prácticos, pero estoy más preocupado por el meollo de la cuestión de los caracteres de control, las secuencias de escape especiales y cómo los diferentes terminales manejan estas entradas.

Estoy más interesado en los detalles técnicos de los personajes de control y cómo los terminales o shells interpretan la "basura" y los personajes de control. No estoy preguntando "¿cómo resolverías este problema?". Estoy preguntando "¿por qué el terminal maneja archivos binarios como este?".

Respuesta1

Yo usaría lessen su lugar, que advierte sobre archivos binarios y en algunos sistemas puede manejar varios tipos (p.ejen CentOS 7, puedo hacer less file.rpmy ver los archivos en el RPM). Creo que eso se llama "lesspipe".

Además, la próxima vez que eso suceda, puedes intentar resetvolver tput reseta la normalidad. Estos envían secuencias de escape al terminal que le indican que se restablezca a un estado sano predeterminado y también hacen el equivalente a stty sanecambiar la configuración del archivo del dispositivo tty a un estado predeterminado sano (sin embargo, descargar un archivo binario no debería afectarlos). resetTambién puede corregir la noción del archivo del dispositivo tty sobre el tamaño de la ventana del terminal o emulador de terminal (según lo informado por tty size) con aquellos terminales que admiten consultas.

Respuesta2

Nadie ha mencionado "cadenas". Aunque strings no es exactamente como cat, imprime solo las cadenas de texto de datos de texto continuo para que sea más seguro verlo en la terminal. Suele venir con el paquete binutils. Es un programa útil para garantizar rápidamente que no obtenga ninguna salida binaria de los datos impresos y también es útil si solo desea ver el contenido no binario continuo. Tenga en cuenta que, de forma predeterminada, solo imprime secciones de texto continuo con 4 o más caracteres ASCII. Esto se puede ajustar con la opción -n.

Respuesta3

Interactúa con un terminal o emulador de terminal a través de una línea serie o dispositivo pseudo-tty (que emula una línea serie).

Aunque hay un módulo de software en el kernel que se ubica en el medio como una especie de capa de adaptación y realiza alguna transformación (que se analiza brevemente más adelante), normalmente:

  • enviar un flujo de bytes al terminal a través de esa línea serial que el terminal interpreta como glifos para representar en su pantalla o instrucciones especiales para cambiar su comportamiento
  • a cambio, el terminal envía un flujo de bytes a la computadora a través de otro cable en esa línea serie para decirle a la computadora lo que usted escribió o para responder a algunas de las consultas de control que recibió.

Por ejemplo, un terminal podría configurarse como ISO8859-1 (también conocido como terminal latin1), lo que significa que cuando recibe el 0x53 0x74 0xe9 0x70 0x68 0x61 0x6e 0x65, lo interpreta como que representa los glifos S, t, é, p, h, a, n, een el posición actual del cursor en su pantalla. Y a la inversa, cuando el usuario escribe S, el terminal envía el byte 0x53.

Los valores de bytes en el rango de 0 a 0x1f se interpretan comocontrolcaracteres. Es decir, no están representados como glifos, sino que tienen un significado especial.

Por ejemplo:

  • 0x7 (BEL) genera una alerta de audio o video
  • 0x8 (BS) mueve el cursor hacia la izquierda
  • 0xa (LF) mueve el cursor hacia abajo
  • 0xd (CR) mueve el cursor a la primera columna de la pantalla
  • 0x9 (TAB) mueve el cursor a la siguiente tabulación

Sólo hay 32 personajes de control en ese rango y la mayoría de terminales tienen muchas más funciones o formas de controlarlos. Además de eso, puedes enviar secuencias de más deunobyte para controlar tu terminal. Para la mayoría de terminales y para la mayoría de esas secuencias, el primer byte es 0x1b (ESC) seguido de uno o más bytes.

Por ejemplo, si bien hay caracteres de control para mover el cursor hacia la izquierda o hacia abajo como se ve arriba, no hay ninguno para moverlo hacia la derecha o hacia arriba (como originalmente, en las telemáquinas de escribir, la derecha se hacía con "espacio", pero en Terminales CRT que borran lo que hay debajo del cursor, y no usaría una telemáquina de escribir ya que eso probablemente crearía un atasco de papel), por lo que se tuvieron que introducir secuencias de escape para ellos, en la mayoría de los terminales 0x1b 0x5b 0x43 y 0x1b 0x5b 0x41 respectivamente. (Por cierto, esa es también la secuencia de bytes que envían muchos terminales al presionar Righty Uppara aquellos que tienen dichas teclas).

Ahora bien, entre las secuencias de escape que soportan las terminales se encuentran algunas que:

  • cambiar el texto o el color de fondo y otros atributos de representación gráfica
  • cambiar el juego de caracteres. Por ejemplo, no hay ningún carácter griego en latin1, y las terminales (desde los días anteriores a Unicode y aún hoy) admiten el cambio a un conjunto de caracteres diferente para mostrar letras de otros idiomas o caracteres de dibujo de cuadros.
  • establecer la posición de las tabulaciones
  • Se puede consultar información desde el terminal como posición del cursor, color, título de la ventana, tamaño...
  • puede afectar la forma en que se procesa la entrada. Por ejemplo, algunos terminales admiten ingresar a un modo mediante el cual al presionar Shift+, Apor ejemplo, no envía un Acarácter 0x41 (ASCII), sino una secuencia de bytes que codifica información sobre modificadores (shift, alt, ctrl...) y código clave.
  • algunos emuladores de terminal X11 reconocen secuencias de escape para cambiar la fuente, el tamaño de la ventana, mostrar imágenes JPEG, enviar el contenido de la pantalla a una impresora...

En un archivo de texto, normalmente solo tiene bytes (o secuencias de bytes si es UTF-8 u otros conjuntos de caracteres multibyte) que representan caracteres gráficos. El únicocontrolLos caracteres que encontrarás en los archivos de texto son NL (0xa, también conocido como LF) y TAB (0x9).

Cuando lo hace cat file.txt, catsimplemente lee el contenido file.txty lo escribe en su salida estándar. Si stdout es un archivo de dispositivo serial o pseudo-tty ( /dev/ttyS0, /dev/pts/0por ejemplo) que tiene una disciplina de línea de terminal insertada, como sería el caso si ejecuta ese comando desde un shell interactivo en un emulador de terminal, la disciplina de línea traduce esos NL a CR+NL (aunque NLNL puede traducirse solo a CRNLNL), por lo que el terminal al recibir CRNL moverá el cursor al inicio y luego hacia abajo.

Por lo tanto, el texto del contenido del archivo se mostrará en la pantalla del terminal siempre que el texto del archivo esté codificado en el juego de caracteres del terminal.

Ahora, los bytes en archivos ejecutables u otros archivos binarios aleatorios no están destinados a representar caracteres, pueden tener cualquier valor, incluidos los que están en el rango de 0 a 31, por lo que cuando se envían a una terminal, la terminal hará lo que se le indique y los interpretará como personajes de control, lo que puede hacer que haga cualquier cosa como se menciona anteriormente y mucho más y dejarlo completamente inutilizable.

Para protegerse contra eso, primero no envíe esos archivos a una terminal ya que eso no tendría sentido, o si no sabe si un archivo puede ser un archivo de texto (o un archivo destinado a ser visto palabra por palabra por un terminal con secuencias de escapedestinadopara ser interpretado por una terminal) o no, puede usar una herramienta que elimine los caracteres de control (al menos todos menos TAB y NL) o les dé una representación gráfica visual.

Eso es lo que hacen las opciones -vy -tcompatibles con muchas catimplementaciones. Donde con -v, todos excepto NL y TAB se convierten a alguna ^Xnotación para los bytes 0 a 31 y 0x7f, M-^Xpara los bytes 0x80 a 0x9f y 0xff y M-Xpara los bytes 0xa0 a 0xfe, que son representaciones visuales comunes de caracteres no ASCII. Y -tlo hace solo para TAB (cambiado a ^I).

O puede usar un buscapersonas como lesso vim's viewque lo hace de forma predeterminada (al menos siempre que no use las opciones -r/ -Rraw) y es un poco más inteligente porque no transforma caracteres no ASCII que son destinado a tener representaciones gráficas en su ubicación y dejar más claro qué bytes se han transformado mediante el uso de modos de color o destacado.

O puede utilizar herramientas dedicadas a obtener una vista previa de archivos que no son de texto, como hexdump -Co xxd.

Vea también el lcomando de sedwhich hace algo similar cat -vtey es estándar (contrario a cat -vte) de una manera menos ambigua:

sed -n l < a-file

Respuesta4

  • Sí, joven padawan.
$ cargo search bat 
bat = "0.23.0"            # A cat(1) clone with wings.
  • Pero maestro, ¿qué es un cargamento?
$ cargo --help |any install rust 
Rust's package manager
      --list                List installed commands
      --explain <CODE>      Run `rustc --explain CODE`
    install     Install a Rust binary. Default location is $HOME/.cargo/bin
    uninstall   Uninstall a Rust binary
$ cargo install bat
(...)

maestro:Esto sucede si intentas batun binario.

$ bat `which bat`
[bat warning]: Binary content from file '/home/jaroslav/.cargo/bin/bat'
will not be printed to the terminal (but will be present if the output
of 'bat' is piped). You can use 'bat -A' to show the binary file contents.
  • padawan:¿Hay desventajas en batear, maestro?
  • maestro:Sí, puede ser lento en archivos grandes, pero eso se debe en parte a que resalta la sintaxis estructurada. Esas cosas se pueden desactivar, por ejemplo --style=plain --color=never
  • padawan:¿Qué pasa con los caracteres extraños que cat envía a la terminal, maestro?
  • maestro:Esto sucede porque los terminales aceptarán e interpretarán gustosamente cualquier cosa que parezca un código de escape ANSI (comando interno del terminal) e intentarán hacer lo que dice el comando, si ese comando está implementado. Para una breve introducción, mira estolista de secuencias de escape de color ansi

A continuación se explica cómo reproducir este comportamiento:

$ echo -ne "\u1B\u5B\u63" | xxd
00000000: 1b5b 63                                  .[c

$ echo -ne "\u1B\u5B\u63" 
^[[?1;2c

$ 1;2c

información relacionada