Pregunta

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 podría copiar el nombre de alguien (por ejemplo, Tom Brokaw) con Tom Bro763.

¿Cuáles son las ventajas de usar strncpy() sobre strcpy()?

¿Fue útil?

Solución

strncpy Combata el desbordamiento del búfer al requerirle que ponga una longitud en él. strcpy depende de un final \0, que puede no ocurrir siempre.

En segundo lugar, por qué eligió copiar solo 5 caracteres en una cadena de 7 caracteres está más allá de mí, pero está produciendo el comportamiento esperado. Solo está copiando sobre el primero n personajes, donde n es el tercer argumento.

los n Las funciones se usan como codificación defensiva contra los desbordamientos del búfer. Úselos en lugar de funciones anteriores, como strcpy.

Otros consejos

los strncpy() La función fue diseñada con un problema muy particular en mente: manipular las cadenas almacenadas a la manera de las entradas originales de directorio UNIX. Estos usaban una matriz de tamaño fijo, y un terminador NUL solo se usaba si el nombre de 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 completamente el destino, con NULS si es necesario.

Para un "más seguro strcpy()", es mejor que use strncat() al igual que:

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

Eso siempre finalizará el resultado y no copiará más de lo necesario.

Mientras conozco la intención detrás strncpy, no es realmente una buena función. Evite ambos. Raymond Chen explica.

Personalmente, mi conclusión es simplemente evitar strncpy Y todos sus amigos si se trata de cuerdas nulas terminadas. A pesar del "STR" en el nombre, estas funciones no producen cadenas nulas terminadas. Convierten una cadena terminada en un búfer de caracteres en bruto. Usarlos donde se espera una cadena nula ya que el segundo búfer es simplemente incorrecto. No solo no puede obtener una terminación nula adecuada si la fuente es demasiado larga, sino que si la fuente es corta obtienes un relleno nulo innecesario.

Ver también ¿Por qué strncpy es inseguro?

Strncpy no es más seguro que Strcpy, solo intercambia un tipo de errores con otro. En C, al manejar cadenas C, debe saber el tamaño de sus búferes, no hay forma de evitarlo. Strncpy estaba justificado para el directorio mencionado por otros, pero de lo contrario, nunca debe usarlo:

  • Si sabe la longitud de su cadena y búfer, ¿por qué usar strncpy? Es un desperdicio de potencia informática en el mejor de los casos (agregando 0 inútil)
  • Si no conoce las longitudes, entonces corre el riesgo de truncar en silencio sus cuerdas, lo que no es mucho mejor que un desbordamiento de búfer

Lo que estás 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, 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 puede ver las discusiones enhttp://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 las 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()) con una versión de captura que aborta brutalmente el programa en desbordamientos o truncamientos de búfer. Esto permite atrapar rápidamente a los peores delincuentes. Especialmente si trabaja 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;
}

los strncpy() La función es la más segura: debe pasar la longitud máxima que el búfer de destino puede aceptar. De lo contrario, podría suceder que la cadena de origen no se termine correctamente 0, en cuyo caso el strcpy() La función podría escribir más caracteres para el destino, corrompiendo cualquier cosa que esté en la memoria después del búfer de destino. Este es el problema del búfer-superpuesto utilizado en muchas exploits

También para funciones de API de Posix como read() que no pone el terminación 0 en el búfer, pero devuelve el número de bytes leídos, lo pondrá manualmente el 0 o lo copiará usando strncpy().

En su código de ejemplo, index en realidad no es un índice, sino un count - dice cuántos personajes a lo sumo Para copiar de origen a destino. Si no hay byte nulo entre los primeros n bytes de fuente, la cadena colocada en el destino no será finalizada

strncpy llena el destino con ' 0' para el tamaño de la fuente, aunque el tamaño del destino es más pequeño ...

ManPage:

Si la longitud de Src es menor que n, strncpy () se altera el resto de Dest con bytes nulos.

Y no solo el resto ... también después de esto hasta que se alcancen los caracteres. Y así obtienes un desbordamiento ... (consulte la implementación de la página del hombre)

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 parte limitada de la cadena original en lugar de strcpy (). Veo que proviene el código que ha puesto publib.boulder.ibm.com.

Eso depende de nuestro requisito. Para usuarios de Windows

Usamos strncpy cuando no queremos copiar una cadena completa o queremos copiar solo un número de caracteres. Pero Strcpy copia toda la cadena, incluida la terminación del carácter nulo.

Estos enlaces lo ayudarán más a saber sobre strcpy y strncpy y dónde podemos usar.

Acerca de strcpy

sobre strncpy

El strncpy es una versión más segura de strcpy, de hecho, nunca debe usar strcpy porque su potencial vulnerabilidad de desbordamiento de búfer que lo hace vulnerable a todo tipo de ataques

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top