Avertissement C6029

Dépassement de mémoire tampon possible dans l’appel à ' function'

Dépassement de mémoire tampon possible dans la fonction appelée en raison d’un paramètre de longueur/taille de mémoire tampon non case activée ed.

Notes

Cet avertissement indique que le code passe une taille non case activée ed à une fonction qui prend une mémoire tampon et une taille. Le code ne vérifie pas que les données lues à partir d’une source externe sont inférieures à la taille de la mémoire tampon. Un attaquant peut spécifier intentionnellement une valeur supérieure à la valeur attendue pour la taille, ce qui peut entraîner un dépassement de mémoire tampon. En général, chaque fois que vous lisez des données d'une source externe non fiable, pensez à vérifier leur validité. Il est approprié de vérifier la taille pour vous assurer qu’elle se trouve dans la plage attendue.

Nom de l’analyse du code : USING_TAINTED_DATA

Exemple

Le code suivant génère cet avertissement lorsqu’il appelle la fonction std::fread annotée deux fois. Le code utilise le premier appel pour déterminer la longueur des données à lire dans les appels ultérieurs. Après le premier appel, les marques dataSize d’analyse proviennent d’une source non approuvée. Par conséquent, lorsque le code transmet la valeur non approuvée au deuxième std::fread appel, l’analyseur génère cet avertissement. Un acteur malveillant peut modifier le fichier et provoquer le std::fread dépassement du buffer tableau. Dans le code réel, vous devez également gérer la récupération d’erreurs en fonction de la valeur de retour de std::fread. Par souci de simplicité, ces exemples abandonnent intentionnellement l’erreur code de récupération.

void processData(FILE* file)
{
    const size_t MAX_BUFFER_SIZE = 100;
    uint32_t buffer[MAX_BUFFER_SIZE]{};
    uint8_t dataSize = 0;

    // Read length data from the beginning of the file
    fread(&dataSize, sizeof(uint8_t), 1, file);
    // Read the rest of the data based on the dataSize
    fread(buffer, sizeof(uint32_t), dataSize, file);
}

Le correctif du problème dépend de la nature des données et du comportement de la fonction annotée qui déclenche le diagnostic. Pour plus d’informations, consultez la documentation de cette fonction. Un correctif simple consiste à case activée la taille avant le deuxième appel à std:fread. Dans l’exemple suivant, nous lèveons une exception pour mettre fin à la fonction. La plupart du code réel aurait plutôt une stratégie de récupération d’erreur spécifique au scénario.

void processData(FILE* file)
{
    const size_t MAX_BUFFER_SIZE = 100;
    uint32_t buffer[MAX_BUFFER_SIZE]{};
    uint8_t dataSize = 0;

    fread(&dataSize, sizeof(uint32_t), 1, file);

    if (dataSize > MAX_BUFFER_SIZE)
    {
        throw std::runtime_error("file data unexpected size");
    }

    fread(buffer, sizeof(uint32_t), dataSize, file);
}

Dans std:fread et des fonctions similaires, le code peut avoir besoin de lire de grandes quantités de données. Pour gérer les données volumineuses, vous pouvez allouer dynamiquement la taille de la mémoire tampon une fois la taille connue. Vous pouvez également appeler std:fread plusieurs fois si nécessaire pour lire dans le reste des données. Si vous allouez la mémoire tampon de manière dynamique, nous vous recommandons de limiter la taille pour éviter d’introduire une attaque hors mémoire pour les valeurs volumineuses. Nous n’utilisons pas cette approche dans notre exemple, car elle est déjà limitée par la taille de uint8_t.

void processDataDynamic(FILE* file)
{
    uint8_t dataSize = 0;
    fread(&dataSize, sizeof(uint8_t), 1, file);
    
    // Vector with `dataSize` default initialized objects
    std::vector<uint32_t> vecBuffer(dataSize);

    fread(&vecBuffer[0], sizeof(uint32_t), dataSize, file);
}
void processDataMultiple(FILE* file)
{
    const size_t MAX_BUFFER_SIZE = 100;
    uint32_t buffer[MAX_BUFFER_SIZE]{};
    uint8_t dataSize = 0;

    fread(&dataSize, sizeof(uint32_t), 1, file);

    while( dataSize > 0 )
    {
        size_t readSize = dataSize > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : dataSize;
        readSize = fread(buffer, sizeof(uint32_t), readSize, file);
        dataSize = dataSize - readSize;
        // Process the data in `buffer`...
    }
}

Voir aussi

Ensembles de règles pour le code C++
Utilisation des annotations SAL pour réduire les défauts de code