Advertencia C6029

Posible saturación del búfer en la llamada a "function"

Posible saturación del búfer en la función llamada debido a un parámetro de longitud o tamaño del búfer no activado.

Comentarios

Esta advertencia indica que el código pasa un tamaño sin marcar a una función que toma un búfer y un tamaño. El código no comprueba que los datos leídos de algún origen externo sean menores que el tamaño del búfer. Un atacante podría especificar intencionadamente un valor mayor del esperado para el tamaño, lo que puede provocar una saturación del búfer. Por lo general, cada vez que se lean los datos desde un origen externo que no sea de confianza, asegúrese de comprobar su validez. Es adecuado comprobar el tamaño para asegurarse de que está en el intervalo esperado.

Nombre del análisis de código: USING_TAINTED_DATA

Ejemplo

El código siguiente genera esta advertencia cuando llama a la función std::fread anotada dos veces. El código usa la primera llamada para determinar la longitud de los datos que se van a leer en llamadas posteriores. Después de la primera llamada, el análisis marca dataSize como procedente de un origen que no es de confianza. Por lo tanto, cuando el código pasa el valor que no es de confianza a la segunda std::fread llamada, el analizador genera esta advertencia. Un actor malintencionado podría modificar el archivo y hacer que la llamada a std::fread desbordar la buffer matriz. En el código real, también debe controlar la recuperación de errores en función del valor devuelto de std::fread. Por motivos de simplicidad, estos ejemplos abandonan intencionadamente el código de recuperación de errores.

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 corrección del problema depende de la naturaleza de los datos y del comportamiento de la función anotada que desencadena el diagnóstico. Para obtener más información, consulte la documentación de esa función. Una corrección sencilla consiste en comprobar el tamaño antes de la segunda llamada a std:fread. En el ejemplo siguiente, se produce una excepción para finalizar la función. En su lugar, la mayoría del código real tendría una estrategia de recuperación de errores específica del escenario.

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

En std:fread y funciones similares, el código puede necesitar leer grandes cantidades de datos. Para controlar datos grandes, puede asignar el tamaño del búfer dinámicamente después de que se conozca el tamaño. O bien, puede llamar a std:fread varias veces según sea necesario para leer en el resto de los datos. Si asigna el búfer dinámicamente, se recomienda colocar un límite en el tamaño para evitar la introducción de una vulnerabilidad de vulnerabilidad de memoria insuficiente para valores grandes. No usamos este enfoque en nuestro ejemplo porque ya está limitado por el tamaño 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`...
    }
}

Consulte también

Conjuntos de reglas para código de C++
Uso de anotaciones SAL para reducir los defectos en el código