Los estándares C11 y C++14 han eliminado la función gets() que es intrínsecamente insegura y genera problemas de seguridad porque no realiza comprobaciones de límites que dan como resultado un desbordamiento del búfer. Entonces, ¿por qué el estándar C11 no descarta las funciones strcat() y strcpy() ? La función strcat() no verifica si la segunda cadena cabe en la primera matriz. La función strcpy() tampoco contiene ninguna disposición para verificar el límite de la matriz de destino. ¿Qué sucede si la matriz de origen tiene más caracteres de los que puede contener la matriz de destino? Lo más probable es que el programa se bloquee en tiempo de ejecución.
Entonces, ¿no sería bueno si estas dos funciones inseguras se eliminaran por completo del lenguaje? ¿Por qué todavía existen? ¿Cuál es la razón? ¿No estaría bien tener solo funciones como strncat(),strncpy() ? Si no me equivoco, el compilador Microsoft C & C++ proporciona versiones seguras de estas funciones strcpy_s(),strcat_s() . Entonces, ¿por qué otros compiladores de C no los implementan oficialmente para brindar seguridad?
gets() es intrínsecamente inseguro, porque en general puede desbordar el objetivo si se reciben demasiados datos en stdin . Este:
char s[MANY]; gets(s); causará un comportamiento indefinido si se ingresan más de MANY caracteres y, por lo general, el programa no puede hacer nada para evitarlo.
strcpy() y strcat() se pueden usar de forma completamente segura , ya que pueden desbordar el destino solo si la cadena de origen es demasiado larga para estar contenida en la matriz de destino. La cadena de origen está contenida en un objeto de matriz que está bajo el control del propio programa, no de ninguna entrada externa. Por ejemplo, esto:
char s[100]; strcpy(s, "hello"); strcat(s, ", "); strcat(s, "world");posiblemente no se desborde a menos que se modifique el propio programa.
strncat() se puede usar como una versión más segura de strcat() , siempre que especifique el tercer argumento correctamente. Un problema con strncat() es que solo le brinda una forma de manejar el caso en el que no hay suficiente espacio en la matriz de destino: trunca silenciosamente la cadena. A veces, eso puede ser lo que desea, pero a veces es posible que desee detectar el desbordamiento y hacer algo al respecto.
En cuanto a strncpy() , no es simplemente una versión más segura de strcpy() . No es intrínsecamente peligroso, pero si no tiene mucho cuidado, puede dejar fácilmente la matriz de destino sin un carácter nulo '\0' terminación, lo que lleva a un comportamiento indefinido la próxima vez que lo pase a una función que espera un puntero a una cadena. Da la casualidad de que he escrito sobre esto .
strcpy y strcat no son similares a gets . El problema de gets es que se usa para leer desde la entrada, por lo que está fuera del control del programador si habrá un desbordamiento del búfer.
C99 Rational explica strncpy como:
Justificación de la Norma Internacional — Lenguajes de Programación — C §7.21.2.4 La función
strncpy
strncpyse introdujo inicialmente en la biblioteca C para tratar con campos de nombre de longitud fija en estructuras como entradas de directorio. Dichos campos no se usan de la misma manera que las cadenas: el nulo final no es necesario para un campo de longitud máxima, y establecer los bytes finales para nombres más cortos en nulo asegura comparaciones eficientes de campo.strncpyno es por origen una “strcpylimitada”, y el Comité prefirió reconocer la práctica existente en lugar de alterar la función para adaptarla mejor a dicho uso.
strcat() y strcpy() son funciones perfectamente seguras .
También tenga en cuenta que strncpy nunca tuvo la intención de ser una versión segura de strcpy . Se usa para un formato de cadena oscuro y obsoleto que se usaba en una versión antigua de Unix. strncpy es en realidad muy inseguro ( una de las muchas publicaciones de blog al respecto aquí ), a diferencia de strcpy , ya que muy pocos programadores parecen poder usar el primero sin producir errores fatales (sin terminación nula).
Una mejor pregunta es por qué el inherentemente inseguro strncpy() no se eliminó del lenguaje. ¿Hay alguien que trabaje mucho con oscuras cadenas de Unix de la década de 1970?