secuencias salida que programacion formatos formato especificadores especificador escape conversion c++ c printf

c++ - salida - que es un especificador de formato en programacion



Programa de especificador de formato% n que da diferentes salidas en diferentes compiladores. ¿Por qué? (2)

Como se señaló en la pregunta Code Blocks son correctos, mientras que Orwell Dev C++ es incorrecto. Visual Studio por otro lado no es conforme.

La documentación de cppreferences C para printf dice:

devuelve el número de caracteres escritos hasta ahora por esta llamada a la función.

No veo nada en el borrador del estándar que lo haga opcional, C ++ se refiere al estándar C con respecto a printf . MSDN documenta esto y dice:

Debido a que el formato% n es inherentemente inseguro, está deshabilitado de manera predeterminada. Si se encuentra% n en una cadena de formato, se invoca el controlador de parámetros no válido, como se describe en Validación de parámetros. Para habilitar el soporte de% n, vea _set_printf_count_output.

¿Por qué el formato% n es inherentemente inseguro?

Supongo que lo consideran inseguro debido a problemas de seguridad, como los descritos en los documentos de Vulnerabilidad de cadenas de formato , una posible forma de explotar esto. Se basa en la cadena de formato controlada por la entrada del usuario. El papel da el siguiente ejemplo:

char user_input[100]; scanf("%s", user_input); printf(user_input);

Ninja retirado vinculado a la publicación Bugtraq que muestra un ejemplo real de un error de este tipo que termina en un exploit en proftpd 1.2.0pre6 :

  • ftp al host
  • inicio de sesión (anónimo o no)

(esto debería ser todo en una línea, sin espacios)

ftp> ls aaaXXXX% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u% u % u% u% u% u% u% u% u% u% u% u% u% u% u% 653300u% n

(Reemplace las X con los caracteres con valores ASCII 0xdc, 0x4f, 0x07,0x08 consecutivamente)

Muchos otros desagradables se pueden hacer fácilmente con esto. Dado que proftpd pasará los datos de entrada del usuario a snprintf, los ataques de argumentos son fáciles.

El problema con el enfoque de Visual Studios es que rompe la portabilidad. Otros enfoques incluyen el uso de indicadores como Wformat-security utilizado por gcc, que combinado con -WError puede hacer que sea un error, pero puede elegir esto como parte de su proceso de compilación.

Estaba leyendo sobre el especificador de formato %n en C en esta pregunta . Pero cuando probé el siguiente programa en diferentes compiladores de C ++, me dio diferentes salidas.

¿Por qué? ¿Cual es la razon? ¿Está ocurriendo un comportamiento indefinido o de implementación definida?

#include<stdio.h> int main() { int c = -1; printf("geeks for %ngeeks ", &c); printf("%d", c); getchar(); return 0; }

Salida:

Bloques de código 13.12: (salida correcta)

geeks for geeks 10

Borland / CodeGear / Embarcadero C ++: (salida correcta)

geeks for geeks 10

Orwell Dev C ++:

geeks -1

Microsoft Visual Studio 2010:

Debug assertion failed ("''n'' format specifier disabled",0)


La salida de Code Blocks es correcta.

La salida de Orwell Dev C ++ es incorrecta. O bien esa implementación no es no conforme de forma predeterminada (lea la documentación para ver si hay una manera de hacer que se comporte correctamente), o tiene un error.

La implementación de Microsoft no es conforme por defecto. Desactiva el especificador de formato %n estándar para evitar algunos posibles problemas de seguridad (aunque no hay problemas de este tipo en el código de su pregunta). Aparentemente hay maneras de volver a habilitarlo; Ver la respuesta de Shafik Yaghmour .

El único problema potencial que veo con su programa es que no imprime una nueva línea al final de su salida, pero eso no es relevante para el problema %n .