Travis CI ass e verdeelt Webservice fir Software ze bauen an ze testen déi GitHub als Quellcode-Hosting benotzt. Zousätzlech zu den uewe genannte Betriebsszenarien, kënnt Dir Är eege bäidroen duerch déi extensiv Konfiguratiounsoptiounen. An dësem Artikel wäerte mir den Travis CI konfiguréieren fir mat PVS-Studio mat dem PPSSPP Code Beispill ze schaffen.
Aféierung
Ariichten Travis CI
Mir brauchen e Repository op GitHub, wou de Projet dee mir brauchen ass lokaliséiert, souwéi e Schlëssel fir PVS-Studio (Dir kënnt kréien
Loosst eis op de Site goen
Fir den Test hunn ech PPSSPP geflunn.
Mir aktivéieren de Repository dee mir wëllen sammelen:
Am Moment kann den Travis CI eise Projet net bauen, well et keng Instruktioune gëtt fir ze bauen. Also ass et Zäit fir d'Konfiguratioun.
Während der Analyse wäerten e puer Verännerlechen nëtzlech sinn fir eis, zum Beispill de Schlëssel fir PVS-Studio, wat onerwënscht wier an der Konfiguratiounsdatei ze spezifizéieren. Also loosst eis Ëmfeldvariablen addéieren mat de Build-Astellungen am Travis CI:
Mir brauchen:
- PVS_USERNAME - Benotzernumm
- PVS_KEY - Schlëssel
- MAIL_USER - E-Mail déi benotzt gëtt fir de Bericht ze schécken
- MAIL_PASSWORD - E-Mail Passwuert
Déi lescht zwee sinn fakultativ. Dës gi benotzt fir Resultater per Mail ze schécken. Wann Dir de Rapport op eng aner Manéier wëllt verdeelen, musst Dir se net uginn.
Also, mir hunn d'Ëmweltvariablen bäigefüügt déi mir brauchen:
Loosst eis elo eng Datei erstellen .travis.yml a Plaz et an der Wuerzel vum Projet. PPSSPP hat schonn e Configuratiounsdatei fir Travis CI, awer et war ze grouss a komplett net gëeegent fir d'Beispill, also hu mir et vill vereinfachen an nëmmen d'Basiselementer verloossen.
Als éischt, loosst eis d'Sprooch uginn, d'Versioun vun Ubuntu Linux déi mir an der virtueller Maschinn benotze wëllen, an déi néideg Packagen fir de Bau:
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'
All Packagen déi opgelëscht sinn sinn exklusiv fir PPSSPP gebraucht.
Elo weisen mir d'Versammlungsmatrix un:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
E bësse méi iwwer d'Sektioun Matrix. Am Travis CI ginn et zwou Méiglechkeeten fir Bauoptiounen ze kreéieren: déi éischt ass eng Lëscht vu Compileren ze spezifizéieren, Betribssystemtypen, Ëmweltvariablen, etc., no deem eng Matrix vun all méigleche Kombinatioune generéiert gëtt; déi zweet ass eng explizit Indikatioun vun der Matrix. Natierlech kënnt Dir dës zwou Approche kombinéieren an en eenzegaartege Fall addéieren, oder am Géigendeel, et ausgeschloss mat der Sektioun ausgeschloss sinn. Dir kënnt méi iwwer dëst liesen an
Alles wat bleift ass fir Projet-spezifesch Montageinstruktiounen ze bidden:
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 erlaabt Iech Är eege Kommandoen fir verschidde Stadien vum Liewen vun enger virtueller Maschinn ze addéieren. Sektioun virun_installéieren ausgefouert ier Dir Packagen installéiert. Dann installéieren, déi no der Installatioun vu Packagen aus der Lëscht follegt addons.aptdéi mir uewen uginn. D'Versammlung selwer fënnt am Schrëft. Wann alles gutt gaang ass, da fanne mir eis eran after_erfolg (et ass an dëser Sektioun datt mir statesch Analyse lafen). Dëst sinn net all Schrëtt déi geännert kënne ginn, wann Dir méi braucht, da sollt Dir kucken
Fir Liichtegkeet ze liesen, goufen d'Befehle an engem separaten Skript gesat .travis.sh, déi am Projet root gesat gëtt.
Also hu mir déi folgend Datei .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
Ier Dir d'Packagen installéiere wäerte mir d'Submodule aktualiséieren. Dëst ass néideg fir PPSSPP ze bauen. Loosst eis déi éischt Funktioun addéieren .travis.sh (notéiert d'Verlängerung):
travis_before_install() {
git submodule update --init --recursive
}
Elo komme mir direkt fir den automateschen Start vum PVS-Studio am Travis CI opzestellen. Als éischt musse mir de PVS-Studio Package um System installéieren:
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
}
Am Ufank vun der Funktioun travis_install mir installéieren d'Compiler déi mir brauchen mat Ëmfeldvariablen. Dann wann d'Variabel $PVS_ANALYSE Geschäfter Wäert Jo (mir hunn et an der Rubrik uginn schécken während der Baumatrixkonfiguratioun), installéiere mir de Package pvs-studio. Zousätzlech zu dësem ginn och Packagen uginn libio-socket-ssl-perl и libnet-ssleay-perl, si sinn awer erfuerderlech fir d'Resultater ze mailen, sou datt se net néideg sinn wann Dir eng aner Methode gewielt hutt fir Äre Bericht ze liwweren.
Funktioun download_extrakt downloadt an packt de spezifizéierte Archiv aus:
download_extract() {
aria2c -x 16 $1 -o $2
tar -xf $2
}
Et ass Zäit de Projet zesummenzestellen. Dëst geschitt an der Rubrik Schrëft:
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
}
Tatsächlech ass dëst eng vereinfacht originell Konfiguratioun, ausser fir dës Linnen:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
An dëser Rubrik vum Code setzen mir fir cm maachen Fändel fir d'Kompilatiounsbefehl ze exportéieren. Dëst ass néideg fir e statesche Code Analyser. Dir kënnt méi iwwer dëst am Artikel liesen "
Wann d'Versammlung erfollegräich war, da komme mir op after_erfolg, wou mir statesch Analyse maachen:
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
}
Loosst eis déi folgend Zeilen méi no kucken:
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
Déi éischt Zeil generéiert eng Lizenzdatei vum Benotzernumm a Schlëssel, dee mir am Ufank uginn hunn wann Dir d'Travis CI Ëmfeldvariablen opstellt.
Déi zweet Linn fänkt d'Analyse direkt un. Fändel -j setzt d'Zuel vun thread fir Analyse, Fändel -l weist Lizenz, Fändel -o definéiert d'Datei fir Logbicher auszeginn, an de Fändel -disableLicenseExpirationCheck néideg fir Test Versiounen, zënter Par défaut pvs-studio-analyzer wäert de Benotzer warnen datt d'Lizenz amgaang ass ofzelafen. Fir dëst ze verhënneren, kënnt Dir dëse Fändel uginn.
D'Protokolldatei enthält rau Output déi net ouni Konversioun gelies ka ginn, also musst Dir d'Fichier als éischt liesbar maachen. Loosst eis d'Logbicher duerchgoen Plog-Converter, an d'Ausgab ass eng HTML Datei.
An dësem Beispill hunn ech beschloss Berichter per Mail mat dem Kommando ze schécken sendmail.
Als Resultat krute mir déi folgend Datei .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;
Elo ass et Zäit d'Ännerungen op de Git Repository ze drécken, duerno wäert Travis CI automatesch de Build lafen. Klickt op "ppsspp" fir op d'Build Berichter ze goen:
Mir wäerten en Iwwerbléck iwwer den aktuelle Bau gesinn:
Wann de Bau erfollegräich ofgeschloss ass, kréie mir eng E-Mail mat de Resultater vun der statescher Analyse. Natierlech ass Mailing net deen eenzege Wee fir e Bericht ze kréien. Dir kënnt all Ëmsetzungsmethod wielen. Awer et ass wichteg ze erënneren datt nodeems de Bau ofgeschloss ass, et net méiglech ass op déi virtuell Maschinndateien ze kommen.
Feeler Resumé
Mir hunn de schwieregsten Deel erfollegräich ofgeschloss. Loosst eis elo sécherstellen datt all eis Efforten et wäert sinn. Loosst eis e puer interessant Punkten aus dem statesche Analysebericht kucken, dee mir per Mail komm ass (et war net fir näischt datt ech et uginn hunn).
Geféierlech Optimisatioun
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 Warnung:
Dëst Stéck Code ass am séchere Hashing Modul lokaliséiert, awer et enthält e seriéise Sécherheetsfehler (
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Alles ass an Uerdnung an d'Funktioun memeset ausgeführt gëtt, doduerch wichteg Donnéeën am RAM iwwerschreiwe, awer freet Iech nach net. Loosst eis d'Versammlungslëscht vun der Release Versioun mat Optimiséierung kucken:
; 354 :
; 355 : memset( sum, 0, sizeof( sum ) );
; 356 :}
Wéi aus der Oplëschtung gesi ka ginn, huet de Compiler den Uruff ignoréiert memeset. Dëst ass wéinst der Tatsaach, datt an der Funktioun sha1 nom Opruff memeset keng Referenz méi op Struktur ctx. Dofir gesäit de Compiler kee Sënn fir Prozessor Zäit ze verschwenden iwwer d'Erënnerung déi net an Zukunft benotzt gëtt. Dir kënnt dëst fixéieren andeems Dir d'Funktioun benotzt RtlSecureZeroMemory oder
Richteg:
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 ) );
}
Onnéideg Verglach
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 Warnung:
Opgepasst op déi aner Branche fir d'éischt if. De Code gëtt nëmmen ausgefouert wann all Konditiounen leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rechtvol < 0 wäert sech falsch erausstellen. Dofir kréie mir déi folgend Aussoen, déi richteg sinn fir déi aner Branche: leftvol <= 0xFFFF, rightvol <= 0xFFFF, leftvol >= 0 и rietsvol >= 0. Notéiert déi lescht zwou Aussoen. Ass et Sënn fir z'iwwerpréiwen wat eng néideg Bedingung ass fir d'Ausféierung vun dësem Stéck Code?
Also kënne mir sécher dës bedingte Aussoen ewechhuelen:
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);
}
}
En aneren Szenario. Et ass eng Aart vu Feeler verstoppt hannert dëse redundante Konditiounen. Vläicht hu se net kontrolléiert wat néideg war.
Ctrl+C Ctrl+V Strikes Back
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfData) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Opgepasst op de Scheck bannen if. Fannt Dir et net komesch datt mir kucken ob d'Adress valabel ass? psmfDaten, duebel sou vill? Also dat schéngt mir komesch ... Tatsächlech ass dëst natierlech en Tippfeeler, an d'Iddi war déi zwee Inputparameter ze kontrolléieren.
Déi richteg Optioun:
static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
if (!Memory::IsValidAddress(psmfStruct) ||
!Memory::IsValidAddress(psmfData)) {
return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
}
....
}
Vergiess Variabel
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 Warnung:
Dëse Feeler läit am Dossier ext, Also net wierklech relevant fir de Projet, awer de Käfer gouf fonnt ier ech et gemierkt hunn, also hunn ech decidéiert et ze verloossen. No allem ass dësen Artikel net iwwer d'Iwwerpréiwung vu Feeler, mee iwwer d'Integratioun mam Travis CI, a keng Konfiguratioun vum Analyser gouf duerchgefouert.
Variabel Gréisst gëtt vun enger konstanter initialiséiert, awer et gëtt guer net am Code benotzt, bis zum Bedreiwer if, déi natierlech gëtt falsch beim Iwwerpréiwen vun de Bedéngungen, well, wéi mir eis erënneren, Gréisst gläich op null. Spéider Kontrollen maachen och kee Sënn.
Anscheinend huet den Auteur vum Codefragment vergiess d'Variabel ze iwwerschreiwen Gréisst virun deem.
Stop
Hei wäerte mer wahrscheinlech mat de Feeler ophalen. Den Zweck vun dësem Artikel ass d'Aarbecht vum PVS-Studio zesumme mam Travis CI ze demonstréieren, an net de Projet esou grëndlech wéi méiglech ze analyséieren. Wann Dir méi grouss a méi schéin Feeler wëllt, kënnt Dir se ëmmer bewonneren
Konklusioun
Mat Webservicer fir Projeten ze bauen zesumme mat der Praxis vun der inkrementeller Analyse erlaabt Iech vill Probleemer direkt nom Fusiounscode ze fannen. Wéi och ëmmer, ee Bau ass vläicht net genuch, sou datt d'Tester zesumme mat der statescher Analyse d'Qualitéit vum Code wesentlech verbesseren.
Nëtzlech Adressen
Wann Dir dësen Artikel mat engem engleschsproochege Publikum wëllt deelen, benotzt w.e.g. den Iwwersetzungslink: Maxim Zvyagintsev.
Source: will.com