Saat ini, sistem cloud CI adalah layanan yang sangat populer. Pada artikel ini kami akan memberitahu caranya, menggunakan alat yang ada yang tersedia di PVS-Studio, Anda dapat mengintegrasikan analisis kode sumber dengan platform cloud CI, menggunakan layanan Travis CI sebagai contoh.
Mengapa kita melihat awan pihak ketiga dan tidak membuat awan kita sendiri? Ada beberapa alasan, dan yang utama adalah bahwa SaaS adalah prosedur yang agak mahal dan sulit. Bahkan, mengintegrasikan analisis PVS-Studio secara langsung dengan platform cloud pihak ketiga (apakah itu platform terbuka seperti CircleCI, Travis CI, GitLab, atau beberapa solusi perusahaan khusus yang digunakan hanya dalam satu perusahaan tertentu) adalah tugas yang cukup sederhana dan sepele. Artinya, kita dapat mengatakan bahwa
PVS-Studio sudah tersedia "di awan" . Masalah yang sama sekali berbeda adalah organisasi dan penyediaan infrastruktur untuk pekerjaan tersebut 24/7. Ini adalah tugas yang sama sekali berbeda, dan PVS-Studio tidak memiliki rencana untuk menyediakan platform cloud sendiri secara langsung untuk menjalankan analisis di atasnya.
Informasi tentang perangkat lunak yang digunakan
Travis CI adalah layanan untuk membangun dan menguji perangkat lunak yang menggunakan GitHub sebagai penyimpanan. Travis CI tidak perlu mengubah kode program untuk menggunakan layanan ini, semua pengaturan terjadi dalam file
.travis.yml yang terletak di root repositori.
Kami akan menggunakan
LXC (Linux Containers) sebagai proyek uji untuk pengujian dengan PVS-Studio. Ini adalah sistem virtualisasi tingkat sistem operasi untuk menjalankan beberapa contoh sistem operasi Linux pada satu node.
Proyek ini kecil, tetapi lebih dari cukup untuk ditunjukkan. Output dari perintah cloc:
Catatan: Pengembang LXC sudah menggunakan Travis CI, jadi kami akan mengambil file konfigurasi mereka sebagai basis dan mengeditnya untuk tujuan kami.
Kustomisasi
Untuk memulai dengan Travis CI,
ikuti tautan dan autentikasi menggunakan akun GitHub.
Di jendela yang terbuka, Anda perlu mengesahkan Travis CI.
Setelah otorisasi, pengalihan ke halaman pembuka “Pertama kali di sini? Mari kita mulai! "
, yang menjelaskan secara singkat apa yang perlu dilakukan selanjutnya untuk memulai:
- mengaktifkan repositori;
- tambahkan file .travis.yml ke repositori;
- jalankan build pertama.
Kami akan mulai melaksanakan poin-poin ini.
Untuk menambahkan repositori kami ke Travis CI, buka pengaturan profil
melalui tautan dan klik tombol "Activate".
Setelah mengklik, sebuah jendela terbuka dengan pilihan repositori yang dapat diakses oleh aplikasi Travis CI.
Catatan: untuk memberikan akses ke repositori, akun harus memiliki hak administrator untuk itu.
Kami memilih repositori yang diinginkan, mengonfirmasi pilihan dengan tombol "Setuju & Instal", dan kami akan diarahkan kembali ke halaman pengaturan profil.
Segera buat variabel yang akan kita gunakan untuk membuat file lisensi penganalisa dan mengirimkan laporannya. Untuk melakukan ini, buka halaman pengaturan - tombol "Pengaturan" di sebelah kanan repositori yang diinginkan.
Jendela pengaturan akan terbuka.
Deskripsi singkat pengaturan:
- Bagian "Umum" - pengaturan pemicu untuk tugas autorun;
- Bagian "Pembatalan Otomatis" - memungkinkan Anda untuk mengkonfigurasi rakitan membatalkan otomatis;
- Bagian "Variabel Lingkungan" - memungkinkan Anda untuk menentukan variabel lingkungan yang berisi informasi publik dan rahasia, seperti kredensial, kunci ssh;
- Bagian “Pekerjaan Cron” - mengatur jadwal peluncuran tugas.
Di bagian "Variabel Lingkungan" kami membuat variabel
PVS_USERNAME dan
PVS_KEY yang masing-masing berisi nama pengguna dan kunci lisensi untuk penganalisa statis. Jika Anda tidak memiliki lisensi PVS-Studio permanen, maka Anda dapat
meminta lisensi uji coba .
Segera buat variabel
MAIL_USER dan
MAIL_PASSWORD yang berisi nama pengguna dan kata sandi kotak surat, yang akan kami gunakan untuk mengirim laporan.
Ketika tugas diluncurkan, Travis CI mengambil instruksi dari file .travis.yml yang terletak di root repositori.
Menggunakan Travis CI, kita dapat menjalankan analisis statis secara langsung di mesin virtual, atau menggunakan wadah yang telah dikonfigurasi untuk ini. Hasil pendekatan ini tidak berbeda satu sama lain, tetapi menggunakan wadah pra-konfigurasi bisa berguna, misalnya, jika kita sudah memiliki wadah dengan beberapa lingkungan spesifik di mana produk perangkat lunak dibangun dan diuji, dan tidak ada keinginan untuk memulihkan lingkungan ini di Travis CI .
Mari kita membuat konfigurasi untuk menjalankan analisa di mesin virtual.
Untuk perakitan dan pengujian, kami akan menggunakan mesin virtual berbasis Ubuntu Trusty, deskripsinya dapat ditemukan di
sini .
Pertama-tama, kami menunjukkan bahwa proyek ini ditulis dalam C dan kami daftar kompiler yang akan kami gunakan untuk perakitan:
language: c compiler: - gcc - clang
Catatan : jika Anda menentukan lebih dari satu kompiler, tugas akan diluncurkan secara paralel untuk masing-masingnya. Baca lebih lanjut
di dokumentasi .
Sebelum memulai pembuatan, kita perlu menambahkan repositori analyzer, menginstal dependensi dan paket tambahan:
before_install: - sudo add-apt-repository ppa:ubuntu-lxc/daily -y - wget -q -O - https:
Sebelum membangun proyek, Anda perlu menyiapkan lingkungan:
script: - ./coccinelle/run-coccinelle.sh -i - git diff --exit-code - export CFLAGS="-Wall -Werror" - export LDFLAGS="-pthread -lpthread" - ./autogen.sh - rm -Rf build - mkdir build - cd build - ../configure --enable-tests --with-distro=unknown
Selanjutnya, kita perlu membuat file dengan lisensi dan menjalankan analisis proyek.
Perintah pertama membuat file lisensi untuk penganalisa. Data untuk variabel
$ PVS_USERNAME dan
$ PVS_KEY diambil dari pengaturan proyek.
- pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
Perintah berikut memulai jejak perakitan proyek:
- pvs-studio-analyzer trace -- make -j4
Setelah kami memulai analisis statis.
Catatan: saat menggunakan lisensi percobaan, Anda harus menentukan parameter
--disableLicenseExpirationCheck .
- pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic -o PVS-Studio-${CC}.log –-disableLicenseExpirationCheck
Dengan perintah terakhir, file hasil analisis dikonversi ke laporan html.
- plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html
Karena TravisCI tidak mengizinkan mengubah format pemberitahuan email, kami akan menggunakan paket sendemail untuk mengirim laporan pada langkah terakhir:
- sendemail -t mail@domain.com -u "PVS-Studio $CC report, commit:$TRAVIS_COMMIT" -m "PVS-Studio $CC report, commit:$TRAVIS_COMMIT" -s smtp.gmail.com:587 -xu $MAIL_USER -xp $MAIL_PASSWORD -o tls=yes -f $MAIL_USER -a PVS-Studio-${CC}.log PVS-Studio-${CC}.html
Teks lengkap file konfigurasi untuk menjalankan alat analisa dalam mesin virtual:
language: c compiler: - gcc - clang before_install: - sudo add-apt-repository ppa:ubuntu-lxc/daily -y - wget -q -O - https:
Untuk menjalankan analisis statis dalam sebuah wadah, pertama-tama buatlah menggunakan Dockerfile berikut:
FROM docker.io/ubuntu:trusty ENV CFLAGS="-Wall -Werror" ENV LDFLAGS="-pthread -lpthread" RUN apt-get update && apt-get install -y software-properties-common wget \ && wget -q -O - https:
Dalam hal ini, file konfigurasi mungkin terlihat seperti ini:
before_install: - docker pull docker.io/oandreev/lxc env: - CC=gcc - CC=clang script: - docker run --rm --cap-add SYS_PTRACE -v $(pwd):/pvs -w /pvs docker.io/oandreev/lxc /bin/bash -c " ./coccinelle/run-coccinelle.sh -i && git diff --exit-code && ./autogen.sh && mkdir build && cd build && ../configure CC=$CC && pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic && pvs-studio-analyzer trace -- make -j4 && pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic -o PVS-Studio-$CC.log --disableLicenseExpirationCheck && plog-converter -t html -o PVS-Studio-$CC.html PVS-Studio-$CC.log && sendemail -t mail@domain.com -u 'PVS-Studio $CC report, commit:$TRAVIS_COMMIT' -m 'PVS-Studio $CC report, commit:$TRAVIS_COMMIT' -s smtp.gmail.com:587 -xu $MAIL_USER -xp $MAIL_PASSWORD -o tls=yes -f $MAIL_USER -a PVS-Studio-${CC}.log PVS-Studio-${CC}.html"
Seperti yang Anda lihat, dalam hal ini kami tidak melakukan apa pun di dalam mesin virtual, dan tentu saja semua tindakan untuk merakit dan menguji proyek berlangsung di dalam wadah.
Catatan : saat memulai wadah, Anda harus menentukan
--cap-add SYS_PTRACE atau
--security-opt seccomp: parameter tidak dikonfigurasikan , karena panggilan sistem ptrace digunakan untuk mengkompilasi jejak.
Kami memuat file konfigurasi ke dalam root repositori dan melihat bahwa Travis CI menerima pemberitahuan tentang kehadiran perubahan dalam proyek dan secara otomatis memulai perakitan.
Informasi terperinci tentang kemajuan perakitan dan verifikasi penganalisa dapat dilihat di konsol.
Setelah tes selesai, kami akan menerima 2 surat dalam surat: satu dengan hasil analisis statis untuk membangun proyek menggunakan gcc, dan yang kedua dengan dentang, masing-masing.
Secara singkat tentang hasil tes
Secara umum, proyek ini cukup bersih, analis hanya mengeluarkan 24 peringatan kritis dan 46 rata-rata. Untuk mendemonstrasikan pekerjaan, pertimbangkan beberapa pemberitahuan menarik:
Kondisi redundan di if
V590 Pertimbangkan untuk memeriksa
ekspresi 'ret! = (- 1) && ret == 1'. Ekspresi berlebihan atau mengandung kesalahan cetak. lampirkan.c 107
#define EOF -1 static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid) { .... while (getline(&line, &line_bufsz, proc_file) != -1) { ret = sscanf(line, "CapBnd: %llx", &info->capability_mask); if (ret != EOF && ret == 1)
Jika
ret == 1 , maka jelas tidak sama dengan -1 (EOF). Validasi berlebihan,
ret! = EOF dapat dihapus.
Dua peringatan lagi dikeluarkan:
- V590 Pertimbangkan untuk memeriksa ekspresi 'ret! = (- 1) && ret == 1'. Ekspresi berlebihan atau mengandung kesalahan cetak. attach.c 579
- V590 Pertimbangkan untuk memeriksa ekspresi 'ret! = (- 1) && ret == 1'. Ekspresi berlebihan atau mengandung kesalahan cetak. attach.c 583
Hilangnya bit tinggi
V784 Ukuran bit mask kurang dari ukuran operan pertama. Ini akan menyebabkan hilangnya bit yang lebih tinggi. conf.c 1879
struct mount_opt { char *name; int clear; int flag; }; static void parse_mntopt(char *opt, unsigned long *flags, char **data, size_t size) { struct mount_opt *mo; for (mo = &mount_opt[0]; mo->name != NULL; mo++) { if (strncmp(opt, mo->name, strlen(mo->name)) == 0) { if (mo->clear) { *flags &= ~mo->flag;
Di Linux,
long adalah variabel integer 64-bit,
flag-> adalah variabel integer 32-bit. Menggunakan
flag mo-> sebagai bitmask akan menghasilkan hilangnya 32 bit paling signifikan. Casting implisit bitmask ke variabel integer 64-bit setelah inversi bitwise dilakukan. Bit tinggi topeng ini akan menjadi nol.
Tunjukkan dengan contoh:
unsigned long long x; unsigned y; .... x &= ~y;
Kode yang benar adalah:
*flags &= ~(unsigned long)(mo->flag);
Penganalisa mengeluarkan peringatan serupa lainnya:
- V784 Ukuran bit mask kurang dari ukuran operan pertama. Ini akan menyebabkan hilangnya bit yang lebih tinggi. conf.c 1933
Siklus yang mencurigakan
V612 Suatu 'pengembalian' tanpa syarat dalam satu lingkaran. conf.c 3477
#define lxc_list_for_each(__iterator, __list) \ for (__iterator = (__list)->next; __iterator != __list; \ __iterator = __iterator->next) static bool verify_start_hooks(struct lxc_conf *conf) { char path[PATH_MAX]; struct lxc_list *it; lxc_list_for_each (it, &conf->hooks[LXCHOOK_START]) { int ret; char *hookname = it->elem; ret = snprintf(path, PATH_MAX, "%s%s", conf->rootfs.path ? conf->rootfs.mount : "", hookname); if (ret < 0 || ret >= PATH_MAX) return false; ret = access(path, X_OK); if (ret < 0) { SYSERROR("Start hook \"%s\" not found in container", hookname); return false; } return true; // <= } return true; }
Siklus dimulai dan pada iterasi pertama ia terputus. Mungkin ini memang dimaksudkan, tapi kemudian siklusnya bisa dihilangkan.
Di luar batas
V557 Array underrun dimungkinkan. Nilai indeks 'bytes - 1' dapat mencapai -1. network.c 2570
static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcname, struct lxc_netdev *netdev, pid_t pid, unsigned int hooks_version) { int bytes; char buffer[PATH_MAX] = {0}; .... bytes = lxc_read_nointr(pipefd[0], &buffer, PATH_MAX); if (bytes < 0) { SYSERROR("Failed to read from pipe file descriptor"); close(pipefd[0]); } else { buffer[bytes - 1] = '\0'; } .... }
Bytes dibaca dari pipa ke buffer. Jika terjadi kesalahan, fungsi
lxc_read_nointr akan mengembalikan nilai negatif. Jika semuanya berjalan dengan baik, maka terminal nol ditulis sebagai elemen terakhir. Namun, jika 0 byte dibaca, maka buffer akan keluar dari batas, yang mengarah pada perilaku yang tidak ditentukan.
Penganalisa mengeluarkan peringatan serupa lainnya:
- V557 Array underrun dimungkinkan. Nilai indeks 'bytes - 1' dapat mencapai -1. network.c 2725
Buffer overflow
V576 Format salah. Pertimbangkan untuk memeriksa argumen aktual ketiga dari fungsi 'sscanf'. Berbahaya menggunakan penspesifikasi string tanpa spesifikasi lebar. Buffer overflow dimungkinkan. lxc_unshare.c 205
static bool lookup_user(const char *oparg, uid_t *uid) { char name[PATH_MAX]; .... if (sscanf(oparg, "%u", uid) < 1) { if (sscanf(oparg, "%s", name) < 1)
Menggunakan
sscanf dalam hal ini bisa berbahaya, karena jika panjang buffer
oparq lebih besar dari panjang buffer
nama , maka ia akan pergi ke luar negeri ketika buffer
nama terbentuk.
Kesimpulan
Seperti yang kita lihat, pengaturan pemeriksaan kode statis dari proyek kami di cloud adalah tugas yang cukup sederhana. Untuk melakukan ini, Anda hanya perlu menambahkan satu file ke repositori dan menghabiskan waktu minimum menyiapkan sistem CI. Sebagai hasilnya, kami mendapatkan alat yang memungkinkan Anda mengidentifikasi kode bermasalah pada tahap penulisan, dan tidak memungkinkan kesalahan untuk sampai ke tahap pengujian berikutnya, di mana koreksi mereka akan membutuhkan lebih banyak waktu dan sumber daya.
Tentu saja, menggunakan PVS-Studio dalam hubungannya dengan platform cloud tidak terbatas pada Travis CI. Dengan analogi dengan metode yang dijelaskan dalam artikel, dengan perbedaan minimal, analisis PVS-Studio dapat diintegrasikan dengan solusi CI berbasis cloud populer lainnya, seperti CircleCI, GitLab, dll.
Tautan yang bermanfaat
- Informasi tambahan tentang peluncuran PVS-Studio di Linux dan MacOS dapat ditemukan di sini .
- Anda dapat membaca tentang membuat, mengonfigurasi, dan menggunakan wadah dengan penganalisis statis PVS-Studio yang diinstal di sini .
- Dokumentasi TravisCI .

Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Oleg Andreev.
PVS-Studio di Awan -Lari Analisis Travis CI