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
.