Condividi tramite


Avviso C6029

Possibile sovraccarico del buffer nella chiamata a 'function'

Possibile sovraccarico del buffer nella funzione chiamata a causa di un parametro di lunghezza/dimensione del buffer non selezionato.

Osservazioni:

Questo avviso indica che il codice passa una dimensione deselezionata a una funzione che accetta un buffer e una dimensione. Il codice non verifica che i dati letti da un'origine esterna siano inferiori alle dimensioni del buffer. Un utente malintenzionato potrebbe specificare intenzionalmente un valore maggiore del previsto per le dimensioni, che può causare un sovraccarico del buffer. In genere, quando si leggono i dati da un'origine esterna non attendibile, è consigliabile accertarsi di verificarne la validità. È opportuno verificare le dimensioni per assicurarsi che si tratti dell'intervallo previsto.

Nome dell'analisi del codice: USING_TAINTED_DATA

Esempio

Il codice seguente genera questo avviso quando chiama la funzione std::fread annotata due volte. Il codice usa la prima chiamata per determinare la lunghezza dei dati da leggere nelle chiamate successive. Dopo la prima chiamata, l'analisi contrassegna dataSize come proveniente da un'origine non attendibile. Pertanto, quando il codice passa il valore non attendibile alla seconda std::fread chiamata, l'analizzatore genera questo avviso. Un attore malintenzionato potrebbe modificare il file e causare l'overflow della buffer chiamata alla std::fread matrice. Nel codice reale è necessario gestire anche il ripristino degli errori in base al valore restituito di std::fread. Per semplicità, questi esempi lasciano intenzionalmente fuori il codice di ripristino degli errori.

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);
}

La correzione per il problema dipende dalla natura dei dati e dal comportamento della funzione annotata che attiva la diagnostica. Per altre informazioni, vedere la documentazione per tale funzione. Una correzione semplice consiste nel controllare le dimensioni prima della seconda chiamata a std:fread. Nell'esempio seguente viene generata un'eccezione per terminare la funzione. La maggior parte del codice reale avrà invece una strategia di ripristino degli errori specifica per lo scenario.

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);
}

In std:fread e funzioni simili, il codice potrebbe dover leggere grandi quantità di dati. Per gestire dati di grandi dimensioni, è possibile allocare dinamicamente le dimensioni del buffer dopo che le dimensioni diventano note. In alternativa, è possibile chiamare std:fread più volte in base alle esigenze per leggere il resto dei dati. Se si alloca il buffer in modo dinamico, è consigliabile impostare un limite sulle dimensioni per evitare di introdurre un exploit di memoria insufficiente per valori di grandi dimensioni. Questo approccio non viene usato nell'esempio perché è già vincolato dalle dimensioni di 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`...
    }
}

Vedi anche

Set di regole per il codice C++
Uso delle annotazioni SAL per ridurre i difetti del codice