Analisis aliran data merupakan bagian integral dari penganalisis kode statis modern. Namun, dari luar, tidak begitu jelas apa ini dan apa yang paling penting - mengapa ini diperlukan. Hingga saat ini, beberapa orang mengaitkan analisis statis dengan mencari sesuatu di kode sesuai dengan pola tertentu. Oleh karena itu, dari waktu ke waktu kami menulis catatan di mana kami mendemonstrasikan bagaimana teknologi ini atau itu, yang digunakan dalam penganalisis PVS-Studio, membantu mengungkap kesalahan menarik lainnya. Hari ini hanyalah artikel di mana kami akan mempertimbangkan bug di salah satu implementasi standar pengkodean data biner Base64.
Semuanya dimulai dengan memeriksa versi terbaru pustaka Qt 6. Ini adalah artikel klasik terpisah , di mana saya menjelaskan 77 kesalahan yang ditemukan. Kebetulan pada awalnya saya memutuskan untuk membaca sekilas laporan, belum menyembunyikan peringatan yang terkait dengan pustaka pihak ketiga. Dengan kata lain, saya belum menonaktifkan peringatan yang terkait dengan \ src \ 3rdparty di pengaturan. Dan kebetulan saya segera menemukan contoh kesalahan yang menarik di Open Asset Import Library , yang saya putuskan untuk membuat catatan kecil terpisah ini.
, , 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 :). :
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. , , , " , ".
, : Andrey Karpov. Why PVS-Studio Uses Data Flow Analysis: Based on Gripping Error in Open Asset Import Library.