Travis CI is in ferspraat webtsjinst foar it bouwen en testen fan software dy't GitHub brûkt as boarnekoade-hosting. Neist de boppesteande operaasjescenario's kinne jo jo eigen tafoegje troch de wiidweidige konfiguraasjeopsjes. Yn dit artikel sille wy Travis CI konfigurearje om te wurkjen mei PVS-Studio mei it PPSSPP-koadefoarbyld.
Ynlieding
It ynstellen fan Travis CI
Wy sille in repository nedich hawwe op GitHub, wêr't it projekt dat wy nedich is leit, lykas ek in kaai foar PVS-Studio (jo kinne krije
Litte wy nei de side gean
Foar de test forkearde ik PPSSPP.
Wy aktivearje it repository dat wy wolle sammelje:
Op it stuit kin Travis CI ús projekt net bouwe, om't d'r gjin ynstruksjes binne foar it bouwen. Dus it is tiid foar konfiguraasje.
Tidens de analyze, guon fariabelen sille wêze nuttich foar ús, bygelyks, de kaai foar PVS-Studio, dat soe wêze net winske te spesifisearje yn de konfiguraasje triem. Dat litte wy omjouwingsfariabelen tafoegje mei de bouynstellingen yn Travis CI:
Wy sille nedich wêze:
- PVS_USERNAME - brûkersnamme
- PVS_KEY - kaai
- MAIL_USER - e-post dy't brûkt wurdt om it rapport te ferstjoeren
- MAIL_PASSWORD - e-postwachtwurd
De lêste twa binne opsjoneel. Dizze sille brûkt wurde om resultaten per post te ferstjoeren. As jo it rapport op in oare manier ferspriede wolle, hoege jo dy net oan te jaan.
Dat, wy hawwe de omjouwingsfariabelen tafoege dy't wy nedich binne:
Litte wy no in bestân oanmeitsje .travis.yml en pleats it yn 'e woartel fan it projekt. PPSSPP hie al in konfiguraasjetriem foar Travis CI, lykwols, it wie te grut en folslein net geskikt foar it foarbyld, dus wy moasten it sterk ferienfâldigje en allinich de basiseleminten litte.
Litte wy earst de taal oanjaan, de ferzje fan Ubuntu Linux dy't wy wolle brûke yn 'e firtuele masine, en de nedige pakketten foar it bouwen:
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'
Alle pakketten dy't neamd binne binne eksklusyf nedich foar PPSSPP.
No jouwe wy de gearstalling matrix oan:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
In bytsje mear oer de seksje matrix. Yn Travis CI binne d'r twa manieren om bouwopsjes te meitsjen: de earste is om in list fan gearstallers, typen fan bestjoeringssysteem, omjouwingsfariabelen, ensfh., wêrnei't in matriks fan alle mooglike kombinaasjes wurdt oanmakke; de twadde is in eksplisite oantsjutting fan 'e matrix. Fansels kinne jo dizze twa oanpakken kombinearje en in unyk gefal tafoegje, of krekt oarsom, it útslute mei de seksje útslute. Jo kinne mear oer dit lêze yn
Alles wat oerbliuwt is projektspesifike montage-ynstruksjes te leverjen:
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 lit jo jo eigen kommando's tafoegje foar ferskate stadia fan it libben fan in firtuele masine. Ôfdieling before_install útfierd foardat jo pakketten ynstallearje. Dan ynstallearje, dy't folget de ynstallaasje fan pakketten út 'e list addons.aptdy't wy hjirboppe oanjûn hawwe. De gearkomste sels fynt plak yn skrift. As alles goed gie, dan fine wy ússels yn after_success (it is yn dizze seksje dat wy statyske analyze sille útfiere). Dit binne net alle stappen dy't kinne wurde wizige, as jo mear nedich binne, dan moatte jo deryn sjen
Foar it gemak fan it lêzen waarden de kommando's yn in apart skript pleatst .travis.sh, dat wurdt pleatst by de projekt root.
Sa hawwe wy de folgjende triem .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
Foardat jo de pakketten ynstallearje, sille wy de submodules bywurkje. Dit is nedich om PPSSPP te bouwen. Litte wy de earste funksje tafoegje oan .travis.sh (note de útwreiding):
travis_before_install() {
git submodule update --init --recursive
}
No komme wy direkt by it ynstellen fan de automatyske lansearring fan PVS-Studio yn Travis CI. Earst moatte wy it PVS-Studio-pakket op it systeem ynstallearje:
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
}
Oan it begjin fan 'e funksje travis_install wy ynstallearje de gearstallers dy't wy nedich hawwe mei help fan omjouwingsfariabelen. Dan as de fariabele $PVS_ANALYSE winkels wearde Ja (wy hawwe it oanjûn yn 'e seksje sawat tidens build matrix konfiguraasje), ynstallearje wy it pakket pvs-studio. Dêrnjonken wurde ek pakketten oanjûn libio-socket-ssl-perl и libnet-ssleay-perl, lykwols, se binne nedich foar mailing resultaten, dus se binne net nedich as jo hawwe keazen in oare metoade foar it leverjen fan jo rapport.
function download_extract downloadt en útpakt it opjûne argyf:
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
It is tiid om it projekt byinoar te bringen. Dit bart yn 'e seksje skrift:
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
}
Yn feite is dit in ferienfâldige orizjinele konfiguraasje, útsein dizze rigels:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
Yn dizze seksje fan koade wy ynstelle foar cmke flagge foar it eksportearjen fan kompilaasjekommando's. Dit is nedich foar in statyske koade analyzer. Jo kinne hjir mear oer lêze yn it artikel "
As de gearkomste suksesfol wie, dan komme wy oan after_success, wêr't wy statyske analyze útfiere:
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
}
Litte wy de folgjende rigels in tichterby besjen:
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
De earste rigel genereart in lisinsjebestân fan 'e brûkersnamme en kaai dy't wy oan it begjin spesifisearre hawwe by it ynstellen fan de Travis CI-omjouwingsfariabelen.
De twadde rigel begjint de analyze direkt. Flagge -j stelt it oantal triedden foar analyze, flagge -l jout lisinsje, flagge -o definiearret de triem foar it útfieren fan logs, en de flagge -disableLicenseExpirationCheck fereaske foar proefferzjes, sûnt standert pvs-studio-analyzer sil de brûker warskôgje dat de lisinsje op it punt is te ferrinnen. Om foar te kommen dat dit bart, kinne jo dizze flagge opjaan.
It lochbestân befettet rau útfier dy't net lêzen wurde kin sûnder konverzje, dus jo moatte earst it bestân lêsber meitsje. Litte wy de logs trochjaan plog-konverter, en de útfier is in html-bestân.
Yn dit foarbyld haw ik besletten om rapporten per post te stjoeren mei it kommando Stjoer email.
As gefolch hawwe wy it folgjende bestân krigen .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;
No is it tiid om de wizigingen nei it git-repository te triuwen, wêrnei't Travis CI de build automatysk sil útfiere. Klikje op "ppsspp" om nei de bourapporten te gean:
Wy sille in oersjoch sjen fan 'e hjoeddeistige bou:
As de bou mei súkses foltôge is, krije wy in e-post mei de resultaten fan 'e statyske analyse. Fansels is mailing net de ienige manier om in rapport te ûntfangen. Jo kinne elke ymplemintaasjemetoade kieze. Mar it is wichtich om te ûnthâlden dat nei it bouwen is foltôge, it sil net mooglik wêze om tagong te krijen ta de firtuele masine-bestannen.
Flater gearfetting
Wy hawwe it dreechste diel mei súkses foltôge. Litte wy no soargje dat al ús ynspanningen it wurdich binne. Litte wy ris nei wat nijsgjirrige punten sjen út it statyske analyserapport dat per post by my kaam (it wie net foar neat dat ik it oanjûn hie).
Gefaarlike optimalisaasje
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 warskôging:
Dit stik koade leit yn 'e befeilige hashingmodule, it befettet lykwols in serieuze befeiligingsfout (
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Alles is yn oarder en de funksje memeset wurdt útfierd, dêrmei oerskriuwe wichtige gegevens yn RAM, lykwols net bliid krekt noch. Litte wy sjen nei de gearstallingslist fan 'e Release-ferzje mei optimisaasje:
; 354 :
; 355 : memset( sum, 0, sizeof( sum ) );
; 356 :}
Lykas kin wurde sjoen út de list, negearre de gearstaller de oprop memeset. Dit komt troch it feit dat yn 'e funksje sha1 nei de oprop memeset gjin ferwizing mear nei struktuer ctx. Dêrom, de gearstaller sjocht gjin punt yn fergrieme prosessor tiid oerskriuwen ûnthâld dat wurdt net brûkt yn 'e takomst. Jo kinne dit reparearje mei de funksje RtlSecureZeroMemory of
Korrekt:
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 ) );
}
Unnedich ferliking
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 warskôging:
Jou omtinken oan 'e oare tûke foar de earste if. De koade sil allinich útfierd wurde as alle betingsten leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rjochts < 0 sil blike te wêzen falsk. Dêrom krije wy de folgjende útspraken, dy't wier wêze sille foar de oare branch: leftvol <= 0xFFFF, rightvol <= 0xFFFF, leftvol >= 0 и rjochtsvol >= 0. Let op de lêste twa útspraken. Hat it sin om te kontrolearjen wat in needsaaklike betingst is foar de útfiering fan dit stik koade?
Sa kinne wy dizze betingsten útspraken feilich fuortsmite:
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);
}
}
In oar senario. D'r is wat soarte flater ferburgen efter dizze oerstallige betingsten. Miskien hawwe se net kontrolearre wat der nedich wie.
Ctrl+C Ctrl+V slacht werom
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfData) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Jou omtinken oan de kontrôle binnen if. Fynsto it net nuver dat wy kontrolearje oft it adres jildich is? psmfData, twa kear safolle? Dit liket my dus nuver... Eins is dit fansels in typflater, en it idee wie om beide ynfierparameters te kontrolearjen.
Korrekte opsje:
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfStruct) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Ferjitten fariabele
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 warskôging:
Dizze flater leit yn 'e map ext, Dus net echt relevant foar it projekt, mar de brek waard fûn foardat ik it opmurken, dus ik besleat it te ferlitten. Dit artikel is ommers net oer it besjen fan flaters, mar oer yntegraasje mei Travis CI, en gjin konfiguraasje fan 'e analysator waard útfierd.
Variable grutte wurdt inisjalisearre troch in konstante, lykwols, it wurdt net brûkt hielendal yn de koade, rjocht omleech nei de operator if, dy't fansels jout falsk wylst wy de betingsten kontrolearje, om't, lykas wy ús ûnthâlde, grutte gelyk oan nul. De folgjende kontrôles hawwe ek gjin sin.
Blykber fergeat de skriuwer fan it koadefragmint de fariabele te oerskriuwen grutte dêrfoar.
Ophâlde
Dit is wêr't wy wierskynlik einigje mei de flaters. It doel fan dit artikel is om it wurk fan PVS-Studio tegearre mei Travis CI te demonstrearjen, en net it projekt sa yngeand mooglik te analysearjen. As jo gruttere en moaier flaters wolle, kinne jo se altyd bewûnderje
konklúzje
It brûken fan webtsjinsten om projekten te bouwen tegearre mei de praktyk fan inkrementele analyze kinne jo in protte problemen fine direkt nei it fusearjen fan koade. Ien build kin lykwols net genôch wêze, dus it opsetten fan testen tegearre mei statyske analyse sil de kwaliteit fan 'e koade signifikant ferbetterje.
Nuttige keppelings
As jo dit artikel wolle diele mei in Ingelsktalig publyk, brûk dan de oersettingskeppeling: Maxim Zvyagintsev.
Boarne: www.habr.com