Pourquoi PVS-Studio utilise l'analyse de flux de données: en raison d'une erreur intéressante dans la bibliothèque d'importation d'actifs ouverts

PVS-Studio - Analyse des flux de données

L'analyse des flux de données fait partie intégrante de tout analyseur de code statique moderne. Cependant, de l'extérieur, on ne sait pas très bien ce que c'est et ce qui est le plus important - pourquoi cela est nécessaire. Jusqu'à présent, certaines personnes associaient l'analyse statique à la recherche de quelque chose dans le code selon un certain modèle. Par conséquent, de temps en temps, nous écrivons des notes dans lesquelles nous démontrons comment telle ou telle technologie, utilisée dans l'analyseur PVS-Studio, aide à révéler une autre erreur intéressante. Aujourd'hui est justement un tel article dans lequel nous examinerons un bogue dans l'une des implémentations du standard d'encodage de données binaires Base64.







Tout a commencé par la vérification de la dernière version de la bibliothèque Qt 6. C'était un article classique séparé , où j'ai décrit 77 erreurs trouvées. Il se trouve qu'au début, j'ai décidé de parcourir le rapport, sans masquer encore les avertissements liés aux bibliothèques tierces. En d'autres termes, je n'ai pas désactivé les avertissements liés à \ src \ 3rdparty dans les paramètres. Et il se trouve que je suis immédiatement tombé sur un exemple intéressant d'erreur dans la bibliothèque d'importation d'actifs ouverts , à propos de laquelle j'ai décidé de faire cette petite note séparée.







, , 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