Travis CI minangka layanan web sing disebarake kanggo mbangun lan nguji piranti lunak sing nggunakake GitHub minangka hosting kode sumber. Saliyane ing skenario operasi ndhuwur, sampeyan bisa nambah thanks dhewe kanggo opsi konfigurasi ekstensif. Ing artikel iki, kita bakal ngatur Travis CI kanggo nggarap PVS-Studio nggunakake conto kode PPSSPP.
Pambuka
Nggawe Travis CI
Kita butuh repositori ing GitHub, ing ngendi proyek sing kita butuhake, uga kunci kanggo PVS-Studio (sampeyan bisa entuk
Ayo menyang situs
Kanggo tes, aku nyuwil PPSSPP.
Kita ngaktifake repositori sing pengin diklumpukake:
Ing wayahe, Travis CI ora bisa mbangun proyek kita amarga ora ana instruksi kanggo mbangun. Dadi wektu kanggo konfigurasi.
Sajrone analisis, sawetara variabel bakal migunani kanggo kita, contone, tombol kanggo PVS-Studio, sing ora dikarepake kanggo nemtokake ing file konfigurasi. Dadi ayo nambah variabel lingkungan nggunakake setelan mbangun ing Travis CI:
Kita kudu:
- PVS_USERNAME - jeneng panganggo
- PVS_KEY - tombol
- MAIL_USER - email sing bakal digunakake kanggo ngirim laporan
- MAIL_PASSWORD - sandi email
Loro pungkasan iku opsional. Iki bakal digunakake kanggo ngirim asil liwat mail. Yen sampeyan pengin nyebarake laporan kanthi cara liya, sampeyan ora perlu menehi tandha.
Dadi, kita wis nambahake variabel lingkungan sing dibutuhake:
Saiki ayo nggawe file .travis.yml lan sijine iku ing ROOT saka project. PPSSPP wis duwe file konfigurasi kanggo Travis CI, Nanging, iku gedhe banget lan ora cocog kanggo contone, supaya kita kudu nemen menakake lan ninggalake mung unsur dhasar.
Pisanan, ayo nuduhake basa, versi Ubuntu Linux sing pengin digunakake ing mesin virtual, lan paket sing dibutuhake kanggo mbangun:
language: cpp
dist: xenial
addons:
apt:
update: true
packages:
- ant
- aria2
- build-essential
- cmake
- libgl1-mesa-dev
- libglu1-mesa-dev
- libsdl2-dev
- pv
- sendemail
- software-properties-common
sources:
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'ppa:ubuntu-sdk-team/ppa'
Kabeh paket sing kadhaptar dibutuhake khusus kanggo PPSSPP.
Saiki kita nuduhake matriks perakitan:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
A sethitik liyane babagan bagean Matriks. Ing Travis CI, ana rong cara kanggo nggawe opsi mbangun: sing pisanan yaiku nemtokake dhaptar kompiler, jinis sistem operasi, variabel lingkungan, lan liya-liyane, sawise matriks kabeh kombinasi sing bisa digawe; kapindho minangka pratondo eksplisit saka matriks. Mesthi, sampeyan bisa nggabungake loro pendekatan kasebut lan nambah kasus sing unik, utawa, sebaliknya, ora kalebu nggunakake bagean kasebut. ngilangi. Sampeyan bisa maca liyane babagan iki ing
Kabeh sing isih ana yaiku nyedhiyakake instruksi perakitan khusus proyek:
before_install:
- travis_retry bash .travis.sh travis_before_install
install:
- travis_retry bash .travis.sh travis_install
script:
- bash .travis.sh travis_script
after_success:
- bash .travis.sh travis_after_success
Travis CI ngijini sampeyan kanggo nambah printah dhewe kanggo macem-macem orane tumrap sekolah saka urip mesin virtual. Bagean sadurunge_instal dieksekusi sadurunge nginstal paket. Banjur masang, sing nderek instalasi paket saka dhaptar addons.aptsing wis dituduhake ing ndhuwur. Majelis dhewe njupuk Panggonan ing script. Yen kabeh mlaku kanthi becik, mula kita bakal mlebu sawise_sukses (Ing bagean iki kita bakal mbukak analisis statis). Iki ora kabeh langkah sing bisa diowahi, yen sampeyan butuh luwih akeh, sampeyan kudu ndeleng
Kanggo gampang diwaca, prentah kasebut diselehake ing naskah sing kapisah .travis.sh, kang diselehake ing ROOT project.
Dadi kita duwe file ing ngisor iki .travis.yml:
language: cpp
dist: xenial
addons:
apt:
update: true
packages:
- ant
- aria2
- build-essential
- cmake
- libgl1-mesa-dev
- libglu1-mesa-dev
- libsdl2-dev
- pv
- sendemail
- software-properties-common
sources:
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'ppa:ubuntu-sdk-team/ppa'
matrix:
include:
- os: linux
compiler: "gcc"
env: PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
before_install:
- travis_retry bash .travis.sh travis_before_install
install:
- travis_retry bash .travis.sh travis_install
script:
- bash .travis.sh travis_script
after_success:
- bash .travis.sh travis_after_success
Sadurunge nginstal paket, kita bakal nganyari submodul. Iki perlu kanggo mbangun PPSSPP. Ayo dadi nambah fungsi pisanan kanggo .travis.sh (cathetan ekstensi):
travis_before_install() {
git submodule update --init --recursive
}
Saiki kita langsung nyiyapake peluncuran otomatis PVS-Studio ing Travis CI. Pisanan kita kudu nginstal paket PVS-Studio ing sistem:
travis_install() {
if [ "$CXX" = "g++" ]; then
sudo apt-get install -qq g++-4.8
fi
if [ "$PVS_ANALYZE" = "Yes" ]; then
wget -q -O - https://files.viva64.com/etc/pubkey.txt
| sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio
libio-socket-ssl-perl
libnet-ssleay-perl
fi
download_extract
"https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz"
cmake-3.6.2-Linux-x86_64.tar.gz
}
Ing wiwitan fungsi travis_install kita nginstal kompiler sing kita butuhake nggunakake variabel lingkungan. Banjur yen variabel $PVS_ANALYZE nyimpen nilai Ya (kita nuduhake ing bagean kasebut sugeng nalika mbangun konfigurasi matriks), kita nginstal paket kasebut pvs-studio. Saliyane iki, paket uga dituduhake libio-soket-ssl-perl ΠΈ libnet-ssleay-perl, Nanging, iku dibutuhake kanggo asil mail, supaya iku ora perlu yen sampeyan wis milih cara liyane kanggo ngirim laporan.
fungsi download_ekstrak ngundhuh lan mbongkar arsip sing ditemtokake:
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
Iku wektu kanggo sijine proyek bebarengan. Iki kedadeyan ing bagean kasebut script:
travis_script() {
if [ -d cmake-3.6.2-Linux-x86_64 ]; then
export PATH=$(pwd)/cmake-3.6.2-Linux-x86_64/bin:$PATH
fi
CMAKE_ARGS="-DHEADLESS=ON ${CMAKE_ARGS}"
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
cmake $CMAKE_ARGS CMakeLists.txt
make
}
Nyatane, iki minangka konfigurasi asli sing disederhanakake, kajaba baris kasebut:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
Ing bagean kode iki kita nyetel kanggo cmake flag kanggo ngekspor printah kompilasi. Iki perlu kanggo penganalisa kode statis. Sampeyan bisa maca liyane babagan iki ing artikel "
Yen majelis wis sukses, banjur kita njaluk menyang sawise_sukses, ing ngendi kita nindakake analisis statis:
travis_after_success() {
if [ "$PVS_ANALYZE" = "Yes" ]; then
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic
-o PVS-Studio-${CC}.log
--disableLicenseExpirationCheck
plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html
sendemail -t [email protected]
-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
fi
}
Ayo katon luwih cetha ing baris ing ngisor iki:
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic
-o PVS-Studio-${CC}.log
--disableLicenseExpirationCheck
plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html
Baris pisanan ngasilake file lisensi saka jeneng pangguna lan kunci sing wis ditemtokake ing wiwitan nalika nyetel variabel lingkungan Travis CI.
Baris kapindho miwiti analisis langsung. GendΓ©ra -j nyetel nomer Utas kanggo analisis, flag -l nuduhake lisensi, flag -o nemtokake file kanggo outputting log, lan flag -disableLicenseExpirationCheck dibutuhake kanggo versi nyoba, wiwit minangka standar pvs-studio-analyzer bakal ngelingake pangguna yen lisensi bakal kadaluwarsa. Kanggo nyegah kedadeyan kasebut, sampeyan bisa nemtokake gendera iki.
File log ngemot output mentah sing ora bisa diwaca tanpa konversi, mula sampeyan kudu nggawe file kasebut bisa diwaca. Ayo liwat log liwat plug-converter, lan output minangka file html.
Ing conto iki, aku mutusake ngirim laporan kanthi mail nggunakake printah sendemail.
AkibatΓ©, kita entuk file ing ngisor iki .travis.sh:
#/bin/bash
travis_before_install() {
git submodule update --init --recursive
}
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
travis_install() {
if [ "$CXX" = "g++" ]; then
sudo apt-get install -qq g++-4.8
fi
if [ "$PVS_ANALYZE" = "Yes" ]; then
wget -q -O - https://files.viva64.com/etc/pubkey.txt
| sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio
libio-socket-ssl-perl
libnet-ssleay-perl
fi
download_extract
"https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz"
cmake-3.6.2-Linux-x86_64.tar.gz
}
travis_script() {
if [ -d cmake-3.6.2-Linux-x86_64 ]; then
export PATH=$(pwd)/cmake-3.6.2-Linux-x86_64/bin:$PATH
fi
CMAKE_ARGS="-DHEADLESS=ON ${CMAKE_ARGS}"
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
cmake $CMAKE_ARGS CMakeLists.txt
make
}
travis_after_success() {
if [ "$PVS_ANALYZE" = "Yes" ]; then
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic
-o PVS-Studio-${CC}.log
--disableLicenseExpirationCheck
plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html
sendemail -t [email protected]
-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
fi
}
set -e
set -x
$1;
Saiki wektune kanggo push owah-owahan menyang repositori git, sawise Travis CI bakal kanthi otomatis mbukak mbangun. Klik ing "ppsspp" kanggo pindhah menyang laporan mbangun:
Kita bakal weruh ringkesan babagan bangunan saiki:
Yen mbangun kasil rampung, kita bakal nampa email karo asil analisis statis. Mesthi, surat ora mung cara kanggo nampa laporan. Sampeyan bisa milih cara implementasine. Nanging penting kanggo elinga yen sawise mbangun rampung, ora bakal bisa ngakses file mesin virtual.
Ringkesan kesalahan
Kita wis kasil ngrampungake bagean sing paling angel. Saiki ayo padha mesthekake yen kabeh usaha kita bakal entuk manfaat. Ayo goleki sawetara poin sing menarik saka laporan analisis statis sing teka ing emailku (ora ana gunane sing dakkandhakake).
Optimasi mbebayani
void sha1( unsigned char *input, int ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
PVS-Studio warning:
Potongan kode iki ana ing modul hashing sing aman, nanging ngemot cacat keamanan sing serius (
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Kabeh ana ing urutan lan fungsi memeset wis kaleksanan, mangkono nimpa data penting ing RAM, Nanging, aja bungah mung durung. Ayo ndeleng dhaptar perakitan versi Rilis kanthi optimalisasi:
; 354 :
; 355 : memset( sum, 0, sizeof( sum ) );
; 356 :}
Kaya sing bisa dideleng saka dhaptar, kompiler ora nggatekake telpon kasebut memeset. Iki amarga kasunyatan sing ing fungsi sha1 sawise telpon memeset ora ana maneh referensi kanggo struktur CTX. Mulane, compiler weruh ora ana titik kanggo mbuang wektu prosesor overwriting memori sing ora digunakake ing mangsa. Sampeyan bisa ndandani iki kanthi nggunakake fungsi kasebut RtlSecureZeroMemory utawa
Bener:
void sha1( unsigned char *input, int ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
RtlSecureZeroMemory(&ctx, sizeof( sha1_context ) );
}
Perbandingan sing ora perlu
static u32 sceAudioOutputPannedBlocking
(u32 chan, int leftvol, int rightvol, u32 samplePtr) {
int result = 0;
// For some reason, this is the only one that checks for negative.
if (leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0) {
....
} else {
if (leftvol >= 0) {
chans[chan].leftVolume = leftvol;
}
if (rightvol >= 0) {
chans[chan].rightVolume = rightvol;
}
chans[chan].sampleAddress = samplePtr;
result = __AudioEnqueue(chans[chan], chan, true);
}
}
PVS-Studio warning:
Pay manungsa waé menyang cabang liyane kanggo pisanan if. Kode bakal dieksekusi mung yen kabeh kahanan leftvol > 0xFFFF || volume tengen > 0xFFFF || kiwavol < 0 || volume tengen <0 bakal dadi palsu. Mulane, kita entuk pernyataan ing ngisor iki, sing bakal bener kanggo cabang liya: volume kiwa <= 0xFFFF, volume tengen <= 0xFFFF, volume kiri >= 0 и volume tengen > = 0. Wigati rong statement pungkasan. Apa ana pangertèn kanggo mriksa apa syarat sing dibutuhake kanggo eksekusi kode kasebut?
Supaya kita bisa mbusak statement kondisional iki kanthi aman:
static u32 sceAudioOutputPannedBlocking
(u32 chan, int leftvol, int rightvol, u32 samplePtr) {
int result = 0;
// For some reason, this is the only one that checks for negative.
if (leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0) {
....
} else {
chans[chan].leftVolume = leftvol;
chans[chan].rightVolume = rightvol;
chans[chan].sampleAddress = samplePtr;
result = __AudioEnqueue(chans[chan], chan, true);
}
}
Skenario liyane. Ana sawetara jinis kesalahan sing didhelikake ing mburi kahanan sing berlebihan iki. Mbok menawa dheweke ora mriksa apa sing dibutuhake.
Ctrl+C Ctrl+V Strike Back
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfData) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Pay manungsa waé menyang mriksa nang if. Apa sampeyan ora mikir aneh yen kita mriksa alamat kasebut bener? psmfData, ping pindho? Dadi iki misale jek aneh kanggo kula ... Ing kasunyatan, iki, mesthi, typo, lan idea iki kanggo mriksa loro paramèter input.
Pilihan sing bener:
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfStruct) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
variabel lali
extern void ud_translate_att(
int size = 0;
....
if (size == 8) {
ud_asmprintf(u, "b");
} else if (size == 16) {
ud_asmprintf(u, "w");
} else if (size == 64) {
ud_asmprintf(u, "q");
}
....
}
PVS-Studio warning:
Kesalahan iki dumunung ing folder kasebut ext, dadi ora cocog karo proyek kasebut, nanging bug kasebut ditemokake sadurunge aku weruh, mula aku mutusake ninggalake. Sawise kabeh, artikel iki dudu babagan mriksa kesalahan, nanging babagan integrasi karo Travis CI, lan ora ana konfigurasi analisa sing ditindakake.
Variabel ukuran wis initialized dening pancet, Nanging, iku ora digunakake ing kabeh ing kode, hak mudhun kanggo operator if, kang, mesthi, menehi palsu nalika mriksa kahanan, amarga kita elinga, ukuran padha karo nul. Priksa sabanjure uga ora ana gunane.
Ketoke, penulis fragmen kode kelalen nimpa variabel kasebut ukuran sadurunge iku.
mungkasi
Iki ngendi kita bakal mungkasi karo kesalahan. Tujuan saka artikel iki kanggo nduduhake karya PVS-Studio bebarengan karo Travis CI, lan ora kanggo njelasno project sak tenane sabisa. Yen sampeyan pengin kesalahan sing luwih gedhe lan luwih apik, sampeyan bisa tansah ngujo
kesimpulan
Nggunakake layanan web kanggo mbangun proyek bebarengan karo praktik analisis tambahan ngidini sampeyan nemokake akeh masalah langsung sawise nggabungake kode. Nanging, siji mbangun bisa uga ora cukup, supaya nyetel testing bebarengan karo analisis statis bakal Ngartekno nambah kualitas kode.
link migunani
Yen sampeyan pengin nuduhake artikel iki karo pamirsa sing nganggo basa Inggris, gunakake tautan terjemahan: Maxim Zvyagintsev.
Source: www.habr.com