¿Por qué debería usar strncpy en lugar de strcpy?
buffer-overflow c89 (10)
Eso depende de nuestro requerimiento. Para usuarios de Windows
Usamos strncpy cuando no queremos copiar una cadena completa o queremos copiar solo n caracteres. Pero strcpy copia toda la cadena incluyendo la terminación del carácter nulo.
Estos enlaces te ayudarán a saber más sobre strcpy y strncpy y dónde podemos usar.
Editar: he agregado la fuente para el ejemplo.
Me encontré con este ejemplo :
char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;
/* This is how strcpy works */
printf("destination is originally = ''%s''/n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes ''%s''/n/n", destination);
/* This is how strncpy works */
printf( "destination1 is originally = ''%s''/n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes ''%s''/n", destination1 );
Que produjo esta salida:
destination is originally = ''abcdefg'' After strcpy, destination becomes ''123456789'' destination1 is originally = ''abcdefg'' After strncpy, destination1 becomes ''12345fg''
Lo que me hace preguntarme por qué alguien querría este efecto. Parece que sería confuso. Este programa me hace pensar que básicamente puedes copiar el nombre de alguien (por ejemplo, Tom Brokaw) con Tom Bro763.
¿Cuáles son las ventajas de usar strncpy()
sobre strcpy()
?
Esto se puede usar en muchos otros escenarios, donde necesita copiar solo una parte de su cadena original al destino. Usando strncpy () puede copiar una porción limitada de la cadena original en lugar de strcpy (). Veo que el código que ha presentado proviene de publib.boulder.ibm.com .
La función strncpy()
es la más segura: debe pasar la longitud máxima que puede aceptar el búfer de destino. De lo contrario, podría suceder que la cadena fuente no termine correctamente, en cuyo caso la función strcpy()
podría escribir más caracteres en el destino, corrompiendo todo lo que está en la memoria después del buffer de destino. Este es el problema de desbordamiento de búfer utilizado en muchos exploits
También para las funciones de la API POSIX, como read()
que no pone el 0 de terminación en el búfer, pero devuelve el número de bytes leídos, usted colocará el 0 manualmente o lo copiará usando strncpy()
.
En su código de ejemplo, el index
realidad no es un índice, sino un count
; le dice cuántos caracteres, como máximo, copiar del origen al destino. Si no hay un byte nulo entre los primeros n bytes de la fuente, la cadena colocada en el destino no terminará en nulo
La función strncpy()
se diseñó teniendo en cuenta un problema muy particular: manipular cadenas almacenadas de la misma forma que las entradas de directorio originales de UNIX. Estos utilizaron una matriz de tamaño fijo, y un terminador nul solo se usó si el nombre del archivo era más corto que la matriz.
Eso es lo que hay detrás de las dos rarezas de strncpy()
:
- No pone un terminador nul en el destino si está completamente lleno; y
- Siempre llena por completo el destino, con nuls si es necesario.
Para una " strcpy()
más segura", es mejor que strncat()
manera:
if (dest_size > 0)
{
dest[0] = ''/0'';
strncat(dest, source, dest_size - 1);
}
Eso siempre anulará el resultado y no copiará más de lo necesario.
Lo que está buscando es la función strlcpy()
que termina siempre la cadena con 0 e inicializa el búfer. También es capaz de detectar desbordamientos. El único problema es que no es (realmente) portátil y está presente solo en algunos sistemas (BSD, Solaris). El problema con esta función es que abre otra lata de gusanos como se puede ver en las discusiones en http://en.wikipedia.org/wiki/Strlcpy
Mi opinión personal es que es mucho más útil que strncpy()
y strcpy()
. Tiene un mejor rendimiento y es un buen compañero para snprintf()
. Para plataformas que no lo tienen, es relativamente fácil de implementar. (Para la fase de desarrollo de una aplicación, sustituyo estas dos funciones ( snprintf()
y strlcpy()
) por una versión de captura que aborta brutalmente el programa en desbordamientos o truncamientos del búfer. Esto permite capturar rápidamente a los peores delincuentes. en una base de código de otra persona.
EDITAR: strlcpy()
se puede implementar fácilmente:
size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t len = strlen(src);
if(dstsize) {
size_t bl = (len < dstsize-1 ? len : dstsize-1);
((char*)memcpy(dst, src, bl))[bl] = 0;
}
return len;
}
Si bien sé la intención detrás de strncpy
, no es realmente una buena función. Evita ambos. Raymond Chen explica .
Personalmente, mi conclusión es simplemente evitar
strncpy
y todos sus amigos si se trata de cadenas terminadas en nulo. A pesar del "str" en el nombre, estas funciones no producen cadenas terminadas en nulo. Convierten una cadena terminada en nulo en un buffer de caracteres sin procesar. Utilizándolos donde se espera una cadena terminada en nulo como el segundo buffer está completamente equivocado. No solo no obtiene la terminación nula adecuada si la fuente es demasiado larga, pero si la fuente es corta, obtiene un relleno nulo innecesario.
Ver también ¿Por qué strncpy es inseguro?
el strncpy es una versión más segura de Strcpy, de hecho, nunca deberías usar strcpy porque su potencial vulnerabilidad de desbordamiento del búfer hace que el sistema sea vulnerable a todo tipo de ataques.
strncpy NO es más seguro que Strcpy, solo intercambia un tipo de error con otro. En C, cuando maneje cadenas C, necesita saber el tamaño de sus búferes, no hay forma de evitarlo. strncpy fue justificado por el directorio mencionado por otros, pero por lo demás, nunca debes usarlo:
- si conoce la longitud de su cadena y buffer, ¿por qué usar strncpy? Es un desperdicio de poder de cómputo en el mejor de los casos (agregando 0 inútil)
- si no conoce las longitudes, corre el riesgo de truncar silenciosamente sus cadenas, lo cual no es mucho mejor que un desbordamiento de búfer
strncpy llena el destino con ''/ 0'' para el tamaño de la fuente, aunque el tamaño del destino es más pequeño ....
página de manual:
Si la longitud de src es menor que n, strncpy () rellena el resto de dest con bytes nulos.
y no solo el resto ... también después de esto hasta que se alcance n caracteres. Y así obtienes un desbordamiento ... (ver la implementación de la página man)
strncpy
combate el desbordamiento del búfer al exigirte que pongas una longitud en él. strcpy
depende de un /0
final, que puede no ocurrir siempre.
En segundo lugar, no puedo entender por qué eligió copiar solo 5 caracteres en cadenas de 7 caracteres, pero está produciendo el comportamiento esperado. Solo copia sobre los primeros n
caracteres, donde n
es el tercer argumento.
Las n
funciones se usan todas como codificación defensiva contra desbordamientos de búfer. Úselos en lugar de funciones anteriores, como strcpy
.