Artikel ini melanjutkan seri publikasi tentang penggunaan PVS-Studio di sistem cloud. Kali ini kita akan melihat cara penganalisa bekerja bersama dengan GitLab CI, yang merupakan produk yang dibuat oleh GitLab Inc. Integrasi analisa statis dalam sistem CI memungkinkan mendeteksi bug segera setelah pembangunan proyek dan merupakan cara yang sangat efektif untuk mengurangi biaya menemukan bug.
Daftar artikel kami yang lain tentang pengintegrasian ke dalam sistem cloud CI:
Informasi tentang perangkat lunak yang digunakan
GitLab adalah layanan online yang dirancang untuk mengelola repositori. Anda dapat menggunakannya secara langsung di browser di situs web resmi dengan mendaftarkan akun Anda, atau menginstal dan menyebarkannya di server Anda sendiri.
PVS-Studio adalah alat yang dirancang untuk mendeteksi kesalahan dan kerentanan potensial dalam kode sumber program, ditulis dalam C, C ++, C # dan Java. Bekerja di sistem 64-bit pada Windows, Linux dan macOS dan dapat menganalisis kode untuk platform ARM 32-bit, 64-bit dan tertanam. Jika ini adalah pertama kalinya Anda menggunakan analisa untuk memeriksa proyek Anda, kami sarankan Anda membaca
artikel tentang cara cepat memeriksa peringatan PVS-Studio yang paling menarik dan mengevaluasi kemampuan alat.
Proyek OBS akan digunakan untuk menunjukkan kemampuan penganalisa statis di cloud.
Open Broadcaster Software adalah kumpulan program gratis dan terbuka untuk perekaman dan streaming video. OBS menyediakan perangkat real-time dan sumber intersepsi, komposisi adegan, decoding, rekaman dan penyiaran. Data ditransfer terutama melalui Protokol Pesan Waktu Nyata, dan dapat dikirim ke sumber apa pun yang mendukung RTMP - program ini memiliki pra-instalasi yang siap pakai untuk siaran langsung pada platform streaming paling populer.
Konfigurasi
Untuk mulai bekerja dengan GitLab, buka situs web dan klik
Daftarkan :
Anda dapat mendaftar dengan menautkan akun layanan lain seperti GitHub, Twitter, Google, BitBucket, Saleforce atau hanya dengan mengisi formulir yang terbuka. Setelah otorisasi, GitLab mengundang kami untuk membuat proyek:
Daftar platform yang tersedia untuk mengimpor file:
Mari kita buat proyek kosong untuk kejelasan:
Selanjutnya, kita perlu mengunggah proyek kita di repositori yang dibuat. Lakukan dengan menggunakan petunjuk yang muncul di jendela proyek yang dibuat.
Saat Anda memulai tugas, GitLab CI mengambil instruksi dari file
.gitlab-ci.yml . Anda dapat menambahkannya dengan mengklik
Setel CI / CD , atau cukup dengan membuat repositori lokal dan mengunggahnya ke situs. Mari ikuti opsi pertama:
Sekarang buat pembungkus minimal untuk skrip:
image: debian job: script:
Unduh utilitas penganalisa dan sendemail, yang akan kita perlukan nanti:
- apt-get update && apt-get -y install wget gnupg - wget -O - https:
Selanjutnya, kami akan menginstal 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). Dengan melakukan hal itu, Anda tidak perlu menentukan file lisensi di parameter yang dijalankan penganalisis, itu akan diangkat 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, ikuti: Pengaturan> CI / CD> Variabel.
Bangun proyek, menggunakan cmake:
- cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On /builds/Stolyarrrov/obscheck/ - make -j4
Setelah itu, jalankan alat analisa:
- pvs-studio-analyzer analyze -o PVS-Studio.log
PVS-Studio.log akan menyimpan hasil analisis. File yang dihasilkan dengan laporan tidak dimaksudkan untuk dibaca. Agar dapat diakses oleh mata manusia, kita memerlukan utilitas plog-converter. Program ini mengubah log penganalisis ke dalam berbagai format. Untuk memudahkan membaca, mari konversi log ke dalam format html:
- plog-converter -t html PVS-Studio.log -o PVS-Studio.html
Anda dapat mengekspor laporan menggunakan
artefak , tetapi kami akan mengubah taktik dan mengirim file dengan hasil analisa melalui 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
komit perubahan . Jika kami melakukan semuanya dengan benar, kami akan melihat hasilnya:
Konfigurasi GitLab CI ini valid. Untuk melacak kemajuan, mari kita pindah ke tab
CI / CD> Pipeline .
Klik
menjalankan . Kita akan melihat jendela terminal mesin virtual tempat file konfigurasi kita berjalan. Setelah beberapa saat kami mendapat pesan:
pekerjaan berhasil.Jadi sudah waktunya untuk membuka file html dengan peringatan yang dikirim melalui surat.
Hasil analisis
Mari kita lihat beberapa peringatan dari laporan ini, mengungkap kesalahan dalam proyek Open Broadcaster Software untuk mendapatkan esensi dari analisis kode statis. Karena tujuan utama artikel ini adalah untuk menjelaskan prinsip-prinsip interaksi PVS-Studio dan GitLab CI / CD, hanya beberapa contoh nontrivial yang diambil. Kami siap memberi para penulis proyek lisensi sementara dan, jika mereka mau, mereka dipersilakan untuk melakukan analisis proyek yang lebih menyeluruh. Selain itu, mereka dapat menggunakan salah satu
cara untuk mendapatkan lisensi PVS-Studio gratis .
Juga setiap orang bisa
mendapatkan kunci percobaan untuk mengeksplorasi kemampuan PVS-Studio dan memeriksa proyek mereka.
Jadi, mari kita perhatikan 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); } .... }
Baris
if (data_end_pos> cb-> kapasitas) pasti patut
dicermati . Jika kondisinya benar, variabel
back_size , yang didefinisikan dalam baris di bawah ini, akan selalu lebih besar dari nol, karena di sini kita berurusan dengan pengurangan nilai yang terkenal lebih kecil dari yang lebih besar. Pada akhirnya, kondisi, yang merupakan dua baris di bawah ini, akan selalu
benar . Kondisi mubazir tidak begitu berbahaya ketika diikuti oleh kode, 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; .... }
Operasi yang membingungkan lebih dari tipe 32-bit dan 64-bit terlihat mencurigakan di sini. Pertama, programmer mengevaluasi topeng, menggunakan tipe 32-bit (ekspresi
(1 << indent) - 1 ), setelah itu secara implisit meluas ke tipe 64-bit dalam ekspresi
active & = .... Kemungkinan besar, ketika mengevaluasi topeng, penggunaan tipe 64-bit juga diperlukan.
Versi kode yang benar:
active &= ((uint64_t)(1) << indent) - 1;
Atau:
active &= (1ull << indent) - 1;
Ngomong-ngomong, versi salin-tempel blok ini ada di bawah, penganalisis juga mengeluarkan peringatan untuk itu:
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 dalam setiap kasus kode tersebut menunjukkan kesalahan
salin-tempel . Kemungkinan besar, fungsi-fungsi ini harus dipanggil dengan argumen yang berbeda. Kalaupun tidak, kode ini terlihat aneh. Solusi yang baik adalah dengan menulis blok hanya 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 dapat kita lihat,
pengubah adalah penunjuk, diinisialisasi dengan alamat bidang
pengubah dari struktur
kombo . Karena nilainya tidak berubah hingga cek, itu akan tetap non-nol. Selain itu, setelah inisialisasi sebelum cek, pointer digunakan ketika memanggil fungsi
load_modifier , di mana ia akan direferensikan. Karenanya, pemeriksaan
! Pengubah tidak ada gunanya, karena karena operator
&& kami akan selalu
salah ketika mengevaluasi ekspresi logis. Saya pikir programmer ingin memeriksa nilai integer dengan alamat yang disimpan dalam
pengubah pointer, tetapi lupa untuk mengubah
referensi pointer ini.
Jadi menurut saya ceknya adalah sebagai berikut:
if (!*modifiers && ....) Or like this: 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); .... }
Paling sering kode semacam itu tidak aman, karena mengabaikan bahwa
malloc dapat mengembalikan pointer nol. Jika
malloc mengembalikan
NULL , perilaku yang tidak terdefinisi akan muncul dalam kasus ini, karena argumen pertama dari fungsi
strncpy akan memiliki nilai
NULL .
Untuk informasi lebih lanjut tentang mengapa penting untuk memeriksa nilai pengembalian fungsi
malloc , lihat
artikel yang relevan .
Peringatan N7, N8, N9Tebak case mana yang mengandung perhitungan yang salah:
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 penganalisa:
- 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)
Inilah jawaban yang tepat: di mana, di mana
saya tidak dilemparkan untuk mengapung. Alat analisis menunjukkan kepada kami fragmen dengan divisi integer. Kode seperti itu mungkin bekerja tidak sesuai harapan programmer.
Kesimpulan
Seperti yang dapat kita lihat, integrasi analisa PVS-Studio dalam proyek Anda di GitLab adalah proses yang cukup sederhana. Untuk melakukan ini, Anda hanya perlu menulis satu file konfigurasi dan meletakkannya di repositori cloud Anda. Karena GitLab memiliki mesin virtual terintegrasi sendiri, kami bahkan tidak perlu menghabiskan banyak waktu untuk mengonfigurasi sistem CI. Pengecekan kode akan memungkinkan Anda menemukan masalah tepat setelah pembangunan. Ini membantu menghilangkan masalah pada tahap di mana kompleksitas dan biayanya kecil.