Question

EDIT: J'ai ajouté la source de l'exemple.

Je suis tombé sur cet exemple:

char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;

/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);

/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );

Qui ont produit cette sortie:

destination is originally = 'abcdefg'
After strcpy, destination becomes '123456789'

destination1 is originally = 'abcdefg'
After strncpy, destination1 becomes '12345fg'

Ce qui me fait me demander pourquoi quelqu'un voudrait cet effet. On dirait que ce serait déroutant. Ce programme me fait penser que vous pourriez essentiellement copier le nom de quelqu'un (par exemple Tom Brokaw) avec Tom Bro763.

Quels sont les avantages de l'utilisation strncpy() plus de strcpy()?

Était-ce utile?

La solution

strncpy combat le débordement de tampon en vous obligeant à y mettre une longueur. strcpy dépend d'une traîne \0, ce qui peut ne pas toujours se produire.

Deuxièmement, pourquoi vous avez choisi de copier uniquement 5 caractères sur 7 caractères String me dépasse, mais cela produit un comportement attendu. Il ne fait que copier sur le premier n personnages, où n est le troisième argument.

La n Les fonctions sont toutes utilisées comme codage défensif contre les débordements tampons. Veuillez les utiliser au lieu d'anciennes fonctions, telles que strcpy.

Autres conseils

La strncpy() La fonction a été conçue avec un problème très particulier à l'esprit: manipuler les chaînes stockées à la manière des entrées de répertoire UNIX originales. Ceux-ci ont utilisé un réseau de taille fixe et un terminateur Nul n'a été utilisé que si le nom de fichier était plus court que le tableau.

C'est ce qui est derrière les deux bizarreries de strncpy():

  • Il ne met pas un num-terminateur sur la destination s'il est complètement rempli; et
  • Il remplit toujours complètement la destination, avec des NUL si nécessaire.

Pour un "plus sûr strcpy()", tu ferais mieux d'utiliser strncat() ainsi:

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

Cela terminera toujours le résultat et ne copiera pas plus que nécessaire.

Alors que je connais l'intention derrière strncpy, ce n'est pas vraiment une bonne fonction. Évitez les deux. Raymond Chen explique.

Personnellement, ma conclusion est simplement d'éviter strncpy Et tous ses amis si vous avez affaire à des cordes à terminaison nulle. Malgré le "STR" dans le nom, ces fonctions ne produisent pas de cordes à terminaison nulle. Ils convertissent une chaîne à terminaison nulle en un tampon de caractère brut. Les utiliser là où une chaîne à terminaison nulle est attendue car le deuxième tampon est tout à fait faux. Non seulement vous ne parvenez pas à obtenir une terminaison nulle appropriée si la source est trop longue, mais si la source est courte, vous obtenez un rembourrage nul inutile.

Voir également Pourquoi Strncpy est-il insécurisé?

Strncpy n'est pas plus sûr que Strcpy, il échange simplement un type de bugs avec un autre. En C, lors de la gestion des chaînes C, vous devez connaître la taille de vos tampons, il n'y a aucun moyen de contourner cela. Strncpy a été justifié pour le répertoire mentionné par les autres, mais sinon, vous ne devriez jamais l'utiliser:

  • Si vous connaissez la longueur de votre chaîne et de votre tampon, pourquoi utiliser strncpy? C'est un gaspillage de puissance de calcul au mieux (ajoutant inutile 0)
  • Si vous ne connaissez pas les longueurs, vous risquez de tronquer silencieusement vos cordes, ce qui n'est pas beaucoup mieux qu'un débordement de tampon

Ce que vous recherchez, c'est la fonction strlcpy() qui termine toujours la chaîne avec 0 et initialise le tampon. Il est également capable de détecter les débordements. Seul le problème, ce n'est pas (vraiment) portable et n'est présent que sur certains systèmes (BSD, Solaris). Le problème avec cette fonction est qu'il ouvre une autre boîte de vers comme le montre les discussions surhttp://en.wikipedia.org/wiki/strlcpy

Mon opinion personnelle est qu'il est beaucoup plus utile que strncpy() et strcpy(). Il a de meilleures performances et est un bon compagnon pour snprintf(). Pour les plateformes qui ne l'ont pas, il est relativement facile à mettre en œuvre. (Pour la phase de développement d'une application, je remplace ces deux fonctions (snprintf() et strlcpy()) Avec une version de piégeage qui interdit brutalement le programme sur les débordements de tampon ou les troncatures. Cela permet d'attraper rapidement les pires contrevenants. Surtout si vous travaillez sur une base de code de quelqu'un d'autre.

ÉDITER: strlcpy() Peut être mis en œuvre facilement:

size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
  size_t len = strlen(src);
  if(dstsize) {
    size_t bl = (len < dstsize-1 ? len : dstsize-1);
    ((char*)memcpy(dst, src, bl))[bl] = 0;
  }
  return len;
}

La strncpy() La fonction est la plus sûre: vous devez passer la longueur maximale que le tampon de destination peut accepter. Sinon, il pourrait arriver que la chaîne source ne soit pas correctement terminée strcpy() La fonction pourrait écrire plus de caractères vers la destination, corrompant tout ce qui est dans la mémoire après le tampon de destination. Ceci est le problème de contrericité de tampon utilisé dans de nombreux exploits

Également pour les fonctions API POSIX comme read() qui ne met pas le terminaison 0 dans le tampon, mais renvoie le nombre d'octets lus, vous mettrez soit manuellement le 0, soit le copier à l'aide strncpy().

Dans votre exemple de code, index n'est en fait pas un index, mais un count - il dit combien de personnages au plus pour copier de la source à la destination. S'il n'y a pas d'octet nulle parmi les n octets de première source, la chaîne placée dans la destination ne sera pas terminée nul

Strncpy remplit la destination avec ' 0' pour la taille de la source, bien que la taille de la destination soit plus petite ...

MANPAGE:

Si la longueur de SRC est inférieure à N, strncpy () remporte le reste de DEST avec des octets nuls.

Et pas seulement le reste ... Aussi après cela jusqu'à ce que N les personnages soient atteints. Et ainsi vous obtenez un débordement ... (voir l'implémentation de la page de l'homme)

Cela peut être utilisé dans de nombreux autres scénarios, où vous devez copier seulement une partie de votre chaîne d'origine vers la destination. À l'aide de strncpy (), vous pouvez copier une partie limitée de la chaîne d'origine par opposition par strcpy (). Je vois que le code que vous avez mis vient publib.boulder.ibm.com.

Cela dépend de notre exigence. Pour les utilisateurs de Windows

Nous utilisons Strncpy chaque fois que nous ne voulons pas copier une chaîne entière ou que nous voulons copier uniquement n nombre de caractères. Mais Strcpy copie toute la chaîne, y compris la terminaison du caractère nul.

Ces liens vous aideront davantage à en savoir plus sur Strcpy et Strncpy et où nous pouvons utiliser.

À propos de Strcpy

À propos de strncpy

Le strncpy est une version plus sûre de Strcpy en fait, vous ne devez jamais utiliser Strcpy parce que sa vulnérabilité potentielle de débordement de tampon qui vous rend Vulnérable System à toutes sortes d'attaques

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top