ProHoster > Blog > Administrácia > Ako nakonfigurovať PVS-Studio v Travis CI pomocou príkladu emulátora hernej konzoly PSP
Ako nakonfigurovať PVS-Studio v Travis CI pomocou príkladu emulátora hernej konzoly PSP
Travis CI je distribuovaná webová služba na vytváranie a testovanie softvéru, ktorá využíva GitHub ako hosting zdrojového kódu. Okrem vyššie uvedených operačných scenárov si môžete pridať svoje vlastné vďaka rozsiahlym možnostiam konfigurácie. V tomto článku nakonfigurujeme Travis CI na prácu s PVS-Studio pomocou príkladu kódu PPSSPP.
Úvod
Travis C.I. je webová služba na vytváranie a testovanie softvéru. Zvyčajne sa používa v spojení s postupmi nepretržitej integrácie.
PPSSPP - Emulátor hernej konzoly PSP. Program je schopný emulovať spúšťanie akýchkoľvek hier z diskových obrazov určených pre Sony PSP. Program bol vydaný 1. novembra 2012. PPSSPP je licencovaný pod GPL v2. Každý môže urobiť zlepšenie zdrojový kód projektu.
Štúdio PVS — analyzátor statického kódu na vyhľadávanie chýb a potenciálnych zraniteľností v programovom kóde. V tomto článku pre zmenu spustíme PVS-Studio nie lokálne na počítači vývojára, ale v cloude a budeme hľadať chyby v PPSSPP.
Poďme na stránku Travis C.I.. Po autorizácii pomocou vášho účtu GitHub sa nám zobrazí zoznam úložísk:
Na test som forkoval PPSSPP.
Aktivujeme úložisko, ktoré chceme zhromaždiť:
V súčasnosti nemôže Travis CI postaviť náš projekt, pretože neexistujú žiadne pokyny na stavbu. Takže je čas na konfiguráciu.
Pri analýze sa nám budú hodiť niektoré premenné, napríklad kľúč pre PVS-Studio, ktorý by bolo nežiaduce špecifikovať v konfiguračnom súbore. Pridajme teda premenné prostredia pomocou nastavení zostavy v Travis CI:
potrebujeme:
PVS_USERNAME – používateľské meno
PVS_KEY - kľúč
MAIL_USER - e-mail, ktorý bude použitý na odoslanie prehľadu
MAIL_PASSWORD - e-mailové heslo
Posledné dve sú voliteľné. Tieto budú použité na odoslanie výsledkov poštou. Ak chcete správu distribuovať iným spôsobom, nemusíte ich uvádzať.
Takže sme pridali premenné prostredia, ktoré potrebujeme:
Teraz vytvoríme súbor .travis.yml a umiestnite ho do koreňového adresára projektu. PPSSPP už mal konfiguračný súbor pre Travis CI, bol však príliš veľký a pre príklad úplne nevhodný, takže sme ho museli výrazne zjednodušiť a ponechať len základné prvky.
Najprv označme jazyk, verziu Ubuntu Linux, ktorú chceme použiť vo virtuálnom stroji, a potrebné balíčky pre zostavenie:
Všetky uvedené balíčky sú potrebné výhradne pre PPSSPP.
Teraz uvádzame montážnu maticu:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Trochu viac o sekcii matice. V Travis CI existujú dva spôsoby vytvárania možností zostavenia: prvým je špecifikácia zoznamu kompilátorov, typov operačného systému, premenných prostredia atď., po čom sa vygeneruje matica všetkých možných kombinácií; druhý je explicitný údaj o matici. Tieto dva prístupy môžete samozrejme kombinovať a pridať jedinečný prípad, alebo ho naopak pomocou sekcie vylúčiť vylúčiť. Viac si o tom môžete prečítať v Dokumentácia Travis CI.
Zostáva len poskytnúť návod na montáž pre konkrétny projekt:
Travis CI vám umožňuje pridávať vlastné príkazy pre rôzne fázy života virtuálneho počítača. oddiel pred_inštaláciou spustené pred inštaláciou balíkov. Potom inštalovať, ktorá nasleduje po inštalácii balíkov zo zoznamu addons.aptktoré sme naznačili vyššie. Samotná montáž prebieha v scenár. Ak všetko pôjde dobre, ocitneme sa tam po_úspechu (v tejto časti spustíme statickú analýzu). Toto nie sú všetky kroky, ktoré možno upraviť, ak potrebujete viac, mali by ste sa pozrieť Dokumentácia Travis CI.
Pre uľahčenie čítania boli príkazy umiestnené v samostatnom skripte .travis.sh, ktorý je umiestnený v koreňovom adresári projektu.
Teraz prejdeme priamo k nastaveniu automatického spustenia PVS-Studio v Travis CI. Najprv musíme do systému nainštalovať balík PVS-Studio:
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
}
Na začiatku funkcie travis_install nainštalujeme kompilátory, ktoré potrebujeme, pomocou premenných prostredia. Potom ak premenná $ PVS_ANALYZE uchováva hodnotu Áno (uviedli sme to v sekcii ca. počas konfigurácie zostavovacej matice), nainštalujeme balík pvs-štúdio. Okrem toho sú uvedené aj balíčky libio-socket-ssl-perl и libnet-ssleay-perl, sú však potrebné na odosielanie výsledkov poštou, takže nie sú potrebné, ak ste si vybrali iný spôsob doručenia správy.
Funkcia download_extract stiahne a rozbalí zadaný archív:
Je čas dať projekt dokopy. Toto sa deje v sekcii scenár:
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
}
V skutočnosti ide o zjednodušenú pôvodnú konfiguráciu, s výnimkou týchto riadkov:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
V tejto časti kódu sme si stanovili cmake príznak pre export kompilačných príkazov. Toto je potrebné pre analyzátor statického kódu. Viac si o tom môžete prečítať v článku „Ako spustiť PVS-Studio na Linuxe a MacOS".
Ak bola montáž úspešná, tak sa dostávame do po_úspechu, kde vykonávame statickú analýzu:
Prvý riadok vygeneruje licenčný súbor z používateľského mena a kľúča, ktoré sme zadali na úplnom začiatku pri nastavovaní premenných prostredia Travis CI.
Druhý riadok spustí analýzu priamo. Vlajka -j nastavuje počet vlákien na analýzu, príznak -l označuje licenciu, vlajku -o definuje súbor pre výstup protokolov a príznak -disableLicenseExpirationCheck vyžadované pre skúšobné verzie, pretože štandardne pvs-studio-analyzer upozorní používateľa, že platnosť licencie čoskoro vyprší. Aby ste tomu zabránili, môžete zadať tento príznak.
Protokolový súbor obsahuje nespracovaný výstup, ktorý nie je možné prečítať bez konverzie, takže najprv musíte súbor sprístupniť. Prejdeme cez polená plog-konvertora výstupom je súbor html.
V tomto príklade som sa rozhodol posielať správy poštou pomocou príkazu poslať email.
V dôsledku toho sme dostali nasledujúci súbor .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;
Teraz je čas presunúť zmeny do úložiska git, po ktorom Travis CI automaticky spustí zostavenie. Kliknutím na „ppsspp“ prejdete na zostavy zostavy:
Uvidíme prehľad aktuálnej zostavy:
Ak je zostava úspešne dokončená, dostaneme e-mail s výsledkami statickej analýzy. Poštová zásielka samozrejme nie je jediným spôsobom, ako dostať správu. Môžete si vybrať akýkoľvek spôsob implementácie. Je však dôležité si uvedomiť, že po dokončení zostavenia nebude možné pristupovať k súborom virtuálneho počítača.
Súhrn chýb
Najťažšiu časť máme úspešne za sebou. Teraz sa presvedčte, že všetko naše úsilie stojí za to. Pozrime sa na niektoré zaujímavé body zo správy o statickej analýze, ktorá mi prišla poštou (nie nadarmo som to naznačil).
Upozornenie PVS-Studio: V597 Kompilátor mohol vymazať volanie funkcie 'memset', ktoré sa používa na vyprázdnenie vyrovnávacej pamäte 'súčet'. Na vymazanie súkromných údajov by sa mala použiť funkcia RtlSecureZeroMemory(). sha1.cpp 325
Tento kus kódu sa nachádza v zabezpečenom hašovacom module, obsahuje však závažnú bezpečnostnú chybu (CWE-14). Pozrime sa na výpis zostavy, ktorý sa generuje pri kompilácii verzie ladenia:
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Všetko je v poriadku a funkcia memeset sa vykoná, čím sa prepíšu dôležité dáta v RAM, no zatiaľ sa neradujte. Pozrime sa na zoznam zostavy verzie Release s optimalizáciou:
Ako vidno z výpisu, kompilátor volanie ignoroval memeset. Je to spôsobené tým, že vo funkcii sha1 po hovore memeset už žiadny odkaz na štruktúru ctx. Preto kompilátor nevidí zmysel v plytvaní časom procesora prepisovaním pamäte, ktorá sa v budúcnosti nepoužije. Môžete to opraviť pomocou funkcie RtlSecureZeroMemory alebo podobný jej.
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);
}
}
Upozornenie PVS-Studio: V547 Výraz 'leftvol >= 0' je vždy pravdivý. sceAudio.cpp 120
Najprv venujte pozornosť vetve else if. Kód bude vykonaný, iba ak sú splnené všetky podmienky leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0 sa ukáže ako falošný. Preto dostaneme nasledujúce tvrdenia, ktoré budú platiť pre vetvu else: leftvol <= 0xFFFF, rightvol <= 0xFFFF, leftvol >= 0 и rightvol >= 0. Všimnite si posledné dva výroky. Má zmysel kontrolovať, čo je nevyhnutnou podmienkou pre vykonanie tohto kusu kódu?
Takže môžeme bezpečne odstrániť tieto podmienené príkazy:
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);
}
}
Ďalší scenár. Za týmito nadbytočnými podmienkami sa skrýva nejaký druh chyby. Možno neskontrolovali, čo bolo potrebné.
V501 Naľavo a napravo od výrazu '||' sú rovnaké podvýrazy '!Memory::IsValidAddress(psmfData)' operátor. scePsmf.cpp 703
Venujte pozornosť kontrole vo vnútri if. Nezdá sa vám zvláštne, že kontrolujeme, či je adresa platná? psmfData, dva krát toľko? Tak toto sa mi zdá zvláštne... V skutočnosti ide samozrejme o preklep a zámerom bolo skontrolovať oba vstupné parametre.
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");
}
....
}
Upozornenie PVS-Studio: V547 Výraz 'veľkosť == 8' je vždy nepravdivý. syn-att.c 195
Táto chyba sa nachádza v priečinku ext, takže to naozaj nie je relevantné pre projekt, ale chyba sa našla skôr, ako som si ju všimol, tak som sa rozhodol ju nechať. Koniec koncov, tento článok nie je o kontrole chýb, ale o integrácii s Travis CI a nebola vykonaná žiadna konfigurácia analyzátora.
Variabilné veľkosť sa inicializuje konštantou, tá sa však v kóde vôbec nepoužíva, až po operátora if, čo, samozrejme, dáva nepravdivý pri kontrole podmienok, pretože, ako si pamätáme, veľkosť rovná nule. Následné kontroly tiež nemajú zmysel.
Autor fragmentu kódu zrejme zabudol prepísať premennú veľkosť pred tým.
Stop
Tu asi s chybami skončíme. Účelom tohto článku je demonštrovať prácu PVS-Studio spolu s Travis CI a nie čo najdôkladnejšie analyzovať projekt. Ak chcete väčšie a krajšie chyby, vždy ich môžete obdivovať tu :).
Záver
Používanie webových služieb na vytváranie projektov spolu s praxou prírastkovej analýzy vám umožňuje nájsť veľa problémov ihneď po zlúčení kódu. Jedno zostavenie však nemusí stačiť, takže nastavenie testovania spolu so statickou analýzou výrazne zlepší kvalitu kódu.