flawopen.com/Seguridad de memoria/strcpy vs strncpy
¿strncpy() es más segura que strcpy()?
Un campo de ancho fijo es como una fila de casillas: la última necesita un marcador de fin si el código tratará los bytes como una cadena C. strncpy() escribe como máximo n bytes y solo evita rebasar el destino si n no supera el tamaño real del búfer. Si la fuente llena ese límite, no añade terminador nulo. Una función posterior puede leer más allá del destino buscando el marcador ausente.
char dst[16]; /* 1. Unbounded — classic overflow */ strcpy(dst, src); /* 2. Bounded, but may not terminate. If strlen(src) >= 16, dst has no '\0' and every later strlen/printf reads out of bounds. */ strncpy(dst, src, sizeof(dst)); /* 3. Off-by-one: room for 16 chars plus a terminator = 17 bytes, but dst only holds 16. */ strncpy(dst, src, sizeof(dst)); dst[sizeof(dst)] = '\0'; /* OOB! */
char dst[16]; /* Preferred: snprintf always null-terminates (when size > 0), and tells you about truncation. */ int n = snprintf(dst, sizeof(dst), "%s", src); if (n < 0 || (size_t)n >= sizeof(dst)) { /* truncated — handle it */ return ERR_TOO_LONG; } /* Or strlcpy where available — always terminates, returns the length it tried to create. */ if (strlcpy(dst, src, sizeof(dst)) >= sizeof(dst)) { return ERR_TOO_LONG; }
Para qué se diseñó strncpy
Este comportamiento no es un defecto: strncpy() se diseñó para secuencias de caracteres de ancho fijo y rellenadas con nulos, no como copia segura general de cadenas C. Si la cadena fuente es más corta que n, rellena el destino con bytes nulos hasta n - 1. Si no hay un byte nulo entre los primeros n bytes de la fuente, copia exactamente n bytes y no termina el destino. Puede servir para campos de ancho fijo, pero es peligrosa si el resultado se pasa a API que esperan una cadena terminada en nulo.
Cuando la fuente es más corta que n, el relleno requerido escribe hasta el ancho completo del campo. En búferes grandes y fuentes cortas, puede hacer más trabajo que una copia que se detiene en el terminador.
Comprueba siempre el truncamiento
Evitar el desbordamiento es solo la mitad. El truncamiento silencioso también puede ser un problema: un host, una ruta o un valor de autorización truncado puede cambiar de significado. snprintf devuelve la longitud que habría escrito; compárala con el tamaño del búfer. Interpretar mal ese valor como bytes escritos también fue relevante en Citrix Bleed.
Preguntas frecuentes
Terminan la cadena y comprueban límites, pero su portabilidad es irregular: funcionan bien en Windows y están implementadas de forma desigual en otros sistemas. Para varios sistemas, snprintf suele estar más disponible.
No. Surgió en OpenBSD y está disponible en BSD y macOS; versiones recientes de glibc también la incluyen. Comprueba tus plataformas de destino.
Prefiere std::string y std::string_view, que gestionan la longitud. Usa funciones C solo en límites de API que exijan un búfer sin procesar.