O problema está aqui:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Se a string for maior que o comprimento do buffer de destino, o strncpy ainda a copiará. Você está baseando o número de caracteres da sequência como o número a ser copiado em vez do tamanho do buffer. A maneira correta de fazer isso é a seguinte:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
O que isso faz é limitar a quantidade de dados copiados para o tamanho real do buffer menos um para o caractere final nulo. Em seguida, definimos o último byte no buffer para o caractere nulo como uma proteção adicional. A razão para isso é que o strncpy copiará até n bytes, incluindo o nulo final, se strlen (str) <len - 1. Caso contrário, o nulo não será copiado e você terá um cenário de falha, porque agora seu buffer não possui terminação. corda.
Espero que isto ajude.
EDIT: Após um exame mais aprofundado e contribuições de outras pessoas, segue uma codificação possível para a função:
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 já sabemos o comprimento da string, podemos usar o memcpy para copiar a string do local referenciado por str no buffer. Observe que, na página de manual do strlen (3) (em um sistema FreeBSD 9.3), o seguinte é indicado:
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.
O que eu interpreto é que o comprimento da string não inclui o nulo. É por isso que copio len + 1 bytes para incluir o nulo, e o teste verifica se o comprimento <tamanho do buffer - 2. Menos um porque o buffer inicia na posição 0 e menos outro para garantir que haja espaço para o nulo.
EDIT: Acontece que o tamanho de algo começa com 1 enquanto o acesso começa com 0; portanto, o -2 anterior estava incorreto porque retornaria um erro para qualquer coisa> 98 bytes, mas deveria ser> 99 bytes.
EDIT: Embora a resposta sobre um curto não assinado esteja geralmente correta, já que o comprimento máximo que pode ser representado é 65.535 caracteres, isso realmente não importa, porque se a string for maior que isso, o valor será contornado. É como pegar 75.231 (que é 0x000125DF) e mascarar os 16 bits principais, fornecendo 9695 (0x000025DF). O único problema que vejo com isso são os primeiros 100 caracteres após 65.535, pois a verificação de comprimento permitirá a cópia, mas copiará até os 100 primeiros caracteres da string em todos os casos e terminará nula . Portanto, mesmo com o problema abrangente, o buffer ainda não será excedido.
Isso pode ou não representar, por si só, um risco de segurança, dependendo do conteúdo da string e para o que você a está usando. Se é apenas texto simples legível por humanos, geralmente não há problema. Você acabou de obter uma string truncada. No entanto, se for algo como uma URL ou mesmo uma sequência de comandos SQL, você poderá ter um problema.