Kuidas konfigureerida PVS-Studio't Travis CI-s PSP mängukonsooli emulaatori näitel
Travis CI on hajutatud veebiteenus tarkvara loomiseks ja testimiseks, mis kasutab lähtekoodi hostina GitHubi. Lisaks ülaltoodud tööstsenaariumidele saate tänu ulatuslikele konfiguratsioonivalikutele lisada oma. Selles artiklis konfigureerime Travis CI töötama koos PVS-Studioga, kasutades PPSSPP koodi näidet.
Sissejuhatus
Travis C.I. on veebiteenus tarkvara ehitamiseks ja testimiseks. Tavaliselt kasutatakse seda koos pideva integratsiooni tavadega.
PPSSPP - PSP mängukonsooli emulaator. Programm suudab emuleerida mis tahes mängude käivitamist Sony PSP jaoks mõeldud kettapiltidelt. Programm ilmus 1. novembril 2012. aastal. PPSSPP on litsentsitud GPL v2 alusel. Igaüks saab teha parandusi projekti lähtekood.
PVS-stuudio — staatiline koodianalüsaator programmikoodis vigade ja võimalike haavatavuste otsimiseks. Selles artiklis käivitame vahelduseks PVS-Studio mitte lokaalselt arendaja masinas, vaid pilves ja otsime vigu PPSSPP-st.
Hetkel ei saa Travis CI meie projekti ehitada, sest ehitamiseks puuduvad juhised. Seega on aeg seadistada.
Analüüsi käigus on meile kasulikud mõned muutujad, näiteks PVS-Studio võti, mida poleks soovitav konfiguratsioonifailis täpsustada. Nii et lisame keskkonnamuutujad, kasutades Travis CI ehitussätteid:
Meil on vaja:
PVS_USERNAME – kasutajanimi
PVS_KEY – võti
MAIL_USER – meiliaadress, mida kasutatakse aruande saatmiseks
MAIL_PASSWORD – meili parool
Kaks viimast on valikulised. Neid kasutatakse tulemuste posti teel saatmiseks. Kui soovite aruannet muul viisil levitada, ei pea te neid märkima.
Seega oleme lisanud vajalikud keskkonnamuutujad:
Nüüd loome faili .travis.yml ja asetage see projekti juure. PPSSPP-l oli juba Travis CI konfiguratsioonifail, kuid see oli liiga suur ja näite jaoks täiesti sobimatu, mistõttu pidime seda oluliselt lihtsustama ja jätma ainult põhielemendid.
Esmalt näitame keelt, Ubuntu Linuxi versiooni, mida tahame virtuaalmasinas kasutada, ja ehitamiseks vajalikud paketid:
Kõik loetletud paketid on vajalikud ainult PPSSPP jaoks.
Nüüd näitame montaažimaatriksit:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Natuke lähemalt rubriigist maatriks. Travis CI-s on ehitussuvandite loomiseks kaks võimalust: esimene on määrata kompilaatorite, operatsioonisüsteemi tüüpide, keskkonnamuutujate jms loend, mille järel genereeritakse maatriks kõigist võimalikest kombinatsioonidest; teine on maatriksi selgesõnaline märge. Muidugi saate need kaks lähenemisviisi kombineerida ja lisada ainulaadse juhtumi või, vastupidi, selle jaotise abil välistada välistama. Selle kohta saate rohkem lugeda artiklist Travis CI dokumentatsioon.
Jääb üle vaid esitada projektipõhised montaažijuhised:
Travis CI võimaldab teil lisada oma käske virtuaalse masina eluea erinevateks etappideks. jaotis enne_installimist käivitatakse enne pakettide installimist. Siis paigaldama, mis järgneb loendist pakettide installimisele addons.aptmillele me eespool osutasime. Kokkupanek ise toimub sisse käsikiri. Kui kõik läks hästi, leiame end sisse pärast_edu (Selles jaotises teostame staatilist analüüsi). Need ei ole kõik sammud, mida saab muuta, kui vajate rohkem, peaksite sisse vaatama Travis CI dokumentatsioon.
Lugemise hõlbustamiseks paigutati käsud eraldi skripti .travis.sh, mis asetatakse projekti juure.
Enne pakettide paigaldamist uuendame alammooduleid. Seda on vaja PPSSPP ehitamiseks. Lisame esimese funktsiooni juurde .travis.sh (pange tähele laiendit):
Nüüd jõuame otse PVS-Studio automaatse käivitamise seadistamiseni Travis CI-s. Kõigepealt peame süsteemi installima paketi 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
}
Funktsiooni alguses travis_install paigaldame keskkonnamuutujaid kasutades vajalikud kompilaatorid. Siis kui muutuja $PVS_ANALYZE talletab väärtust Jah (nimetasime selle jaotises env ehitusmaatriksi seadistamise ajal), installime paketi pvs-stuudio. Lisaks sellele on märgitud ka pakendid libio-socket-ssl-perl и libnet-ssleay-perl, kuid need on tulemuste postitamiseks vajalikud, seega pole need vajalikud, kui olete aruande edastamiseks valinud mõne muu meetodi.
Funktsioon download_extract laadib alla ja pakib lahti määratud arhiivi:
On aeg projekt kokku panna. See juhtub jaotises käsikiri:
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
}
Tegelikult on see lihtsustatud algkonfiguratsioon, välja arvatud järgmised read:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
Selles koodijaotuses määrasime cmmake kompileerimiskäskude eksportimise lipp. See on vajalik staatilise koodianalüsaatori jaoks. Lisateavet selle kohta saate lugeda artiklist "Kuidas käivitada PVS-Studio Linuxis ja macOS-is"
Kui kokkupanek õnnestus, siis jõuame selleni pärast_edu, kus teostame staatilist analüüsi:
Esimene rida genereerib litsentsifaili kasutajanimest ja võtmest, mille määrasime Travis CI keskkonnamuutujate seadistamisel kohe alguses.
Teine rida alustab analüüsi otse. Lipp -j määrab analüüsi lõimede arvu, lipp -l tähistab litsentsi, lippu -o määrab faili logide väljastamiseks ja lipu - disableLicenseExpirationCheck prooviversioonide jaoks vajalik, kuna vaikimisi pvs-stuudio-analüsaator hoiatab kasutajat, et litsents hakkab aeguma. Selle vältimiseks saate selle lipu määrata.
Logifail sisaldab töötlemata väljundit, mida ei saa ilma teisendamata lugeda, seega peate esmalt faili loetavaks muutma. Laseme palgid läbi plog-muundurja väljund on html-fail.
Selles näites otsustasin saata aruanded posti teel, kasutades käsku saada email.
Selle tulemusena saime järgmise faili .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;
Nüüd on aeg lükata muudatused git-hoidlasse, misjärel käivitab Travis CI ehituse automaatselt. Ehitamisaruannete avamiseks klõpsake nuppu "ppsspp".
Näeme praeguse ehituse ülevaadet:
Kui ehitamine on edukalt lõpule viidud, saame staatilise analüüsi tulemustega meili. Loomulikult ei ole postiga saatmine ainus viis aruande saamiseks. Saate valida mis tahes rakendusmeetodi. Kuid on oluline meeles pidada, et pärast ehitamise lõpetamist pole virtuaalse masina failidele juurdepääsetav.
Vea kokkuvõte
Oleme kõige raskema osa edukalt läbinud. Nüüd veendugem, et kõik meie jõupingutused on seda väärt. Vaatame mõnda huvitavat punkti staatilise analüüsi aruandest, mis mulle posti teel jõudis (pole asjata, et ma sellele viitasin).
PVS-Stuudio hoiatus: V597 Kompilaator võib kustutada funktsiooni "memset" kutse, mida kasutatakse "summa" puhvri loputamiseks. Privaatsete andmete kustutamiseks tuleks kasutada funktsiooni RtlSecureZeroMemory(). sha1.cpp 325
See koodijupp asub turvalises räsimoodulis, kuid sisaldab tõsist turvaviga (CWE-14). Vaatame silumisversiooni koostamisel genereeritud koosteloendit:
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Kõik on korras ja toimib memeset käivitatakse, kirjutades sellega üle olulised andmed RAM-is, kuid ärge rõõmustage veel. Vaatame väljalaske versiooni koosteloendit koos optimeerimisega:
Nagu nimekirjast näha, eiras koostaja kõnet memeset. See on tingitud asjaolust, et funktsioonis sha1 pärast kõnet memeset ei viidata enam struktuurile ctx. Seetõttu ei näe kompilaator mõtet raisata protsessori aega selle mälu ülekirjutamisele, mida tulevikus ei kasutata. Saate selle funktsiooni abil parandada RtlSecureZeroMemory või sarnane talle.
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-Stuudio hoiatus: V547 Avaldis 'leftvol >= 0' on alati tõene. sceAudio.cpp 120
Kõigepealt pöörake tähelepanu muule harule if. Kood käivitatakse ainult siis, kui kõik tingimused on täidetud vasakvold > 0xFFFF || paremvolt > 0xFFFF || vasakvold < 0 || paremvolt < 0 osutub valeks. Seetõttu saame järgmised väited, mis kehtivad muu haru kohta: leftvol <= 0xFFFF, rightvol <= 0xFFFF, vasakvolt >= 0 и paremvolt >= 0. Pange tähele kahte viimast väidet. Kas on mõtet kontrollida, mis on selle koodijupi täitmiseks vajalik tingimus?
Seega saame need tingimuslaused ohutult eemaldada:
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);
}
}
Teine stsenaarium. Nende üleliigsete tingimuste taga on peidus mingi viga. Võib-olla nad ei kontrollinud, mida nõuti.
V501 Lahtrist '||' vasakul ja paremal on identsed alamväljendid '!Memory::IsValidAddress(psmfData)' operaator. scePsmf.cpp 703
Pöörake tähelepanu sees olevale tšekile if. Kas teile ei tundu imelik, et me kontrollime, kas aadress on kehtiv? psmfData, kaks korda rohkem? Nii et see tundub mulle imelik... Tegelikult on see muidugi kirjaviga ja mõte oli kontrollida mõlemat sisendparameetrit.
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-Stuudio hoiatus: V547 Avaldis 'suurus == 8' on alati väär. syn-att.c 195
See viga asub kaustas ext, nii et see pole projektiga täpselt seotud, kuid viga leiti enne, kui ma seda märkasin, nii et otsustasin selle jätta. Lõppude lõpuks ei käsitle see artikkel vigade ülevaatamist, vaid integreerimist Travis CI-ga ja analüsaatorit ei konfigureeritud.
Muutuv suurus initsialiseeritakse konstandiga, kuid seda ei kasutata koodis üldse, kuni operaatorini välja if, mis muidugi annab vale tingimusi kontrollides, sest nagu mäletame, suurus võrdne nulliga. Ka hilisematel kontrollidel pole mõtet.
Ilmselt unustas koodifragmendi autor muutuja üle kirjutada suurus enne seda.
Peatus
Siin me tõenäoliselt vigadega lõpetame. Selle artikli eesmärk on demonstreerida PVS-Studio tööd koos Travis CI-ga, mitte analüüsida projekti võimalikult põhjalikult. Kui tahad suuremaid ja ilusamaid vigu, võid neid alati imetleda siin :).
Järeldus
Veebiteenuste kasutamine projektide koostamiseks koos inkrementaalse analüüsi praktikaga võimaldab leida palju probleeme kohe pärast koodi ühendamist. Samas ei pruugi ühest järgust piisata, nii et testimise seadistamine koos staatilise analüüsiga parandab oluliselt koodi kvaliteeti.