55 votes

Quelles fonctions de la bibliothèque standard du langage C encouragent les mauvaises pratiques ?

Ceci est inspiré par cette question et les commentaires sur une réponse particulière dans laquelle j'ai appris que strncpy n'est pas une fonction de traitement des chaînes de caractères très sûre en C et qu'elle remplit les zéros, jusqu'à ce qu'elle atteigne n ce dont je n'étais pas conscient.

Plus précisément, pour citer R..

strncpy ne termine pas à zéro, et le reste du tampon de destination, ce qui est tampon de destination, ce qui est un énorme perte de temps. Vous pouvez contourner le premier en ajoutant votre propre null padding, mais pas le second. Le site n'a jamais été conçu pour être utilisé comme un fonction de "manipulation sûre des chaînes de caractères", mais pour travailler avec des champs de taille fixe dans les et les fichiers de base de données. snprintf(dest, n, "%s", src) est la seule fonction de seul "strcpy sûr" correct en C standard, mais il est C standard, mais il est probable qu'elle soit beaucoup plus lente. D'ailleurs, la troncature en elle-même peut être un bogue majeur et, dans certains cas, peut conduire à une élévation de privilèges ou à un DoS, donc de jeter des fonctions de chaîne "sûres" qui qui tronquent leur sortie en cas de problème n'est pas problème n'est pas une façon de le rendre "sûr" ou ou "sécurisé". Au lieu de cela, vous devez vous assurer que le tampon de destination est de la la bonne taille et utiliser simplement strcpy (ou mieux encore, memcpy si vous connaissez déjà la longueur de la chaîne source).

Et de Jonathan Leffler

Notez que l'interface de strncat() est encore plus encore plus confuse dans son interface que strncpy() - quel est exactement cet argument de longueur longueur, déjà ? Ce n'est pas ce que Ce n'est pas ce que l'on attendrait en fonction de ce que l'on fournit strncpy() etc - il est donc plus sujet à des erreurs d'erreurs, même que strncpy(). Pour copier des chaînes de caractères, je suis de plus en plus l'opinion qu'il y a un argument fort pour arguments pour dire que vous n'avez besoin que de memmove() parce que vous connaissez toujours toutes les tailles à l'avance et on s'assure qu'il y a qu'il y a assez d'espace à l'avance. Utilisez memmove() de préférence à l'une des méthodes suivantes strcpy(), strcat(), strncpy(), strncat(), memcpy().

Donc, je suis clairement un peu rouillé sur la bibliothèque standard C. Par conséquent, je voudrais poser la question :

Quelles fonctions de la bibliothèque standard C sont utilisées de manière inappropriée/d'une manière qui peut causer/entraîner des problèmes de sécurité/des défauts de code/des inefficacités ?

Dans un souci d'objectivité, j'ai un certain nombre de critères pour une réponse :

  • Veuillez, si vous le pouvez, citer les raisons de la conception de la fonction en question, c'est-à-dire sa finalité.
  • Veuillez mettre en évidence le mauvais usage qui est fait de ce code.
  • Veuillez indiquer pourquoi cette mauvaise utilisation peut conduire à un problème. Je sais que cela devrait être évident mais cela évite les réponses molles.

Veuillez éviter :

  • Débats sur les conventions de dénomination des fonctions (sauf lorsque cela entraîne sans équivoque une confusion).
  • "Je préfère x à y" - les préférences sont acceptables, nous en avons tous, mais je m'intéresse aux effets secondaires inattendus et à la manière de s'en prémunir.

Comme cette question est susceptible d'être considérée comme subjective et qu'elle n'a pas de réponse définitive, je la signale d'emblée au wiki communautaire.

Je travaille également selon la norme C99.

34voto

icecrime Points 23650

Quelles fonctions de la bibliothèque standard C sont utilisées de manière inappropriée/de façon à causer/conduire à des problèmes de sécurité/des défauts de code/des inefficacités ?

Je vais aller avec l'évident :

char *gets(char *s);

Avec sa particularité remarquable qu'il est tout simplement impossible de l'utiliser de manière appropriée.

25voto

mizo Points 3783

Un piège commun avec le strtok() est de supposer que la chaîne analysée reste inchangée, alors qu'elle remplace en réalité le caractère séparateur par le caractère '\0' .

Aussi, strtok() est utilisé en faisant des appels ultérieurs, jusqu'à ce que la chaîne entière soit tokenisée. Certaines implémentations de bibliothèques stockent strtok() dans une variable globale, ce qui peut provoquer des surprises désagréables, si l'on veut que l'état interne de l'utilisateur soit pris en compte. strtok() est appelé depuis plusieurs threads en même temps.

El Norme de codage sécurisé CERT C énumère beaucoup de ces pièges dont vous avez parlé.

21voto

caf Points 114951

Dans presque tous les cas, atoi() ne doit pas être utilisé (ceci s'applique également à atof() , atol() y atoll() ).

Cela est dû au fait que ces fonctions ne détectent pas du tout les erreurs hors gamme - la norme dit simplement "Si la valeur du résultat ne peut être représentée, le comportement est indéfini". . Ainsi, la seule fois où ils peuvent être utilisés en toute sécurité est si vous pouvez prouver que l'entrée sera certainement dans la plage (par exemple, si vous passez une chaîne de longueur 4 ou moins à atoi() il ne peut pas être hors de portée).

Au lieu de cela, utilisez l'un des strtol() famille de fonctions.

11voto

Jens Gustedt Points 40410

Étendons la question aux interfaces dans un sens plus large.

errno :

techniquement, ce n'est même pas clair ce que c'est, une variable, une macro, un appel de fonction implicite ? Dans la pratique, sur les systèmes modernes, il s'agit le plus souvent d'une macro qui se transforme en appel de fonction pour avoir un état d'erreur spécifique au thread. C'est un mal :

  • parce que cela peut entraîner une surcharge pour l'appelant l'appelant accède à la valeur, vérifie l'"erreur" (qui peut être simplement un événement exceptionnel)
  • car il impose même à certains endroits que l'appelant efface cette "variable" avant d'effectuer un appel à la bibliothèque.
  • car il implémente une erreur simple retour en fixant un état global, de la bibliothèque.

La norme à venir obtient la définition de errno un peu plus droit, mais ces laideurs restent

6voto

davep Points 178

Il y a souvent un strtok_r.

Pour la réallocation, si vous devez utiliser l'ancien pointeur, il n'est pas très difficile d'utiliser une autre variable. Si votre programme échoue avec une erreur d'allocation, le nettoyage de l'ancien pointeur n'est souvent pas vraiment nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X