Mae Travis CI yn wasanaeth gwe dosbarthedig ar gyfer adeiladu a phrofi meddalwedd sy'n defnyddio GitHub fel gwesteiwr cod ffynhonnell. Yn ogystal â'r senarios gweithredu uchod, gallwch ychwanegu eich hun diolch i'r opsiynau cyfluniad helaeth. Yn yr erthygl hon byddwn yn ffurfweddu Travis CI i weithio gyda PVS-Studio gan ddefnyddio'r enghraifft cod PPSSPP.
Cyflwyniad
Sefydlu Travis CI
Bydd angen ystorfa arnom ar GitHub, lle mae'r prosiect sydd ei angen arnom wedi'i leoli, yn ogystal ag allwedd ar gyfer PVS-Studio (gallwch gael
Gadewch i ni fynd i'r safle
Ar gyfer y prawf, fforchais PPSSPP.
Rydym yn actifadu'r ystorfa yr ydym am ei chasglu:
Ar hyn o bryd, ni all Travis CI adeiladu ein prosiect oherwydd nad oes unrhyw gyfarwyddiadau adeiladu. Felly mae'n amser ar gyfer cyfluniad.
Yn ystod y dadansoddiad, bydd rhai newidynnau yn ddefnyddiol i ni, er enghraifft, yr allwedd ar gyfer PVS-Studio, na fyddai'n ddymunol ei nodi yn y ffeil ffurfweddu. Felly gadewch i ni ychwanegu newidynnau amgylchedd gan ddefnyddio'r gosodiadau adeiladu yn Travis CI:
Bydd angen:
- PVS_USERNAME - enw defnyddiwr
- PVS_KEY - allwedd
- MAIL_USER - e-bost a ddefnyddir i anfon yr adroddiad
- MAIL_PASSWORD - cyfrinair e-bost
Mae'r ddau olaf yn ddewisol. Bydd y rhain yn cael eu defnyddio i anfon canlyniadau drwy'r post. Os ydych am ddosbarthu'r adroddiad mewn ffordd arall, nid oes angen i chi eu nodi.
Felly, rydym wedi ychwanegu'r newidynnau amgylchedd sydd eu hangen arnom:
Nawr, gadewch i ni greu ffeil .travis.yml a'i osod yng ngwraidd y prosiect. Roedd gan PPSSPP ffeil ffurfweddu eisoes ar gyfer Travis CI, fodd bynnag, roedd yn rhy fawr ac yn gwbl anaddas ar gyfer yr enghraifft, felly bu'n rhaid i ni ei symleiddio'n fawr a gadael yr elfennau sylfaenol yn unig.
Yn gyntaf, gadewch i ni nodi'r iaith, y fersiwn o Ubuntu Linux yr ydym am ei ddefnyddio yn y peiriant rhithwir, a'r pecynnau angenrheidiol ar gyfer adeiladu:
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'
Mae angen yr holl becynnau a restrir ar gyfer PPSSPP yn unig.
Nawr rydyn ni'n nodi matrics y cynulliad:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Ychydig mwy am yr adran matrics. Yn Travis CI, mae dwy ffordd i greu opsiynau adeiladu: y cyntaf yw nodi rhestr o gasglwyr, mathau o systemau gweithredu, newidynnau amgylchedd, ac ati, ac ar ôl hynny cynhyrchir matrics o'r holl gyfuniadau posibl; mae'r ail yn arwydd clir o'r matrics. Wrth gwrs, gallwch gyfuno'r ddau ddull hyn ac ychwanegu achos unigryw, neu, i'r gwrthwyneb, ei eithrio gan ddefnyddio'r adran eithrio. Gallwch ddarllen mwy am hyn yn
Y cyfan sydd ar ôl yw darparu cyfarwyddiadau cydosod prosiect-benodol:
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
Mae Travis CI yn caniatáu ichi ychwanegu eich gorchmynion eich hun ar gyfer gwahanol gamau ym mywyd peiriant rhithwir. Adran cyn_osod gweithredu cyn gosod pecynnau. Yna gosod, sy'n dilyn gosod pecynnau o'r rhestr addons.apta nodwyd gennym uchod. Cymer y cynulliad ei hun le yn sgript. Pe bai popeth yn mynd yn iawn, yna rydyn ni'n cael ein hunain i mewn ôl_llwyddiant (yn yr adran hon y byddwn yn rhedeg dadansoddiad statig). Nid dyma'r holl gamau y gellir eu haddasu, os oes angen mwy arnoch, yna dylech edrych i mewn
Er hwylustod, gosodwyd y gorchmynion mewn sgript ar wahân .travis.sh, sy'n cael ei osod wrth wraidd y prosiect.
Felly mae gennym y ffeil ganlynol .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
Cyn gosod y pecynnau, byddwn yn diweddaru'r is-fodiwlau. Mae angen hyn i adeiladu PPSSPP. Gadewch i ni ychwanegu'r swyddogaeth gyntaf at .travis.sh (sylwch ar yr estyniad):
travis_before_install() {
git submodule update --init --recursive
}
Nawr rydym yn dod yn uniongyrchol at sefydlu lansiad awtomatig PVS-Studio yn Travis CI. Yn gyntaf mae angen i ni osod y pecyn PVS-Studio ar y 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
}
Ar ddechrau'r swyddogaeth travis_install rydym yn gosod y casglwyr sydd eu hangen arnom gan ddefnyddio newidynnau amgylchedd. Yna os yw'r newidyn $PVS_ANALYZE gwerth siopau Ydy (rydym wedi ei nodi yn yr adran env yn ystod cyfluniad matrics adeiladu), rydym yn gosod y pecyn pvs-stiwdio. Yn ogystal â hyn, nodir pecynnau hefyd libio-soced-ssl-perl и libnet-ssleay-perl, fodd bynnag, mae eu hangen ar gyfer postio canlyniadau, felly nid ydynt yn angenrheidiol os ydych wedi dewis dull arall ar gyfer cyflwyno eich adroddiad.
Swyddogaeth lawrlwytho_dyfyniad yn llwytho i lawr ac yn dadbacio'r archif penodedig:
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
Mae'n bryd rhoi'r prosiect at ei gilydd. Mae hyn yn digwydd yn yr adran sgript:
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
}
Mewn gwirionedd, mae hwn yn ffurfweddiad gwreiddiol symlach, ac eithrio'r llinellau hyn:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
Yn yr adran hon o'r cod rydym yn gosod ar ei gyfer cmake baner ar gyfer allforio gorchmynion crynhoi. Mae hyn yn angenrheidiol ar gyfer dadansoddwr cod statig. Gallwch ddarllen mwy am hyn yn yr erthygl “
Os oedd y cynulliad yn llwyddiannus, yna rydym yn cyrraedd ôl_llwyddiant, lle rydym yn perfformio dadansoddiad statig:
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
}
Gadewch i ni edrych yn agosach ar y llinellau canlynol:
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
Mae'r llinell gyntaf yn cynhyrchu ffeil trwydded o'r enw defnyddiwr a'r allwedd a nodwyd gennym ar y cychwyn cyntaf wrth sefydlu newidynnau amgylchedd Travis CI.
Mae'r ail linell yn cychwyn y dadansoddiad yn uniongyrchol. Baner -j yn gosod nifer yr edafedd i'w dadansoddi, fflag -l yn dynodi trwydded, baner -o yn diffinio'r ffeil ar gyfer allbynnu logiau, a'r faner -disableLicenseExpirationCheck sy'n ofynnol ar gyfer fersiynau prawf, ers yn ddiofyn pvs-stiwdio-dadansoddwr yn rhybuddio'r defnyddiwr bod y drwydded ar fin dod i ben. Er mwyn atal hyn rhag digwydd, gallwch chi nodi'r faner hon.
Mae'r ffeil log yn cynnwys allbwn crai na ellir ei ddarllen heb ei drosi, felly mae'n rhaid i chi wneud y ffeil yn ddarllenadwy yn gyntaf. Gadewch i ni basio'r logiau drwodd trawsnewidydd plog, ac mae'r allbwn yn ffeil html.
Yn yr enghraifft hon, penderfynais anfon adroddiadau trwy'r post gan ddefnyddio'r gorchymyn anfon e-bost.
O ganlyniad, cawsom y ffeil ganlynol .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;
Nawr mae'n bryd gwthio'r newidiadau i'r ystorfa git, ac ar ôl hynny bydd Travis CI yn rhedeg yr adeilad yn awtomatig. Cliciwch ar “ppsspp” i fynd i'r adroddiadau adeiladu:
Byddwn yn gweld trosolwg o'r adeilad presennol:
Os caiff y gwaith adeiladu ei gwblhau'n llwyddiannus, byddwn yn derbyn e-bost gyda chanlyniadau'r dadansoddiad statig. Wrth gwrs, nid postio yw'r unig ffordd i dderbyn adroddiad. Gallwch ddewis unrhyw ddull gweithredu. Ond mae'n bwysig cofio, ar ôl i'r gwaith adeiladu gael ei gwblhau, ni fydd yn bosibl cyrchu'r ffeiliau peiriant rhithwir.
Crynodeb gwall
Rydym wedi cwblhau'r rhan anoddaf yn llwyddiannus. Nawr gadewch i ni wneud yn siŵr bod ein holl ymdrechion yn werth chweil. Edrychwn ar rai pwyntiau diddorol o'r adroddiad dadansoddi statig a ddaeth ataf drwy'r post (nid am ddim y nodais hynny).
Optimeiddio peryglus
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 ) );
}
Rhybudd PVS-Stiwdio:
Mae'r darn hwn o god wedi'i leoli yn y modiwl stwnsio diogel, fodd bynnag, mae'n cynnwys diffyg diogelwch difrifol (
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Mae popeth mewn trefn a'r swyddogaeth memeset yn cael ei weithredu, a thrwy hynny trosysgrifo data pwysig yn RAM, fodd bynnag, peidiwch â llawenhau eto. Gadewch i ni edrych ar restr y cynulliad o'r fersiwn Rhyddhau gydag optimeiddio:
; 354 :
; 355 : memset( sum, 0, sizeof( sum ) );
; 356 :}
Fel y gwelir o'r rhestriad, anwybyddodd y casglwr yr alwad memeset. Mae hyn oherwydd y ffaith bod yn y swyddogaeth sha1 ar ôl yr alwad memeset dim mwy o gyfeiriadau at strwythur ctx. Felly, nid yw'r casglwr yn gweld unrhyw bwynt mewn gwastraffu amser prosesydd trosysgrifo cof na chaiff ei ddefnyddio yn y dyfodol. Gallwch drwsio hyn trwy ddefnyddio'r swyddogaeth RtlSecureZeroMemory neu
Yn gywir:
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 ) );
}
Cymhariaeth ddiangen
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);
}
}
Rhybudd PVS-Stiwdio:
Rhowch sylw i'r gangen arall am y cyntaf if. Bydd y cod yn cael ei weithredu dim ond os yw'r holl amodau leftvol > 0xFFFF || hawlvol > 0xFFFF || chwithvol < 0 || hawl< 0 bydd yn troi allan i fod yn ffug. Felly, rydym yn cael y datganiadau canlynol, a fydd yn wir am y gangen arall: leftvol <= 0xFFFF, hawlvol <=0xFFFF, chwithvol >= 0 и hawl >= 0. Sylwch ar y ddau ddatganiad olaf. A yw'n gwneud synnwyr i wirio beth yw amod angenrheidiol ar gyfer gweithredu'r darn hwn o god?
Felly gallwn gael gwared ar y datganiadau amodol hyn yn ddiogel:
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);
}
}
Senario arall. Mae rhyw fath o gamgymeriad wedi'i guddio y tu ôl i'r amodau segur hyn. Efallai na wnaethant wirio beth oedd ei angen.
Ctrl+C Mae Ctrl+V yn taro'n ôl
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfData) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Rhowch sylw i'r siec y tu mewn if. Onid ydych yn meddwl ei bod yn rhyfedd ein bod yn gwirio a yw'r cyfeiriad yn ddilys? psmfData, dwywaith cymaint? Felly mae hyn yn ymddangos yn rhyfedd i mi... Mewn gwirionedd, typo yw hwn, wrth gwrs, a'r syniad oedd gwirio'r ddau baramedr mewnbwn.
Opsiwn cywir:
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfStruct) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Newidyn wedi'i anghofio
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");
}
....
}
Rhybudd PVS-Stiwdio:
Mae'r gwall hwn wedi'i leoli yn y ffolder est, felly ddim yn berthnasol iawn i'r prosiect, ond darganfuwyd y byg cyn i mi sylwi arno, felly penderfynais ei adael. Wedi'r cyfan, nid yw'r erthygl hon yn ymwneud ag adolygu gwallau, ond am integreiddio â Travis CI, ac ni chynhaliwyd cyfluniad y dadansoddwr.
Amrywiol maint yn cael ei gychwyn gan gysonyn, fodd bynnag, nid yw'n cael ei ddefnyddio o gwbl yn y cod, hyd at y gweithredwr if, sydd, wrth gwrs, yn rhoi ffug wrth wirio'r amodau, oherwydd, fel y cofiwn, maint hafal i sero. Nid yw gwiriadau dilynol ychwaith yn gwneud unrhyw synnwyr.
Yn ôl pob tebyg, mae awdur y darn cod wedi anghofio trosysgrifo'r newidyn maint cyn hynny.
Stop
Dyma lle mae'n debyg y byddwn ni'n gorffen gyda'r camgymeriadau. Pwrpas yr erthygl hon yw arddangos gwaith PVS-Studio ynghyd â Travis CI, ac nid i ddadansoddi'r prosiect mor drylwyr â phosibl. Os ydych chi eisiau camgymeriadau mwy a harddach, gallwch chi bob amser eu hedmygu
Casgliad
Mae defnyddio gwasanaethau gwe i adeiladu prosiectau ynghyd â'r arfer o ddadansoddi cynyddrannol yn caniatáu ichi ddod o hyd i lawer o broblemau yn syth ar ôl uno cod. Fodd bynnag, efallai na fydd un adeiladwaith yn ddigon, felly bydd sefydlu profion ynghyd â dadansoddiad statig yn gwella ansawdd y cod yn sylweddol.
Dolenni defnyddiol
Os ydych chi am rannu'r erthygl hon â chynulleidfa Saesneg ei hiaith, defnyddiwch y ddolen gyfieithu: Maxim Zvyagintsev.
Ffynhonnell: hab.com