Dela via


Skydda överbelastningar av mallar

Microsoft har avskrivit många funktioner i C Runtime-biblioteket till förmån för mer säkerhetsförbättrade versioner. Är till exempel strcpy_s den säkrare ersättningen för strcpy. De inaktuella funktionerna är vanliga källor till säkerhetsbuggar eftersom de inte förhindrar åtgärder som kan skriva över minnet. Som standard skapar kompilatorn en utfasningsvarning när du använder någon av dessa funktioner. CRT tillhandahåller överlagringar av C++-mallar för dessa funktioner för att underlätta övergången till säkrare varianter.

Det här kodfragmentet genererar till exempel en varning eftersom strcpy det är inaktuellt:

char szBuf[10];
strcpy(szBuf, "test"); // warning: deprecated

Utfasningsvarningen finns där för att berätta att din kod kan vara osäker. Om du har kontrollerat att koden inte kan skriva över minnet har du flera alternativ. Du kan välja att ignorera varningen, du kan definiera symbolen _CRT_SECURE_NO_WARNINGS innan inkluderingssatserna för CRT-huvudena för att ignorera varningen, eller så kan du uppdatera koden så att den använder strcpy_s:

char szBuf[10];
strcpy_s(szBuf, 10, "test"); // security-enhanced _s function

Mallöverlagringarna ger fler alternativ. Om du definierar _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES till 1 möjliggör det mallöverlagringar av standard-CRT-funktioner som anropar de säkrare varianterna automatiskt. Om _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES är 1 krävs inga ändringar i koden. I bakgrunden ändras anropet till strcpy till ett anrop till strcpy_s med det storleksargument som anges automatiskt.

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

// ...

char szBuf[10];
strcpy(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")

Makrot _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES påverkar inte de funktioner som tar ett antal, till exempel strncpy. För att aktivera överlagring av mallar för räknefunktionerna definierar du _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT till 1. Innan du gör det måste du dock se till att koden skickar antalet tecken, inte storleken på bufferten (ett vanligt misstag). Dessutom är det onödigt med kod som uttryckligen skriver ett null-tecken i slutet av bufferten efter funktionsanropet, om den säkra variantens funktionsanrop används. Om du behöver trunkeringsbeteende kan du läsa _TRUNCATE.

Anmärkning

Makrot _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT kräver att det _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES även definieras som 1. Om _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT definieras som 1 och _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES definieras som 0 utför programmet inga överlagringar av mallar.

När du definierar _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES till 1 möjliggör det överlagring av mallar för de säkra varianterna (namn som slutar med "_s"). I det här fallet, om _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES är 1, måste en liten ändring göras i den ursprungliga koden:

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1

// ...

char szBuf[10];
strcpy_s(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")

Endast namnet på funktionen behöver ändras (genom att lägga till "_s"); mallöverlagringen tar hand om att ange storleksargumentet.

Som standard _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES definieras och _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT som 0 (inaktiverad) och _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES definieras som 1 (aktiverad).

Mallöverlagringarna fungerar bara för statiska matriser. Dynamiskt allokerade buffertar kräver andra ändringar i källkoden. Gå tillbaka till exemplen ovan:

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

// ...

char *szBuf = (char*)malloc(10);
strcpy(szBuf, "test"); // still deprecated; change it to
                       // strcpy_s(szBuf, 10, "test");

Och det här exemplet:

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1

// ...

char *szBuf = (char*)malloc(10);
strcpy_s(szBuf, "test"); // doesn't compile; change it to
                         // strcpy_s(szBuf, 10, "test");

Se även

Säkerhetsfunktioner i CRT
.lib