Artikel ini merupakan kelanjutan dari serangkaian publikasi tentang penggunaan PVS-Studio dalam sistem cloud. Kali ini kita akan melihat penganalisa bersama dengan GitLab CI, sebuah produk dari GitLab Inc. Integrasi alat analisis statis dalam sistem CI memungkinkan Anda untuk mengidentifikasi bug segera setelah fase pembangunan proyek dan merupakan cara yang sangat efektif untuk mengurangi biaya mendeteksi kesalahan.
Daftar artikel kami yang lain tentang integrasi ke dalam sistem cloud CI:
Informasi tentang perangkat lunak yang digunakan
GitLab adalah layanan online untuk mengelola repositori. Ini dapat digunakan langsung di browser di situs web resmi dengan mendaftarkan akun, atau diinstal dan digunakan di server Anda sendiri.
PVS-Studio adalah alat analisis kode statis yang dirancang untuk mendeteksi kesalahan dan potensi kerentanan dalam program yang ditulis dalam C, C ++, C # dan Java. Ini bekerja pada sistem 64-bit pada Windows, Linux dan macOS dan dapat menganalisis kode yang dirancang untuk platform ARM 32-bit, 64-bit dan tertanam. Jika ini adalah pertama kalinya Anda mencoba analisis kode statis untuk menguji proyek Anda, kami sarankan Anda membaca
artikel tentang cara cepat melihat peringatan PVS-Studio yang paling menarik dan mengevaluasi kemampuan alat ini.
Proyek OBS akan digunakan untuk menunjukkan operasi penganalisa statis di cloud.
Open Broadcaster Software adalah perangkat lunak sumber terbuka dan gratis untuk perekaman dan streaming video. OBS menyediakan kemampuan untuk mencegat dari perangkat dan sumber secara real time, komposisi adegan, decoding, perekaman dan penyiaran. Transmisi data dilakukan terutama melalui Protokol Pesan Waktu Nyata, dan data dapat ditransfer ke sumber apa pun yang mendukung RTMP - program ini memiliki preset siap pakai untuk penyiaran langsung ke platform streaming paling populer.
Kustomisasi
Untuk memulai dengan GitLab, buka situs dan klik tombol
Daftar :
Anda dapat mendaftar dengan menautkan akun layanan seperti: GitHub, Twitter, Google, BitBucket, Saleforce atau hanya dengan mengisi formulir yang terbuka. Setelah otorisasi, GitLab menemui kami dengan proposal untuk membuat proyek:
Daftar platform tempat Anda dapat mengimpor:
Untuk kejelasan, buat proyek kosong:
Selanjutnya, kita perlu mengunggah proyek kita ke repositori yang dibuat. Ini dilakukan menggunakan prompt yang muncul di jendela proyek yang dibuat.
Ketika tugas dimulai, GitLab CI mengambil instruksi dari file
.gitlab-ci.yml . Anda dapat menambahkannya dengan mengeklik tombol
Atur CI / CD , atau cukup membuatnya di repositori lokal dan mengunggahnya ke situs. Kami akan menggunakan opsi pertama:
Mari kita buat pembungkus minimal untuk skrip:
image: debian job: script:
Unduh alat analisa dan sendemail, yang akan kita perlukan di masa depan:
- apt-get update && apt-get -y install wget gnupg - wget -O - https:
Selanjutnya, instal dependensi dan utilitas untuk membangun OBS:
- apt-get -y install build-essential cmake make pkg-config libx11-dev libgl1-mesa-dev libpulse-dev libxcomposite-dev libxinerama-dev libv4l-dev libudev-dev libfreetype6-dev libfontconfig-dev qtbase5-dev libqt5x11extras5-dev libx264-dev libxcb-xinerama0-dev libxcb-shm0-dev libjack-jackd2-dev libcurl4-openssl-dev libavcodec-dev libqt5svg5 libavfilter-dev libavdevice-dev libsdl2-dev ffmpeg qt5-default qtscript5-dev libssl-dev qttools5-dev qttools5-dev-tools qtmultimedia5-dev libqt5svg5-dev libqt5webkit5-dev libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-jackd2-dev libxrandr-dev libqt5xmlpatterns5-dev libqt5xmlpatterns5 coccinelle parallel libapparmor-dev libcap-dev libseccomp-dev python3-dev python3-setuptools docbook2x libgnutls28-dev libselinux1-dev linux-libc-dev libtool autotools-dev libio-socket-ssl-perl libnet-ssleay-perl ca-certificates
Sekarang kita perlu membuat file dengan lisensi analyzer. Secara default, file PVS-Studio.lic akan dibuat di direktori ../.config/PVS-Studio. Dalam hal ini, file lisensi dapat dihilangkan dari parameter peluncuran penganalisis, itu akan diambil secara otomatis:
- pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
Di sini,
PVS_NAME dan
PVS_KEY adalah nama-nama variabel yang nilainya kami tentukan dalam pengaturan. Mereka akan menyimpan login dan kunci lisensi PVS-Studio. Untuk mengatur nilainya, buka: Pengaturan> CI / CD> Variabel.
Bangun proyek menggunakan cmake:
- cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On /builds/Stolyarrrov/obscheck/ - make -j4
Kemudian jalankan alat analisa:
- pvs-studio-analyzer analyze -o PVS-Studio.log
PVS-Studio.log akan menyimpan hasil analisis. File laporan yang dihasilkan tidak dimaksudkan untuk dibaca, dan untuk membawanya ke tampilan yang dapat diakses oleh mata manusia, kita membutuhkan utilitas plog-converter. Program ini mengonversi log penganalisa ke berbagai format. Agar mudah dibaca, kami akan mengonversi ke format html:
- plog-converter -t html PVS-Studio.log -o PVS-Studio.html
Laporan dapat diunggah menggunakan
artefak , tetapi kami akan menggunakan metode alternatif dan mengirim file dengan hasil analisa ke email menggunakan utilitas sendemail:
- sendemail -t $MAIL_TO -u "PVS-Studio report, commit:GITLAB_COMMIT" -m "PVS-Studio report, commit:GITLAB_COMMIT" -s $GMAIL_PORT -o tls=auto -f $MAIL_FROM -xu $MAIL_FROM -xp $MAIL_FROM_PASS -a PVS-Studio.log PVS-Studio.html
Lengkap .gitlab-ci.yml:
image: debian job: script: - apt-get update && apt-get -y install wget gnupg - wget -O - https:
Klik pada tombol
komit perubahan . Jika kita melakukan semuanya dengan benar, kita akan melihat tulisan:
Konfigurasi GitLab CI ini valid. Untuk melacak kemajuan, buka tab
CI / CD> Pipeline.Klik
menjalankan . Kita akan melihat jendela terminal mesin virtual tempat file konfigurasi kita berjalan. Setelah beberapa waktu, kami menerima pesan:
pekerjaan berhasil.Jadi, saatnya pergi ke surat dan membuka file html dengan peringatan.
Hasil Validasi
Mari kita sekarang melihat beberapa peringatan dari laporan yang menunjukkan kesalahan dalam proyek Perangkat Lunak Penyiar Terbuka untuk menunjukkan esensi dari analisis kode statis. Tujuan artikel ini adalah untuk menjelaskan prinsip-prinsip interaksi antara PVS-Studio dan GitLab CI / CD, sehingga hanya beberapa fragmen kode menarik dengan kesalahan yang telah ditulis. Kami siap memberikan lisensi sementara kepada penulis proyek, dan jika mereka mau, mereka dapat melakukan analisis proyek yang lebih menyeluruh. Atau mereka dapat memanfaatkan salah satu
opsi untuk lisensi PVS-Studio gratis.
Setiap orang juga dapat secara independen
menerima kunci percobaan untuk mengeksplorasi kemampuan PVS-Studio dan memeriksa proyek mereka.
Jadi, mari kita lihat beberapa contoh kesalahan yang ditemukan di Open Broadcaster Software.
Peringatan N1Ekspresi
V547 'back_size' memang benar. circlebuf.h (138)
struct circlebuf { .... size_t capacity; }; static inline void circlebuf_place(struct circlebuf *cb, size_t position,....,const void *data, size_t size) { .... size_t data_end_pos; data_end_pos = position + size; if (data_end_pos > cb->capacity) { size_t back_size = data_end_pos - cb->capacity; if (back_size) { memcpy((uint8_t *)cb->data + position, data, loop_size); } .... }
Perhatikan baris:
jika (data_end_pos> cb-> kapasitas) , pemenuhan kondisi akan berarti bahwa variabel
back_size , yang didefinisikan dalam baris di bawah, akan selalu lebih besar dari nol, karena yang jelas lebih kecil dari yang jelas lebih besar dikurangi, yang berarti bahwa kondisinya adalah baris lain di bawah ini, akan selalu
benar . Kondisi berlebih tidak begitu berbahaya ketika di bawahnya adalah kode yang mengubah data.
Peringatan N2, N3V629 Pertimbangkan untuk memeriksa ekspresi '1 << indent'. Pergeseran bit dari nilai 32-bit dengan ekspansi selanjutnya ke tipe 64-bit. profiler.c (610)
static void profile_print_entry(uint64_t active, unsigned indent, ....) { .... active &= (1 << indent) - 1; .... }
Campuran operasi pada tipe 32-bit dan 64-bit terlihat mencurigakan di sini. Pertama, mask dihitung menggunakan tipe 32-bit (ekspresi
(1 << indent) - 1 ), dan kemudian secara implisit diperluas ke tipe 64-bit dalam ekspresi
active & = .... Kemungkinan besar, saat menghitung topeng, penggunaan tipe 64-bit juga diasumsikan.
Versi kode yang benar:
active &= ((uint64_t)(1) << indent) - 1;
Atau:
active &= (1ull << indent) - 1;
Juga, salin-tempel blok kode ini di bawah ini, yang juga dikeluarkan oleh penganalisis tentang:
V629 Pertimbangkan untuk memeriksa ekspresi '1 << indent'. Pergeseran bit dari nilai 32-bit dengan ekspansi selanjutnya ke tipe 64-bit. profiler.c (719)
Peringatan N4V761 Empat blok teks yang identik ditemukan. 'obs-audio-controls.c' (353)
static float get_true_peak(....) { .... peak = _mm_max_ps(peak, abs_ps(intrp_samples)); SHIFT_RIGHT_2PS(new_work, work); VECTOR_MATRIX_CROSS_PS(intrp_samples, work, m3, m1, p1, p3); peak = _mm_max_ps(peak, abs_ps(intrp_samples)); SHIFT_RIGHT_2PS(new_work, work); VECTOR_MATRIX_CROSS_PS(intrp_samples, work, m3, m1, p1, p3); peak = _mm_max_ps(peak, abs_ps(intrp_samples)); SHIFT_RIGHT_2PS(new_work, work); VECTOR_MATRIX_CROSS_PS(intrp_samples, work, m3, m1, p1, p3); peak = _mm_max_ps(peak, abs_ps(intrp_samples)); SHIFT_RIGHT_2PS(new_work, work); VECTOR_MATRIX_CROSS_PS(intrp_samples, work, m3, m1, p1, p3); .... }
Empat blok identik. Hampir selalu, kode tersebut menunjukkan kesalahan
salin-tempel . Kemungkinan besar, fungsi-fungsi ini seharusnya dipanggil dengan argumen yang berbeda. Kalaupun tidak, kode ini terlihat aneh. Solusi yang baik adalah menulis satu blok sekali dan membungkusnya dalam satu lingkaran:
for(size_t i = 0; i < 3; i++) { peak = _mm_max_ps(peak, abs_ps(intrp_samples)); SHIFT_RIGHT_2PS(new_work, work); VECTOR_MATRIX_CROSS_PS(intrp_samples, work, m3, m1, p1, p3); }
Peringatan N5V560 Bagian dari ekspresi kondisional selalu salah: '! Pengubah'. obs-hotkey.c (662)
typedef struct obs_key_combination obs_key_combination_t; struct obs_key_combination { uint32_t modifiers; obs_key_t key; }; static inline void load_binding(....) { obs_key_combination_t combo = {0}; uint32_t *modifiers = &combo.modifiers; load_modifier(modifiers, data, "shift", INTERACT_SHIFT_KEY); load_modifier(modifiers, data, "control", INTERACT_CONTROL_KEY); load_modifier(modifiers, data, "alt", INTERACT_ALT_KEY); load_modifier(modifiers, data, "command", INTERACT_COMMAND_KEY); if (!modifiers && (combo.key == OBS_KEY_NONE || combo.key >= OBS_KEY_LAST_VALUE)) { .... } .... }
Definisi fungsi
load_modifier :
static inline void load_modifier(uint32_t *modifiers, obs_data_t *data, const char *name, uint32_t flag) { if (obs_data_get_bool(data, name)) *modifiers |= flag; }
Seperti yang kita lihat,
pengubah adalah penunjuk yang diinisialisasi dengan alamat bidang
pengubah dari struktur
kombo . Karena nilainya tidak berubah ke tempat verifikasi, nilainya akan tetap nol. Selain itu - antara tempat inisialisasi dan verifikasi, pointer digunakan ketika memanggil fungsi
load_modifier , di mana ia dereferensi. Karenanya, memeriksa
! Pengubah tidak masuk akal, karena sebagai hasil dari operator
&& kami akan selalu
salah ketika mengevaluasi ekspresi logis. Saya berpikir bahwa pemrogram ingin memeriksa nilai integer yang terletak di alamat yang disimpan dalam
pengubah pointer, tetapi lupa untuk mengubah
referensi pointer ini.
Yaitu Bagiku cek itu seharusnya seperti ini:
if (!*modifiers && ....) : if (!combo.modifiers && ....)
Peringatan N6V575 Potensi penunjuk nol dilewatkan ke fungsi 'strncpy'. Periksa argumen pertama. Periksa baris: 2904, 2903. rtmp.c (2904)
static int PublisherAuth(....) { .... ptr = malloc(r->Link.app.av_len + pubToken.av_len); strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len); .... }
Seringkali, kode ini tidak aman karena tidak memperhitungkan bahwa
malloc dapat mengembalikan pointer nol. Jika
malloc mengembalikan
NULL ,
perilaku yang tidak terdefinisi akan muncul dalam kasus ini, karena argumen pertama ke
strncpy adalah
NULL .
Anda dapat membaca lebih lanjut tentang mengapa penting untuk memeriksa nilai pengembalian fungsi
malloc di
artikel terkait.Peringatan N7, N8, N9Mari kita coba tebak dalam kasus mana perhitungan yang salah dapat terjadi:
class OBSProjector : public OBSQTDisplay { .... float sourceX, sourceY, ....; .... } .... void OBSProjector::OBSRenderMultiview(....) { OBSProjector *window = (OBSProjector *)data; .... auto calcBaseSource = [&](size_t i) { switch (multiviewLayout) { case MultiviewLayout::HORIZONTAL_TOP_24_SCENES: window->sourceX = (i % 6) * window->scenesCX; window->sourceY = window->pvwprgCY + (i / 6) * window->scenesCY; break; case MultiviewLayout::VERTICAL_LEFT_8_SCENES: window->sourceX = window->pvwprgCX; window->sourceY = (i / 2) * window->scenesCY; if (i % 2 != 0) { window->sourceX += window->scenesCX; } break; case MultiviewLayout::VERTICAL_RIGHT_8_SCENES: window->sourceX = 0; window->sourceY = (i / 2) * window->scenesCY; if (i % 2 != 0) { window->sourceX = window->scenesCX; } break; case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES: if (i < 4) { window->sourceX = (float(i) * window->scenesCX); window->sourceY = 0; } else { window->sourceX = (float(i - 4) * window->scenesCX); window->sourceY = window->scenesCY; } break; default:
Peringatan Analyzer:
- V636 Ekspresi 'i / 6' secara implisit dilemparkan dari tipe 'size_t' ke tipe 'float'. Pertimbangkan untuk menggunakan pemeran tipe eksplisit untuk menghindari hilangnya bagian fraksional. Contoh: double A = (double) (X) / Y; window-projector.cpp (330)
- V636 Ekspresi 'i / 2' secara implisit dilemparkan dari tipe 'size_t' ke tipe 'float'. Pertimbangkan untuk menggunakan pemeran tipe eksplisit untuk menghindari hilangnya bagian fraksional. Contoh: double A = (double) (X) / Y; window-projector.cpp (334)
- V636 Ekspresi 'i / 2' secara implisit dilemparkan dari tipe 'size_t' ke tipe 'float'. Pertimbangkan untuk menggunakan pemeran tipe eksplisit untuk menghindari hilangnya bagian fraksional. Contoh: double A = (double) (X) / Y; window-projector.cpp (340)
Jawaban yang benar: di mana
saya tidak dilemparkan ke
mengambang . Dalam ekspresi yang ditunjukkan penganalisa kepada kami, pembagian bilangan bulat terjadi. Kode ini mungkin tidak berfungsi persis seperti yang diharapkan oleh programmer.
Kesimpulan
Seperti yang bisa kita lihat, mengintegrasikan analisa statis PVS-Studio ke proyek GitLab Anda cukup sederhana. Untuk melakukan ini, cukup tulis satu file konfigurasi dan masukkan ke dalam repositori cloud Anda. Karena GitLab memiliki mesin virtual terintegrasi sendiri, kita bahkan tidak perlu menghabiskan banyak waktu untuk mengkonfigurasi sistem CI. Memeriksa kode akan memungkinkan Anda untuk mengidentifikasi masalah segera setelah pembuatan, yang akan membantu untuk memperbaikinya ketika kompleksitas dan biaya pengeditan masih kecil.

Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Vladislav Stolyarov.
PVS-Studio di Awan: GitLab CI / CD .