Selama analisis kode, PVS-Studio menganalisis aliran data dan mengoperasikan nilai variabel. Nilai diambil dari konstanta atau berasal dari ekspresi kondisional. Kami menyebutnya nilai-nilai virtual. Baru-baru ini, kami telah memperbaikinya untuk bekerja dengan konstanta multi-karakter dan ini telah menjadi alasan untuk membuat aturan diagnostik baru.
Pendahuluan
Multi-karakter-literal
didefinisikan oleh implementasi , sehingga kompiler yang berbeda dapat menyandikannya dengan cara yang berbeda. Misalnya, GCC dan Dentang menetapkan nilai, berdasarkan urutan simbol dalam literal, sementara MSVC memindahkannya tergantung pada jenis simbol (reguler atau melarikan diri).
Sebagai contoh, literal 'T \ x65s \ x74' akan dikodekan dengan berbagai cara, tergantung pada kompiler. Logika yang serupa harus ditambahkan dalam analisa. Sebagai hasilnya, kami telah membuat aturan diagnostik baru V1039 untuk mengidentifikasi literal tersebut dalam kode. Literal ini berbahaya dalam proyek lintas platform yang menggunakan banyak kompiler untuk membangun.
Diagnostik V1039
Mari kita lihat contohnya. Kode di bawah ini, dikompilasi oleh kompiler yang berbeda, akan berperilaku berbeda:
#include <stdio.h> void foo(int c) { if (c == 'T\x65s\x74') // <= V1039 { printf("Compiled with GCC or Clang.\n"); } else { printf("It's another compiler (for example, MSVC).\n"); } } int main(int argc, char** argv) { foo('Test'); return 0; }
Program, dikompilasi oleh kompiler yang berbeda, akan mencetak pesan yang berbeda di layar.
Untuk proyek yang menggunakan kompiler tertentu, itu tidak akan terlihat. Tetapi ketika porting, masalah dapat terjadi, jadi seseorang harus mengganti literal tersebut dengan konstanta numerik sederhana, seperti 'Tes' harus diubah dengan 0x54657374.
Untuk menunjukkan perbedaan antara kompiler, kami akan menulis sebuah utilitas kecil yang mengambil urutan 3 dan 4 simbol, seperti 'GHIJ' dan 'GHI', dan menampilkan representasi mereka dalam memori setelah kompilasi.
Kode utilitas:
#include <stdio.h> typedef int char_t; void PrintBytes(const char* format, char_t lit) { printf("%20s : ", format); const unsigned char *ptr = (const unsigned char*)&lit; for (int i = sizeof(lit); i--;) { printf("%c", *ptr++); } putchar('\n'); } int main(int argc, char** argv) { printf("Hex codes are: G(%02X) H(%02X) I(%02X) J(%02X)\n",'G','H','I','J'); PrintBytes("'GHIJ'", 'GHIJ'); PrintBytes("'\\x47\\x48\\x49\\x4A'", '\x47\x48\x49\x4A'); PrintBytes("'G\\x48\\x49\\x4A'", 'G\x48\x49\x4A'); PrintBytes("'GH\\x49\\x4A'", 'GH\x49\x4A'); PrintBytes("'G\\x48I\\x4A'", 'G\x48I\x4A'); PrintBytes("'GHI\\x4A'", 'GHI\x4A'); PrintBytes("'GHI'", 'GHI'); PrintBytes("'\\x47\\x48\\x49'", '\x47\x48\x49'); PrintBytes("'GH\\x49'", 'GH\x49'); PrintBytes("'\\x47H\\x49'", '\x47H\x49'); PrintBytes("'\\x47HI'", '\x47HI'); return 0; }
Output dari utilitas, disusun oleh Visual C ++:
Hex codes are: G(47) H(48) I(49) J(4A) 'GHIJ' : JIHG '\x47\x48\x49\x4A' : GHIJ 'G\x48\x49\x4A' : HGIJ 'GH\x49\x4A' : JIHG 'G\x48I\x4A' : JIHG 'GHI\x4A' : JIHG 'GHI' : IHG '\x47\x48\x49' : GHI 'GH\x49' : IHG '\x47H\x49' : HGI '\x47HI' : IHG
Output dari utilitas, disusun oleh GCC atau Dentang:
Hex codes are: G(47) H(48) I(49) J(4A) 'GHIJ' : JIHG '\x47\x48\x49\x4A' : JIHG 'G\x48\x49\x4A' : JIHG 'GH\x49\x4A' : JIHG 'G\x48I\x4A' : JIHG 'GHI\x4A' : JIHG 'GHI' : IHG '\x47\x48\x49' : IHG 'GH\x49' : IHG '\x47H\x49' : IHG '\x47HI' : IHG
Kesimpulan
Diagnostik V1039 ditambahkan dalam penganalisa PVS-Studio versi
7.03 , yang baru-baru ini dirilis. Anda dapat mengunduh versi analisa terbaru di
halaman unduhan .