ProHoster > Blog > Pangangasiwa > Paano i-configure ang PVS-Studio sa Travis CI gamit ang halimbawa ng isang PSP game console emulator
Paano i-configure ang PVS-Studio sa Travis CI gamit ang halimbawa ng isang PSP game console emulator
Ang Travis CI ay isang distributed web service para sa pagbuo at pagsubok ng software na gumagamit ng GitHub bilang source code hosting. Bilang karagdagan sa mga sitwasyon sa pagpapatakbo sa itaas, maaari kang magdagdag ng iyong sariling salamat sa malawak na mga opsyon sa pagsasaayos. Sa artikulong ito, iko-configure namin ang Travis CI upang gumana sa PVS-Studio gamit ang halimbawa ng PPSSPP code.
Pagpapakilala
Travis CI ay isang serbisyo sa web para sa pagbuo at pagsubok ng software. Karaniwan itong ginagamit kasabay ng tuluy-tuloy na mga kasanayan sa pagsasama.
PPSSPP - PSP game console emulator. Nagagawa ng programa na tularan ang paglulunsad ng anumang mga laro mula sa mga imahe ng disk na inilaan para sa Sony PSP. Ang programa ay inilabas noong Nobyembre 1, 2012. Ang PPSSPP ay lisensyado sa ilalim ng GPL v2. Kahit sino ay maaaring gumawa ng mga pagpapabuti sa source code ng proyekto.
PVS-Studio β isang static na code analyzer para sa paghahanap ng mga error at potensyal na kahinaan sa program code. Sa artikulong ito, para sa pagbabago, ilulunsad namin ang PVS-Studio hindi lokal sa makina ng developer, ngunit sa cloud, at hahanapin ang mga error sa PPSSPP.
Pag-set up ng Travis CI
Kakailanganin namin ang isang repository sa GitHub, kung saan matatagpuan ang proyektong kailangan namin, pati na rin ang isang susi para sa PVS-Studio (maaari kang makakuha ng susi ng pagsubok o libre para sa mga proyekto ng Open Source).
Pumunta tayo sa site Travis CI. Pagkatapos ng pahintulot gamit ang iyong GitHub account, makakakita kami ng listahan ng mga repositoryo:
Para sa pagsubok, nag-forked ako ng PPSSPP.
Ina-activate namin ang repositoryo na gusto naming kolektahin:
Sa ngayon, hindi mabuo ng Travis CI ang aming proyekto dahil walang mga tagubilin para sa pagtatayo. Kaya oras na para sa pagsasaayos.
Sa panahon ng pagsusuri, ang ilang mga variable ay magiging kapaki-pakinabang sa amin, halimbawa, ang susi para sa PVS-Studio, na hindi kanais-nais na tukuyin sa configuration file. Kaya't magdagdag tayo ng mga variable ng kapaligiran gamit ang mga setting ng build sa Travis CI:
Kailangan namin:
PVS_USERNAME - username
PVS_KEY - susi
MAIL_USER - email na gagamitin para ipadala ang ulat
MAIL_PASSWORD - password ng email
Ang huling dalawa ay opsyonal. Gagamitin ang mga ito upang magpadala ng mga resulta sa pamamagitan ng koreo. Kung gusto mong ipamahagi ang ulat sa ibang paraan, hindi mo kailangang ipahiwatig ang mga ito.
Kaya, idinagdag namin ang mga variable ng kapaligiran na kailangan namin:
Ngayon gumawa tayo ng file .travis.yml at ilagay ito sa ugat ng proyekto. Ang PPSSPP ay mayroon nang configuration file para sa Travis CI, gayunpaman, ito ay masyadong malaki at ganap na hindi angkop para sa halimbawa, kaya kailangan namin itong gawing simple at iwanan lamang ang mga pangunahing elemento.
Una, ipahiwatig natin ang wika, ang bersyon ng Ubuntu Linux na gusto nating gamitin sa virtual machine, at ang mga kinakailangang pakete para sa build:
Ang lahat ng mga pakete na nakalista ay kailangan ng eksklusibo para sa PPSSPP.
Ngayon ipinapahiwatig namin ang assembly matrix:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Kaunti pa tungkol sa seksyon matris. Sa Travis CI, mayroong dalawang paraan upang lumikha ng mga pagpipilian sa pagbuo: ang una ay upang tukuyin ang isang listahan ng mga compiler, mga uri ng operating system, mga variable ng kapaligiran, atbp., pagkatapos nito ay nabuo ang isang matrix ng lahat ng posibleng kumbinasyon; ang pangalawa ay isang tahasang indikasyon ng matrix. Siyempre, maaari mong pagsamahin ang dalawang diskarte na ito at magdagdag ng isang natatanging kaso, o, sa kabaligtaran, ibukod ito gamit ang seksyon huwag isama. Maaari mong basahin ang higit pa tungkol dito sa Travis CI dokumentasyon.
Ang natitira na lang ay magbigay ng mga tagubilin sa pagpupulong na partikular sa proyekto:
Pinapayagan ka ng Travis CI na magdagdag ng sarili mong mga command para sa iba't ibang yugto ng buhay ng isang virtual machine. Seksyon before_install naisakatuparan bago mag-install ng mga pakete. Pagkatapos install, na sumusunod sa pag-install ng mga pakete mula sa listahan addons.aptna ipinahiwatig namin sa itaas. Ang pagpupulong mismo ay nagaganap sa script. Kung naging maayos ang lahat, makikita natin ang ating sarili pagkatapos_tagumpay (nasa seksyong ito na tatakbo kami ng static na pagsusuri). Ito ay hindi lahat ng mga hakbang na maaaring baguhin, kung kailangan mo ng higit pa, pagkatapos ay dapat mong tingnan Travis CI dokumentasyon.
Para sa kadalian ng pagbabasa, ang mga utos ay inilagay sa isang hiwalay na script .travis.sh, na inilalagay sa ugat ng proyekto.
Kaya mayroon kaming sumusunod na file .travis.yml:
Bago i-install ang mga pakete, ia-update namin ang mga submodules. Ito ay kinakailangan upang bumuo ng PPSSPP. Idagdag natin ang unang function sa .travis.sh (tandaan ang extension):
Ngayon ay direktang pumunta kami sa pag-set up ng awtomatikong paglulunsad ng PVS-Studio sa Travis CI. Una kailangan nating i-install ang PVS-Studio package sa system:
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
}
Sa simula ng function travis_install ini-install namin ang mga compiler na kailangan namin gamit ang mga variable ng kapaligiran. Pagkatapos kung ang variable $PVS_ANALYZE halaga ng mga tindahan Oo (ipinahiwatig namin ito sa seksyon env sa panahon ng pagsasaayos ng build matrix), ini-install namin ang package pvs-studio. Bilang karagdagan dito, ang mga pakete ay ipinahiwatig din libio-socket-ssl-perl ΠΈ libnet-ssleay-perl, gayunpaman, kinakailangan ang mga ito para sa mga resulta sa pagpapadala ng koreo, kaya hindi kinakailangan ang mga ito kung pumili ka ng ibang paraan para sa paghahatid ng iyong ulat.
Tungkulin download_extract i-download at i-unpack ang tinukoy na archive:
Oras na para pagsama-samahin ang proyekto. Nangyayari ito sa seksyon 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
}
Sa katunayan, ito ay isang pinasimple na orihinal na pagsasaayos, maliban sa mga linyang ito:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
Sa seksyong ito ng code na itinakda namin cmake flag para sa pag-export ng mga compilation command. Ito ay kinakailangan para sa isang static code analyzer. Maaari mong basahin ang higit pa tungkol dito sa artikulong "Paano patakbuhin ang PVS-Studio sa Linux at macOS".
Kung ang pagpupulong ay matagumpay, pagkatapos ay makarating tayo pagkatapos_tagumpay, kung saan nagsasagawa kami ng static na pagsusuri:
Ang unang linya ay bumubuo ng isang file ng lisensya mula sa username at key na tinukoy namin sa pinakadulo simula noong nagse-set up ng mga variable ng kapaligiran ng Travis CI.
Ang pangalawang linya ay direktang nagsisimula sa pagsusuri. Bandila -j nagtatakda ng bilang ng mga thread para sa pagsusuri, i-flag -l ay nagpapahiwatig ng lisensya, bandila -o tumutukoy sa file para sa pag-output ng mga log, at ang bandila -disableLicenseExpirationCheck kinakailangan para sa mga trial na bersyon, dahil bilang default pvs-studio-analyzer babalaan ang user na malapit nang mag-expire ang lisensya. Upang maiwasang mangyari ito, maaari mong tukuyin ang flag na ito.
Ang log file ay naglalaman ng raw na output na hindi mababasa nang walang conversion, kaya dapat mo munang gawing nababasa ang file. Ipasa natin ang mga log pang-log-converter, at ang output ay isang html file.
Sa halimbawang ito, nagpasya akong magpadala ng mga ulat sa pamamagitan ng koreo gamit ang command sendemail.
Bilang resulta, nakuha namin ang sumusunod na file .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;
Ngayon ay oras na upang itulak ang mga pagbabago sa git repository, pagkatapos nito ay awtomatikong tatakbo ng Travis CI ang build. Mag-click sa βppssppβ para pumunta sa mga build report:
Makakakita tayo ng pangkalahatang-ideya ng kasalukuyang build:
Kung matagumpay na nakumpleto ang pagbuo, makakatanggap kami ng email na may mga resulta ng static na pagsusuri. Siyempre, ang pagpapadala sa koreo ay hindi lamang ang paraan upang makatanggap ng ulat. Maaari kang pumili ng anumang paraan ng pagpapatupad. Ngunit mahalagang tandaan na pagkatapos makumpleto ang pagbuo, hindi magiging posible na ma-access ang mga file ng virtual machine.
Buod ng error
Matagumpay naming natapos ang pinakamahirap na bahagi. Ngayon, siguraduhin natin na ang lahat ng ating pagsisikap ay katumbas ng halaga. Tingnan natin ang ilang mga kagiliw-giliw na punto mula sa ulat ng static na pagsusuri na dumating sa akin sa pamamagitan ng koreo (hindi para sa wala na ipinahiwatig ko ito).
Babala sa PVS-Studio: V597 Maaaring tanggalin ng compiler ang 'memset' function call, na ginagamit upang i-flush ang 'sum' buffer. Ang RtlSecureZeroMemory() function ay dapat gamitin upang burahin ang pribadong data. sha1.cpp 325
Ang piraso ng code na ito ay matatagpuan sa secure na hashing na module, gayunpaman, naglalaman ito ng isang seryosong depekto sa seguridad (CWE-14). Tingnan natin ang listahan ng pagpupulong na nabuo kapag kino-compile ang bersyon ng Debug:
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Ang lahat ay nasa ayos at ang pag-andar memeset ay naisakatuparan, at sa gayon ay na-overwrite ang mahalagang data sa RAM, gayunpaman, huwag kang magalak pa. Tingnan natin ang listahan ng pagpupulong ng bersyon ng Paglabas na may pag-optimize:
Tulad ng makikita mula sa listahan, hindi pinansin ng compiler ang tawag memeset. Ito ay dahil sa ang katunayan na sa function sha1 pagkatapos ng tawag memeset wala nang reference sa structure CTx. Samakatuwid, ang compiler ay walang nakikitang punto sa pag-aaksaya ng oras ng processor sa pag-overwrit ng memorya na hindi gagamitin sa hinaharap. Maaari mong ayusin ito sa pamamagitan ng paggamit ng function RtlSecureZeroMemory o katulad sa kanya.
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);
}
}
Babala sa PVS-Studio: V547 Palaging totoo ang expression na 'leftvol >= 0'. sceAudio.cpp 120
Bigyang-pansin ang ibang sangay para sa una if. Ang code ay isasagawa lamang kung ang lahat ng mga kondisyon leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0 lalabas na hindi totoo. Samakatuwid, nakukuha namin ang mga sumusunod na pahayag, na magiging totoo para sa ibang sangay: leftvol <= 0xFFFF, rightvol <= 0xFFFF, leftvol >= 0 ΠΈ rightvol >= 0. Pansinin ang huling dalawang pahayag. Makatuwiran bang suriin kung ano ang kinakailangang kondisyon para sa pagpapatupad ng piraso ng code na ito?
Para ligtas nating maalis ang mga kondisyonal na pahayag na ito:
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);
}
}
Isa pang senaryo. Mayroong ilang uri ng error na nakatago sa likod ng mga kalabisan na kundisyon na ito. Marahil ay hindi nila nasuri kung ano ang kinakailangan.
V501 Mayroong magkaparehong mga sub-expression na '!Memory::IsValidAddress(psmfData)' sa kaliwa at sa kanan ng '||' operator. scePsmf.cpp 703
Bigyang-pansin ang tseke sa loob if. Hindi mo ba naisip na kakaiba na tingnan natin kung valid ang address? psmfData, doble ang dami? Kaya ito ay tila kakaiba sa akin... Sa katunayan, ito ay, siyempre, isang typo, at ang ideya ay suriin ang parehong mga parameter ng input.
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");
}
....
}
Babala sa PVS-Studio: V547 Ang expression na 'size == 8' ay palaging mali. syn-att.c 195
Ang error na ito ay matatagpuan sa folder ext, kaya hindi talaga nauugnay sa proyekto, ngunit natagpuan ang bug bago ko ito napansin, kaya nagpasya akong iwanan ito. Pagkatapos ng lahat, ang artikulong ito ay hindi tungkol sa pagsusuri ng mga error, ngunit tungkol sa pagsasama sa Travis CI, at walang pagsasaayos ng analyzer ang isinagawa.
Variable laki ay pinasimulan ng isang pare-pareho, gayunpaman, hindi ito ginagamit sa lahat sa code, hanggang sa operator if, na, siyempre, ay nagbibigay hindi totoo habang sinusuri ang mga kondisyon, dahil, tulad ng naaalala natin, laki katumbas ng zero. Walang saysay din ang mga kasunod na pagsusuri.
Tila, nakalimutan ng may-akda ng fragment ng code na i-overwrite ang variable laki bago iyon.
Itigil
Dito na siguro tayo magtatapos sa mga pagkakamali. Ang layunin ng artikulong ito ay upang ipakita ang gawain ng PVS-Studio kasama ng Travis CI, at hindi upang suriin ang proyekto nang lubusan hangga't maaari. Kung gusto mo ng mas malaki at mas magagandang pagkakamali, maaari mong laging humanga sa kanila dito :).
Konklusyon
Ang paggamit ng mga serbisyo sa web upang bumuo ng mga proyekto kasama ang pagsasagawa ng incremental analysis ay nagbibigay-daan sa iyong makahanap ng maraming problema kaagad pagkatapos ng pagsasama ng code. Gayunpaman, maaaring hindi sapat ang isang build, kaya ang pagse-set up ng pagsubok kasama ng static na pagsusuri ay makabuluhang magpapahusay sa kalidad ng code.