Travis CI GitHub iturburu-kode ostalari gisa erabiltzen duen softwarea eraikitzeko eta probatzeko banatutako web zerbitzu bat da. Goiko funtzionamendu eszenatokiez gain, zurea gehi dezakezu konfigurazio aukera zabalei esker. Artikulu honetan Travis CI PVS-Studio-rekin lan egiteko konfiguratuko dugu PPSSPP kodearen adibidea erabiliz.
Sarrera
Travis CI konfiguratzea
GitHub-en biltegi bat beharko dugu, non behar dugun proiektua dagoen, baita PVS-Studiorako gako bat ere (lortu dezakezu
Goazen gunera
Proba egiteko, PPSSPP bifurkatu nuen.
Bildu nahi dugun biltegia aktibatzen dugu:
Momentuz, Travis CIk ezin du gure proiektua eraiki eraikitzeko argibiderik ez dagoelako. Beraz, konfiguratzeko garaia da.
Azterketan zehar, aldagai batzuk baliagarriak izango zaizkigu, adibidez, PVS-Studiorako gakoa, konfigurazio fitxategian zehaztea komeni ez dena. Beraz, gehitu ditzagun ingurune-aldagaiak Travis CI-ko eraikuntza-ezarpenak erabiliz:
Beharko dugu:
- PVS_USERNAME - erabiltzaile-izena
- PVS_KEY - tekla
- MAIL_USER - txostena bidaltzeko erabiliko den helbide elektronikoa
- MAIL_PASSWORD - pasahitza elektronikoa
Azken biak aukerakoak dira. Emaitzak postaz bidaltzeko erabiliko dira. Txostena beste modu batean banatu nahi baduzu, ez duzu adierazi beharrik.
Beraz, behar ditugun ingurune-aldagaiak gehitu ditugu:
Orain sortu dezagun fitxategi bat .travis.yml eta kokatu proiektuaren erroan. PPSSPP-k Travis CIrako konfigurazio-fitxategi bat zeukan jada, hala ere, handiegia zen eta guztiz desegokia zen adibiderako, beraz, asko sinplifikatu behar izan genuen eta oinarrizko elementuak soilik utzi.
Lehenik eta behin, adierazi ditzagun hizkuntza, makina birtualean erabili nahi dugun Ubuntu Linux-en bertsioa eta eraikuntzarako beharrezko paketeak:
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'
Zerrendatutako pakete guztiak PPSSPPrako soilik behar dira.
Orain muntaia-matrizea adieraziko dugu:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Atalari buruz pixka bat gehiago matrizea. Travis CI-n, bi modu daude eraikitze-aukerak sortzeko: lehena konpiladoreen, sistema eragileen moten, ingurune-aldagaien eta abarren zerrenda zehaztea da, eta ondoren konbinazio posible guztien matrizea sortzen da; bigarrena matrizearen adierazle esplizitua da. Jakina, bi ikuspegi hauek konbina ditzakezu eta kasu bakarra gehitu edo, aitzitik, baztertu atala erabiliz. baztertzeko. Honi buruz gehiago irakur dezakezu
Proiektuaren berariazko muntaketa argibideak ematea besterik ez da geratzen:
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-k zure komandoak gehi ditzakezu makina birtual baten bizitzako hainbat fasetarako. atala aurretik_instalatu paketeak instalatu aurretik exekutatu. Gero instalatzeko, zerrendako paketeen instalazioari jarraitzen diona gehigarriak.aptgoian adierazi duguna. Batzarra bera bertan egiten da script. Dena ondo joan bada, orduan aurkituko gara arrakasta_ondoren (atal honetan analisi estatikoa egingo dugu). Hauek ez dira alda daitezkeen urrats guztiak, gehiago behar baduzu, begiratu beharko zenuke
Irakurtzeko erraztasuna lortzeko, komandoak gidoi berezi batean jarri ziren .travis.sh, proiektuaren erroan kokatzen dena.
Beraz, honako fitxategia dugu .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
Paketeak instalatu aurretik, azpimoduluak eguneratuko ditugu. PPSSPP eraikitzeko beharrezkoa da. Gehitu dezagun lehenengo funtzioa .travis.sh (kontuan izan luzapena):
travis_before_install() {
git submodule update --init --recursive
}
Orain Travis CI-n PVS-Studio abiarazte automatikoa konfiguratzera gatoz. Lehenik eta behin PVS-Studio paketea instalatu behar dugu sisteman:
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
}
Funtzioaren hasieran travis_install behar ditugun konpilatzaileak ingurune-aldagaiak erabiliz instalatzen ditugu. Orduan aldagaia bada $PVS_ANALYZE balioa gordetzen du Bai (atalean adierazi dugu env eraikitze matrizearen konfigurazioan), paketea instalatzen dugu pvs-estudioa. Honetaz gain, paketeak ere adierazten dira libio-socket-ssl-perl ΠΈ libnet-ssleay-perl, hala ere, emaitzak postaz bidaltzeko beharrezkoak dira, beraz, ez dira beharrezkoak zure txostena bidaltzeko beste metodo bat aukeratu baduzu.
Funtzioa deskargatu_atera zehaztutako artxiboa deskargatu eta deskargatzen du:
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
Proiektua osatzeko garaia da. Hau atalean gertatzen da 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
}
Izan ere, jatorrizko konfigurazio sinplifikatu bat da, lerro hauek izan ezik:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
ezarri dugun kodearen atal honetan cmake konpilazio komandoak esportatzeko bandera. Hau beharrezkoa da kode-analisi estatiko baterako. Honi buruz gehiago irakur dezakezu artikuluan "
Batzarrak arrakasta izan badu, lortuko dugu arrakasta_ondoren, non analisi estatikoa egiten dugu:
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
}
Ikus ditzagun ondoko lerro hauek:
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
Lehenengo lerroak Travis CI ingurune-aldagaiak konfiguratzean hasieran zehaztu genuen erabiltzaile-izenaren eta gakoaren lizentzia-fitxategi bat sortzen du.
Bigarren lerroak zuzenean hasten du analisia. Bandera -j analisirako hari kopurua ezartzen du, bandera -l lizentzia adierazten du, bandera -o erregistroak ateratzeko fitxategia eta bandera definitzen ditu -disableLicenseExpirationCheck probako bertsioetarako beharrezkoa da, lehenespenez geroztik pvs-estudio-analizatzailea lizentzia iraungitzear dagoela ohartaraziko dio erabiltzaileari. Hori gerta ez dadin, bandera hau zehaztu dezakezu.
Erregistro fitxategiak bihurketarik gabe irakurri ezin den irteera gordina dauka, beraz, lehenik fitxategia irakurgarri egin behar duzu. Pasa ditzagun erregistroak plog-bihurgailua, eta irteera html fitxategi bat da.
Adibide honetan, txostenak postaz bidaltzea erabaki nuen komandoa erabiliz bidali posta elektronikoa.
Ondorioz, hurrengo fitxategia lortu dugu .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;
Orain git biltegian aldaketak bultzatzeko garaia da, eta ondoren Travis CI-k automatikoki exekutatu egingo du eraikuntza. Egin klik "ppsspp"-en eraikuntza-txostenetara joateko:
Gaur egungo eraikuntzaren ikuspegi orokorra ikusiko dugu:
Eraikuntza behar bezala amaitzen bada, mezu elektroniko bat jasoko dugu analisi estatikoaren emaitzekin. Jakina, posta bidaltzea ez da txosten bat jasotzeko modu bakarra. Edozein ezarpen-metodo aukeratu dezakezu. Baina garrantzitsua da gogoratzea eraikuntza amaitu ondoren ezin izango dela makina birtualeko fitxategietara sartu.
Errorearen laburpena
Zailena arrakastaz bete dugu. Orain ziurtatu dezagun gure ahalegin guztiak merezi duela. Azter ditzagun postaz heldu zaidan analisi estatikoko txostenetik puntu interesgarri batzuk (ez zen alferrik adierazi nuena).
Optimizazio arriskutsua
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-Studioko abisua:
Kode zati hau hashing modulu seguruan dago, baina segurtasun akats larri bat dauka (
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Dena dago ordena eta funtzioa memeset exekutatzen da, eta horrela RAM datu garrantzitsuak gainidatziz, hala ere, ez poztu oraindik. Ikus dezagun Oharra bertsioaren muntaia-zerrenda optimizazioarekin:
; 354 :
; 355 : memset( sum, 0, sizeof( sum ) );
; 356 :}
Zerrendatik ikus daitekeenez, konpilatzaileak deiari ez zion jaramonik egin memeset. Funtzioan dagoelako da hori sha1 deialdiaren ostean memeset egiturari erreferentzia gehiagorik ez ctx. Horregatik, konpilatzaileak ez du zentzurik ikusten etorkizunean erabiltzen ez den memoria gainidatziz prozesadorearen denbora galtzea. Hau konpondu dezakezu funtzioa erabiliz RtlSecureZeroMemory edo
zuzentzeko:
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 ) );
}
Alferrikako konparaketa
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-Studioko abisua:
Erreparatu beste adarrari lehenengoari if. Baldintza guztiak baldin badira bakarrik exekutatuko da kodea leftvol > 0xFFFF || rightvol > 0xFFFF || ezkervol < 0 || eskuineko bola < 0 faltsua izango da. Beraz, baieztapen hauek lortuko ditugu, beste adarrentzat egia izango direnak: ezkerreko vol <= 0xFFFF, eskuineko vol <= 0xFFFF, ezkerreko bola >= 0 ΠΈ eskuineko bol >= 0. Kontuan izan azken bi adierazpenak. Zentzurik al du kode zati hau exekutatzeko beharrezko baldintza zein den egiaztatzeak?
Beraz, segurtasunez ken ditzakegu baldintzazko adierazpen hauek:
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);
}
}
Beste eszenatoki bat. Baldintza erredundante horien atzean errore motaren bat ezkutatzen da. Beharbada ez zuten egiaztatu zer eskatzen zen.
Ctrl+C Ctrl+V-k atzera jotzen du
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfData) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Erreparatu barruko txekeari if. Ez al zaizu arraroa iruditzen helbideak balio duen egiaztatzea? psmfData, bi aldiz gehiago? Beraz, hau arraroa iruditzen zait... Izan ere, hau, noski, akatsa da, eta ideia sarrerako bi parametroak egiaztatzea zen.
Aukera zuzena:
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfStruct) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Ahaztutako aldagaia
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-Studioko abisua:
Errore hau karpetan dago ext, beraz, ez da proiekturako oso garrantzitsua, baina akatsa konturatu baino lehen aurkitu zen, beraz, uztea erabaki nuen. Azken finean, artikulu hau ez da akatsak berrikustea, Travis CI-rekin integratzeari buruzkoa baizik, eta ez zen analizatzailearen konfiguraziorik egin.
Aldakorra tamaina konstante baten bidez hasieratzen da, hala ere, ez da batere erabiltzen kodean, operadoreari arte if, eta horrek, noski, ematen du false baldintzak egiaztatzen diren bitartean, zeren, gogoratzen dugunez, tamaina zeroren berdina. Ondorengo kontrolek ere ez dute zentzurik.
Dirudienez, kode zatiaren egileari aldagaia gainidaztea ahaztu zaio tamaina horren aurretik.
Gelditu
Hemen amaituko dugu ziurrenik akatsekin. Artikulu honen helburua PVS-Studio-k Travis CIrekin batera egindako lana erakustea da, eta ez proiektua ahalik eta ondoen aztertzea. Akats handiagoak eta ederragoak nahi badituzu, beti miretsi ditzakezu
Ondorioa
Web-zerbitzuak erabiltzeak proiektuak eraikitzeko analisi inkrementalaren praktikarekin batera, kodea batu eta berehala arazo asko aurki ditzakezu. Hala ere, baliteke eraikuntza bat nahikoa ez izatea, beraz, azterketa estatikoarekin batera probak konfiguratzeak kodearen kalitatea nabarmen hobetuko du.
Esteka interesgarriak
Artikulu hau ingelesez hitz egiten duen publiko batekin partekatu nahi baduzu, mesedez erabili itzulpen-esteka: Maxim Zvyagintsev.
Iturria: www.habr.com