Por qué PVS-Studio utiliza el análisis de flujo de datos: debido a un error interesante en la biblioteca de importación de activos abiertos

PVS-Studio - Análisis de flujo de datos

El análisis de flujo de datos es una parte integral de cualquier analizador de código estático moderno. Sin embargo, desde el exterior, no está muy claro qué es esto y qué es más importante, por qué es necesario. Hasta ahora, algunas personas asocian el análisis estático con la búsqueda de algo en el código de acuerdo con un patrón determinado. Por eso, de vez en cuando escribimos notas en las que demostramos cómo esta o aquella tecnología, utilizada en el analizador PVS-Studio, ayuda a revelar otro error interesante. Hoy es un artículo de este tipo en el que consideraremos un error en una de las implementaciones del estándar de codificación de datos binarios Base64.







Todo comenzó con la verificación de la última versión de la biblioteca Qt 6. Este era un artículo clásico separado , donde describí 77 errores encontrados. Dio la casualidad de que al principio decidí hojear el informe, sin ocultar todavía las advertencias relacionadas con las bibliotecas de terceros. En otras palabras, no he desactivado las advertencias relacionadas con \ src \ 3rdparty en la configuración. Y sucedió que inmediatamente me encontré con un ejemplo interesante de un error en la Biblioteca de importación de activos abiertos , sobre el cual decidí hacer esta pequeña nota por separado.







, , PVS-Studio, . . , , ", PVS-Studio ".







, , , Open Asset Import Library (assimp). : \src\3rdparty\assimp\src\code\FBX\FBXUtil.cpp.







std::string EncodeBase64(const char* data, size_t length)
{
    // calculate extra bytes needed to get a multiple of 3
    size_t extraBytes = 3 - length % 3;

    // number of base64 bytes
    size_t encodedBytes = 4 * (length + extraBytes) / 3;

    std::string encoded_string(encodedBytes, '=');

    // read blocks of 3 bytes
    for (size_t ib3 = 0; ib3 < length / 3; ib3++)
    {
        const size_t iByte = ib3 * 3;
        const size_t iEncodedByte = ib3 * 4;
        const char* currData = &data[iByte];

        EncodeByteBlock(currData, encoded_string, iEncodedByte);
    }

    // if size of data is not a multiple of 3,
    // also encode the final bytes (and add zeros where needed)
    if (extraBytes > 0)
    {
        char finalBytes[4] = { 0,0,0,0 };
        memcpy(&finalBytes[0], &data[length - length % 3], length % 3);

        const size_t iEncodedByte = encodedBytes - 4;
        EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte);

        // add '=' at the end
        for (size_t i = 0; i < 4 * extraBytes / 3; i++)
            encoded_string[encodedBytes - i - 1] = '=';
    }
    return encoded_string;
}
      
      





, . , , Base64 :). :







  1. 31 ;
  2. ;
  3. legacy .


Ok, . Base64. 64 . - A-Z, a-z 0-9 (62 ) 2 , . 3 4 .







, , "=". . .







, . , . , , - . "- " : V547 [CWE-571] Expression 'extraBytes > 0' is always true. FBXUtil.cpp 224







, , extraBytes:







// calculate extra bytes needed to get a multiple of 3
size_t extraBytes = 3 - length % 3;
      
      





, , 3. 3. :







size_t extraBytes = length % 3;
      
      





, , , 5 , 5 % 3 = 2, 2 . 6 , , 6 % 3 = 0.







, , . :







size_t extraBytes = (3 - length % 3) % 3;
      
      





, . , :







size_t extraBytes = 3 - length % 3;
      
      





. length, [0..2]. PVS-Studio , . . . Value Range Analysis. .







:







size_t extraBytes = 3 - [0..2];
      
      





, extraBytes . : [1..3].







, . , , , :







if (extraBytes > 0)
      
      





, , , , , , , .







, , , . . , 6 . 8 . , .







// calculate extra bytes needed to get a multiple of 3
size_t extraBytes = 3 - length % 3; // 3-6%3 = 3

// number of base64 bytes
size_t encodedBytes = 4 * (length + extraBytes) / 3; // 4*(6+3)/3 = 12

std::string encoded_string(encodedBytes, '=');
      
      





, 12 , 8. – .







. , - , , Base64. , , , " , ".







PVS-Studio , . :). , . .







, : Andrey Karpov. Why PVS-Studio Uses Data Flow Analysis: Based on Gripping Error in Open Asset Import Library.








All Articles