Le problème est ici:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Si la chaîne est supérieure à la longueur du tampon cible, strncpy la copiera toujours. Vous basez le nombre de caractères de la chaîne comme le nombre à copier au lieu de la taille du tampon. La bonne façon de procéder est la suivante:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Cela limite la quantité de données copiées à la taille réelle de la mémoire tampon moins un pour le caractère de fin nul. Ensuite, nous définissons le dernier octet du tampon sur le caractère nul en tant que sauvegarde supplémentaire. La raison en est que strncpy copiera jusqu'à n octets, y compris le null de fin, si strlen (str) <len - 1. Sinon, le null n'est pas copié et vous avez un scénario de plantage car maintenant votre tampon a un non terminé chaîne.
J'espère que cela t'aides.
EDIT: Après un examen plus approfondi et des contributions d'autres personnes, un codage possible pour la fonction suit:
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);
}
Puisque nous connaissons déjà la longueur de la chaîne, nous pouvons utiliser memcpy pour copier la chaîne de l'emplacement référencé par str dans le tampon. Notez que d'après la page de manuel de strlen (3) (sur un système FreeBSD 9.3), ce qui suit est indiqué:
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.
Ce que j'interprète comme étant que la longueur de la chaîne n'inclut pas le null. C'est pourquoi je copie len + 1 octets pour inclure la valeur null, et le test vérifie que la longueur <taille du tampon - 2. Moins un car le tampon commence à la position 0, et moins un autre pour s'assurer qu'il y a de la place pour le nul.
EDIT: Il s'avère que la taille de quelque chose commence par 1 tandis que l'accès commence par 0, donc le -2 avant était incorrect car il renverrait une erreur pour tout ce qui> 98 octets mais il devrait être> 99 octets.
EDIT: Bien que la réponse à propos d'un court non signé soit généralement correcte car la longueur maximale pouvant être représentée est de 65 535 caractères, cela n'a pas vraiment d'importance car si la chaîne est plus longue que cela, la valeur s'enroulera. C'est comme prendre 75,231 (qui est 0x000125DF) et masquer les 16 premiers bits vous donnant 9695 (0x000025DF). Le seul problème que je vois avec ceci est les 100 premiers caractères après 65 535 car la vérification de la longueur autorisera la copie, mais elle ne copiera que les 100 premiers caractères de la chaîne dans tous les cas et la valeur null terminera la chaîne . Ainsi, même avec le problème de bouclage, le tampon ne sera toujours pas débordé.
Cela peut ou non poser en soi un risque de sécurité en fonction du contenu de la chaîne et de l'utilisation que vous en faites. S'il ne s'agit que d'un texte simple lisible par l'homme, il n'y a généralement pas de problème. Vous obtenez juste une chaîne tronquée. Cependant, si c'est quelque chose comme une URL ou même une séquence de commandes SQL, vous pourriez avoir un problème.