El problema está aquí:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Si la cadena es mayor que la longitud del búfer de destino, strncpy aún la copiará. Está basando el número de caracteres de la cadena como el número a copiar en lugar del tamaño del búfer. La forma correcta de hacer esto es la siguiente:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Lo que esto hace es limitar la cantidad de datos copiados al tamaño real del búfer menos uno para el carácter de terminación nulo. Luego establecemos el último byte en el búfer al carácter nulo como salvaguarda adicional. La razón de esto es porque strncpy copiará hasta n bytes, incluido el nulo de terminación, si strlen (str) <len - 1. Si no, entonces el nulo no se copia y tiene un escenario de bloqueo porque ahora su búfer tiene un no terminado cuerda.
Espero que esto ayude.
EDITAR: Tras un examen adicional y la entrada de otros, sigue una posible codificación para la función:
int func (char *str)
{
char buffer[100];
unsigned short size = sizeof(buffer);
unsigned short len = strlen(str);
if (len > size - 1) return(-1);
memcpy(buffer, str, len + 1);
buffer[size - 1] = '\0';
return(0);
}
Como ya conocemos la longitud de la cadena, podemos usar memcpy para copiar la cadena de la ubicación a la que hace referencia str en el búfer. Tenga en cuenta que según la página del manual para strlen (3) (en un sistema FreeBSD 9.3), se establece lo siguiente:
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
Lo que interpreto es que la longitud de la cadena no incluye el nulo. Es por eso que copio len + 1 bytes para incluir el valor nulo, y la prueba verifica para asegurar que la longitud <tamaño del búfer - 2. Menos uno porque el búfer comienza en la posición 0, y menos otro para asegurarse de que haya espacio para el nulo
EDITAR: Resulta que el tamaño de algo comienza con 1 mientras que el acceso comienza con 0, por lo que -2 antes era incorrecto porque devolvería un error para cualquier cosa> 98 bytes pero debería ser> 99 bytes.
EDITAR: Aunque la respuesta sobre un corto sin signo es generalmente correcta, ya que la longitud máxima que se puede representar es 65.535 caracteres, en realidad no importa porque si la cadena es más larga que eso, el valor se ajustará. Es como tomar 75,231 (que es 0x000125DF) y enmascarar los 16 bits superiores para obtener 9695 (0x000025DF). El único problema que veo con esto son los primeros 100 caracteres más allá de 65,535, ya que la verificación de longitud permitirá la copia, pero solo copiará hasta los primeros 100 caracteres de la cadena en todos los casos y nulo terminará la cadena . Entonces, incluso con el problema envolvente, el búfer aún no se desbordará.
Esto puede o no en sí mismo representar un riesgo de seguridad dependiendo del contenido de la cadena y para qué lo está utilizando. Si se trata solo de texto directo que es legible para los humanos, entonces generalmente no hay problema. Solo obtienes una cadena truncada. Sin embargo, si es algo así como una URL o incluso una secuencia de comandos SQL, podría tener un problema.