Travis CI як хидмати тақсимшудаи веб барои сохтан ва озмоиши нармафзор аст, ки GitHub-ро ҳамчун хостинги коди сарчашма истифода мебарад. Илова ба сенарияҳои амалиётии дар боло зикршуда, шумо метавонед ба шарофати имконоти васеи конфигуратсияи худ илова кунед. Дар ин мақола мо Travis CI-ро барои кор бо PVS-Studio бо истифода аз мисоли рамзи PPSSPP танзим мекунем.
Муқаддима
Насб кардани Travis CI
Ба мо анбори GitHub лозим аст, ки дар он лоиҳаи ба мо лозима ҷойгиршуда ва инчунин калиди PVS-Studio (шумо метавонед дастрас кунед)
Биёед ба сайт равем
Барои санҷиш, ман PPSSPP-ро бурдам.
Мо анбореро, ки ҷамъ кардан мехоҳем, фаъол мекунем:
Дар айни замон, Travis CI наметавонад лоиҳаи моро созад, зеро дастур оид ба сохтмон вуҷуд надорад. Пас вақти конфигуратсия расидааст.
Ҳангоми таҳлил баъзе тағирёбандаҳо барои мо муфид хоҳанд буд, масалан, калиди PVS-Studio, ки дар файли конфигуратсия нишон додани он номатлуб аст. Пас, биёед тағирёбандаҳои муҳити зистро бо истифода аз танзимоти сохтмон дар Travis CI илова кунем:
Мо бояд ба:
- PVS_USERNAME - номи корбар
- PVS_KEY - калид
- MAIL_USER - почтаи электронӣ, ки барои фиристодани гузориш истифода мешавад
- MAIL_PASSWORD - пароли почтаи электронӣ
Ду охирин ихтиёрӣ мебошанд. Инҳо барои фиристодани натиҷаҳо тавассути почта истифода мешаванд. Агар шумо хоҳед, ки гузоришро бо роҳи дигар паҳн кунед, ба шумо лозим нест, ки онҳоро нишон диҳед.
Ҳамин тавр, мо тағирёбандаҳои муҳити атрофро илова кардем, ки ба мо лозим аст:
Акнун биёед файл эҷод кунем .travis.yml ва онро дар решаи лоиҳа ҷойгир кунед. PPSSPP аллакай файли конфигуратсияи Travis CI дошт, аммо он хеле калон буд ва барои мисол комилан номувофиқ буд, аз ин рӯ мо маҷбур шудем, ки онро хеле содда кунем ва танҳо унсурҳои асосиро гузорем.
Аввалан, биёед забон, версияи Ubuntu Linux-ро, ки мо мехоҳем дар мошини виртуалӣ истифода барем ва бастаҳои заруриро барои сохтмон нишон диҳем:
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'
Ҳама бастаҳои номбаршуда танҳо барои PPSSPP лозиманд.
Акнун мо матритсаи монтажро нишон медиҳем:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Каме бештар дар бораи бахш Матраса. Дар Travis CI ду роҳи эҷоди вариантҳои сохтмон вуҷуд дорад: якум ин муайян кардани рӯйхати компиляторҳо, намудҳои системаи амалиётӣ, тағирёбандаҳои муҳити зист ва ғайра мебошад, ки баъд аз он матритсаи ҳамаи комбинатсияҳои имконпазир тавлид мешавад; дуюм нишондоди равшани матрица мебошад. Албатта, шумо метавонед ин ду равишро муттаҳид кунед ва як парвандаи беназир илова кунед ё, баръакс, онро бо истифода аз қисм хориҷ кунед истисно. Шумо метавонед дар ин бора бештар хонед
Ҳама чизи боқимонда ин аст, ки дастурҳои васлкунии лоиҳаро пешниҳод кунанд:
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 ба шумо имкон медиҳад, ки фармонҳои шахсии худро барои марҳилаҳои гуногуни ҳаёти мошини виртуалӣ илова кунед. Ҷудокунӣ пеш аз_насб кардан пеш аз насб кардани бастаҳо иҷро карда мешавад. Баъд насб кунед, ки пас аз насби бастаҳо аз рӯйхат addons.aptки мо дар боло нишон додем. Худи маҷлис дар барномаи саҳнавӣ. Агар ҳама чиз хуб бошад, пас мо худро дар он меёбем баъди_муваффакият (дар ин бахш мо таҳлили статикиро иҷро хоҳем кард). Инҳо на ҳама қадамҳое мебошанд, ки онҳоро тағир додан мумкин аст, агар ба шумо бештар лозим бошад, шумо бояд ба он нигаред
Барои осонии хондан, фармонҳо дар скрипти алоҳида ҷойгир карда шуданд .travis.sh, ки дар решаи лоиҳа ҷойгир шудааст.
Ҳамин тавр, мо файли зеринро дорем .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
Пеш аз насб кардани бастаҳо, мо зермодулҳоро навсозӣ мекунем. Ин барои сохтани PPSSPP лозим аст. Биёед функсияи якумро ба .travis.sh (ба тавсеа диққат диҳед):
travis_before_install() {
git submodule update --init --recursive
}
Ҳоло мо бевосита ба танзими ифтитоҳи автоматии PVS-Studio дар Travis CI меоем. Аввалан мо бояд бастаи 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
}
Дар оғози функсия travis_install мо компиляторҳоеро, ки ба мо лозим аст, бо истифода аз тағирёбандаҳои муҳити зист насб мекунем. Пас, агар тағирёбанда $PVS_ANALYZE арзишро нигоҳ медорад ҳа (мо онро дар фасл нишон додем ҳас ҳангоми конфигуратсияи матритсаи сохтани), мо бастаро насб мекунем pvs-studio. Илова бар ин, бастаҳо низ нишон дода шудаанд libio-socket-ssl-perl и libnet-ssleay-perl, аммо онҳо барои фиристодани натиҷаҳо талаб карда мешаванд, бинобар ин, агар шумо усули дигари пешниҳоди гузориши худро интихоб карда бошед, онҳо лозим нестанд.
функсия зеркашӣ_экстракт Архиви муайяншударо зеркашӣ ва мекушояд:
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
Вақти он расидааст, ки лоиҳаро якҷоя созем. Ин дар бахш рӯй медиҳад барномаи саҳнавӣ:
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
}
Дар асл, ин конфигуратсияи аслӣ соддакардашуда аст, ба истиснои ин сатрҳо:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
Дар ин фасли код мо барои он муқаррар кардаем смаке парчам барои содироти фармонҳои компиляция. Ин барои таҳлилгари рамзи статикӣ зарур аст. Шумо метавонед бештар дар ин бора дар мақолаи "
Агар анҷуман бомуваффақият анҷом дода шавад, мо ба он мерасем баъди_муваффакият, ки мо таҳлили статикиро анҷом медиҳем:
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
}
Биёед ба сатрҳои зерин наздиктар назар андозем:
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
Сатри аввал аз номи корбар ва калид файли литсензияеро тавлид мекунад, ки мо дар ибтидо ҳангоми танзими тағирёбандаҳои муҳити Travis CI муайян кардем.
Сатри дуюм бевосита таҳлилро оғоз мекунад. Парчам -j шумораи риштаҳоро барои таҳлил муқаррар мекунад, байрақ -л иҷозатнома, байрақро нишон медиҳад -о файлро барои баровардани гузоришҳо ва парчамро муайян мекунад - disableLicenseExpirationCheck барои версияҳои озмоишӣ талаб карда мешавад, зеро бо нобаёнӣ pvs-studio-analyzer истифодабарандаро огоҳ мекунад, ки мӯҳлати иҷозатнома ба охир мерасад. Барои пешгирии ин ҳодиса, шумо метавонед ин парчамро муайян кунед.
Дар файли журнал баромади хом мавҷуд аст, ки онро бе табдил хондан ғайриимкон аст, бинобар ин шумо бояд аввал файлро қобили хондан гардонед. Биёед журналҳоро гузаронем табдилдиҳандаи plog, ва баромад файли html аст.
Дар ин мисол, ман қарор додам, ки бо истифода аз фармон гузоришҳоро тавассути почта фиристам почтаи электронӣ фиристед.
Дар натиҷа мо файли зеринро гирифтем .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;
Ҳоло вақти он расидааст, ки тағиротҳоро ба анбори git пахш кунед, пас аз он Travis CI сохтмонро ба таври худкор иҷро мекунад. Барои гузаштан ба гузоришҳои сохтмонӣ "ppsspp" -ро клик кунед:
Мо шарҳи сохтори кунуниро мебинем:
Агар сохтмон бомуваффақият анҷом ёбад, мо паёми электронӣ бо натиҷаҳои таҳлили статикӣ мегирем. Албатта, почта ягона роҳи гирифтани ҳисобот нест. Шумо метавонед ягон усули татбиқро интихоб кунед. Аммо дар хотир доштан муҳим аст, ки пас аз ба итмом расидани сохтмон, дастрасӣ ба файлҳои мошини виртуалӣ ғайриимкон хоҳад буд.
Хулосаи хато
Мо кори душвортаринро бомуваффакият анчом додем. Акнун биёед боварй хосил кунем, ки тамоми чидду чахдамон арзанда аст. Биёед баъзе нуктаҳои ҷолибро аз гузориши таҳлили статикӣ, ки тавассути почта ба ман омадаанд, бубинем (беҳуда ман инро нишон додам).
Оптимизатсияи хатарнок
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:
Ин порчаи код дар модули ҳашингии бехатар ҷойгир аст, аммо он дорои як камбудии ҷиддии амният аст (
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Ҳама чиз дар тартиб ва функсия аст хотира иҷро карда мешавад ва ба ин васила маълумоти муҳимро дар хотираи оперативӣ сабт мекунад, аммо ҳоло хурсанд нашавед. Биёед ба рӯйхати маҷлиси версияи Release бо оптимизатсия назар кунем:
; 354 :
; 355 : memset( sum, 0, sizeof( sum ) );
; 356 :}
Чунон ки аз листинг дида мешавад, компилятор зангро нодида гирифт хотира. Ин аз он сабаб аст, ки дар функсия ШАХНУН пас аз занг хотира дигар ба сохтор ишорае нест ctx. Аз ин рӯ, компилятор барои беҳуда сарф кардани вақти протсессор барои баргардонидани хотирае, ки дар оянда истифода намешавад, ҳеҷ маъно надорад. Шумо метавонед инро бо истифода аз функсия ислоҳ кунед RtlSecureZeroMemory ё
Дуруст аст:
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 ) );
}
Муқоисаи нолозим
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:
Барои аввал ба филиали дигар диққат диҳед if. Рамз танҳо дар сурати мавҷуд будани ҳама шартҳо иҷро мешавад leftvol > 0xFFFF || rightvol > 0xFFFF || чапи < 0 || Ҳаҷми рост < 0 дурӯғ мебарояд. Аз ин рӯ, мо изҳороти зеринро мегирем, ки барои филиали дигар дуруст хоҳанд буд: чапи чап <= 0xFFFF, ҳақиқӣ <= 0xFFFF, чапи чап >= 0 и Ҳаҷми рост >= 0. Ба ду изҳороти охир диққат диҳед. Оё дуруст аст, ки тафтиш кардани шарти зарурии иҷрои ин порчаи код чист?
Ҳамин тавр, мо метавонем ин изҳороти шартиро бехатар хориҷ кунем:
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);
}
}
Сенарияи дигар. Дар паси ин шароити зиёдатӣ як навъ хатогӣ пинҳон аст. Шояд онҳо чизеро, ки лозим буд, тафтиш накардаанд.
Ctrl+C Ctrl+V баргашт
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfData) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Ба чеки дохили он диққат диҳед if. Ба фикри шумо аҷиб нест, ки мо дуруст будани адресро тафтиш мекунем? psmfData, ду баробар зиёд? Пас, ин ба ман аҷиб менамояд... Дарвоқеъ, ин, албатта, хатои хаттӣ аст ва андешаи он буд, ки ҳарду параметри вурудро тафтиш кунем.
Варианти дуруст:
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfStruct) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Тағйирёбандаи фаромӯшшуда
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:
Ин хато дар ҷузвдон ҷойгир аст Садо Ояндасоз, бинобар ин воқеан ба лоиҳа мувофиқ нест, аммо хато пеш аз он ки ман онро пайхас кардам, пайдо шуд, бинобар ин ман қарор додам, ки онро тарк кунам. Дар ниҳоят, ин мақола на дар бораи баррасии хатогиҳо, балки дар бораи ҳамгироӣ бо Travis CI аст ва ҳеҷ конфигуратсияи анализатор гузаронида нашудааст.
Тағйирёбанда андоза бо як доимӣ оғоз карда мешавад, аммо он дар код умуман то оператор истифода намешавад if, ки албатта, медихад бардурӯғ хангоми тафтиши шароит, зеро чунон ки мо дар хотир дорем, андоза ба сифр баробар аст. Санҷишҳои минбаъда низ маъно надоранд.
Эҳтимол, муаллифи порчаи рамз навиштани тағирёбандаро фаромӯш кардааст андоза пеш аз он.
Ист
Ин аст, ки мо эҳтимол бо хатогиҳо хотима медиҳем. Мақсади ин мақола намоиш додани кори PVS-Studio дар якҷоягӣ бо Травис CI аст, на таҳлили лоиҳа то ҳадди имкон дақиқ. Агар шумо хоҳед, ки хатогиҳои калонтар ва зеботар бошед, шумо ҳамеша метавонед онҳоро ба ҳайрат оред
хулоса
Истифодаи хидматҳои веб барои сохтани лоиҳаҳо дар якҷоягӣ бо таҷрибаи таҳлили афзоянда ба шумо имкон медиҳад, ки мушкилоти зиёдеро фавран пас аз якҷоя кардани код пайдо кунед. Аммо, як сохтмон метавонад кофӣ набошад, аз ин рӯ насб кардани санҷиш дар якҷоягӣ бо таҳлили статикӣ сифати кодро ба таври назаррас беҳтар мекунад.
Пайвандҳои муфид
Агар шумо хоҳед, ки ин мақоларо бо шунавандагони англисзабон мубодила кунед, лутфан истиноди тарҷумаро истифода баред: Максим Звягинтсев.
Манбаъ: will.com