opciones - ¿Por qué usar Asprintf?
wp_nav_menu li class (2)
El beneficio es seguridad.
Numerosos programas han permitido que los exploits del sistema ocurran al tener desbordamientos de búfers provistos por el programador cuando se llenan con los datos suministrados por el usuario.
Tener asprintf
asigna el búfer para que las garantías que no puede suceder.
Sin embargo, debe verificar el valor de retorno de asprintf
para asegurarse de que la asignación de memoria realmente tuvo éxito. Ver http://blogs.23.nu/ilja/2006/10/antville-12995/
Me está costando entender por qué necesitarías asprintf. Aquí en el manual dice
Las funciones asprintf () y vasprintf () son análogas de sprintf (3) y vsprintf (3), excepto que asignan una cadena lo suficientemente grande como para contener el resultado incluyendo el byte nulo de terminación y devolver un puntero a través del primer argumento . Este puntero debe pasarse a libre (3) para liberar el almacenamiento asignado cuando ya no sea necesario.
Así que aquí está el ejemplo que trato de entender:
asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
¿Cuál es la diferencia si el búfer asigna una cadena suficientemente grande frente a decir char * = (cadena)
Si usa sprintf () o vsprintf (), primero debe asignar un búfer y debe asegurarse de que el búfer sea lo suficientemente grande como para contener lo que sprintf escribe. De lo contrario, Sprintf sobrescribirá alegremente cualquier memoria que se encuentre más allá del final del búfer.
char* x = malloc(5 * sizeof(char));
sprintf(x,"%s%s%s", "12", "34", "56"); // writes "123456" +null but overruns the buffer
... escribe el ''6'' y el null
terminación más allá del final del espacio asignado a x
, ya sea corrompiendo alguna otra variable o causando un error de segmentación.
Si tiene suerte, pisoteará la memoria entre los bloques asignados, y no hará daño, esta vez. Esto conduce a errores intermitentes, el tipo más difícil de diagnosticar. Es bueno usar una herramienta como ElectricFence que hace que los excesos fallen rápidamente.
Un usuario no malintencionado que proporciona una entrada demasiado larga puede provocar que el programa se comporte de forma inesperada. Un usuario malintencionado podría explotar esto como una forma de obtener su propio código ejecutable en el sistema.
Un protector contra esto es usar snprintf()
, que trunca la cadena a la longitud máxima que usted proporciona.
char *x = malloc(5 * sizeof(char));
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); // writes "1234" + null
El size
valor de retorno es la longitud que se habría escrito si hubiera espacio disponible, sin incluir el nulo de terminación .
En este caso, si el size
es mayor o igual a 5, sabrá que se produjo el truncamiento, y si no desea el truncamiento, puede asignar una nueva cadena e intentar snprintf()
nuevamente.
char *x = malloc(BUF_LEN * sizeof(char));
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56");
if(size >= BUF_LEN) {
realloc(&x,(size + 1) * sizeof(char));
snprintf(x, 5, "%s%s%s", "12", "34", "56");
}
(Es un algoritmo bastante ingenuo, pero ilustra el punto)
asprintf()
hace esto en un solo paso: calcula la longitud de la cadena, asigna esa cantidad de memoria y escribe la cadena en ella.
char *x;
int size = asprintf(&x, "%s%s%s", "12", "34", "56");
En todos los casos, una vez que haya terminado con x
necesita liberarlo, o si pierde memoria:
free(x);
asprintf()
es un malloc()
implícito malloc()
, por lo que debe verificar que funcionó, tal como lo haría con malloc()
o cualquier otra llamada al sistema.
if(size == -1 ) {
/* deal with error in some way */
}
Tenga en cuenta que asprintf()
es parte de las extensiones GNU y BSD de libc; no puede estar seguro de que esté disponible en cada entorno en C. sprintf()
y snprintf()
son parte de los estándares POSIX y C99.