Pourquoi MSVC ++ considère-t-il que «std :: strcat» est «non sécurisé»? (C ++)

Quand j’essaie de faire des choses comme ça:

char* prefix = "Sector_Data\\sector"; char* s_num = "0"; std::strcat(prefix, s_num); std::strcat(prefix, "\\"); 

et ainsi de suite, je reçois un avertissement

 warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. 

Pourquoi strcat est-il considéré comme dangereux et existe-t-il un moyen de supprimer cet avertissement sans utiliser strcat_s?

De plus, si le seul moyen de se débarrasser de l’avertissement est d’utiliser strcat_s, comment cela fonctionne-t-il (syntaxe: en apparence, il ne prend pas deux arguments).

Parce que le tampon, le préfixe, peut avoir moins d’espace que vous ne le copiez, ce qui entraîne un dépassement de la mémoire tampon. Par conséquent, un pirate informatique peut transmettre une chaîne spécialement conçue qui écrase l’adresse de retour ou une autre mémoire critique et commence à exécuter du code dans le contexte de votre programme.

strcat_s résout ce problème en vous obligeant à indiquer la longueur du tampon dans lequel vous copiez la chaîne; si nécessaire, il tronquera la chaîne pour s’assurer que la mémoire tampon n’est pas saturée.

google strcat_s pour voir précisément comment l’utiliser.

Si vous utilisez c ++, pourquoi ne pas éviter tout le bazar et utiliser std::ssortingng . Le même exemple sans erreur ressemblerait à ceci:

 std::ssortingng prefix = "Sector_Data\\sector"; prefix += "0"; prefix += "\\" 

pas besoin de s’inquiéter de la taille des tampons et de tout ça. Et si vous avez une API qui prend un caractère const char * , vous pouvez simplement utiliser le membre .c_str() ;

 some_c_api(prefix.c_str()); 

C’est l’une des fonctions de manipulation de chaînes de C / C ++ pouvant entraîner des erreurs de saturation de la mémoire tampon.

Le problème est que la fonction ne sait pas quelle est la taille des tampons. De la documentation MSDN:

Le premier argument, strDestination, doit être suffisamment grand pour contenir la combinaison actuelle strDestination et strSource, ainsi qu’un ‘\ 0’ de clôture; sinon, un buffer excessif peut survenir

strcat_s prend un argument supplémentaire lui indiquant la taille du tampon. Cela lui permet de valider les tailles avant de faire le concat et d’éviter les dépassements. Voir http://msdn.microsoft.com/en-us/library/d45bbxx4.aspx

Vous pouvez vous débarrasser de ces avertissements en ajoutant:

 _CRT_SECURE_NO_WARNINGS 

et

 _SCL_SECURE_NO_WARNINGS 

aux définitions de pré-processeur de votre projet.

Pour désactiver l’avertissement, vous pouvez le faire.

 #pragma warning(disable:4996) 

Au fait, je vous recommande fortement d’utiliser strcat_s ().

Parce qu’il n’a aucun moyen de vérifier si la chaîne de destination (préfixe) de votre cas sera écrite au-delà de ses limites. strcat fonctionne essentiellement en boucle, en copiant octet par octet la chaîne source dans la destination. Il s’arrête quand il voit une valeur “0” (notée par ‘\ 0’) appelée terminal nul. Puisque C n’a pas de vérification intégrée des limites et que la chaîne de destination n’est qu’un emplacement dans la mémoire, strcat continuera à aller ad-infinidium même si elle dépasse la chaîne source ou la chaîne de destination. str n’a pas de terminal nul.

Les solutions ci-dessus sont spécifiques à la plate-forme de votre environnement Windows. Si vous voulez quelque chose de indépendant de la plateforme, vous devez vous débattre avec strncat:

 strncat(char* dest, const char* src, size_t count) 

Ceci est une autre option lorsqu’il est utilisé intelligemment. Vous pouvez utiliser count pour spécifier le nombre maximal de caractères à copier. Pour ce faire, vous devez déterminer combien d’espace est disponible dans dest (combien vous avez alloué – strlen (dest)) et le définir comme nombre.

Il y a deux problèmes avec strcat. Tout d’abord, vous devez effectuer toute votre validation en dehors de la fonction, en effectuant un travail presque identique à celui de la fonction:

 if(pDest+strlen(pDest)+strlen(pScr) < destSize) 

Vous devez marcher sur toute la longueur des deux cordes pour vous assurer qu’elles vont bien, avant de parcourir à nouveau leur longueur entière pour faire la copie. Pour cette raison, de nombreux programmeurs vont simplement supposer que le test convient et ignorer le test. Pire encore, il se peut que lorsque le code soit écrit pour la première fois, son adaptation soit garantie, mais lorsque quelqu'un ajoute un autre strcat, ou modifie une taille de tampon ou une constante ailleurs dans le programme, vous rencontrez maintenant des problèmes.

L'autre problème est de savoir si pSrc et pDst se chevauchent. Selon votre compilateur, strcat peut très bien être une simple boucle qui vérifie un caractère à la fois pour un 0 dans pSrc. Si pDst écrase ce 0, vous entrerez dans une boucle qui s'exécutera jusqu'à ce que votre programme se bloque.