Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Travis CI er dreifð vefþjónusta til að smíða og prófa hugbúnað sem notar GitHub sem frumkóðahýsingu. Til viðbótar við ofangreindar rekstrarsviðsmyndir geturðu bætt við þínum eigin þökk sé víðtækum stillingarvalkostum. Í þessari grein munum við stilla Travis CI til að vinna með PVS-Studio með því að nota PPSSPP kóða dæmið.

Inngangur

Travis C.I. er vefþjónusta til að smíða og prófa hugbúnað. Það er venjulega notað í tengslum við samfellda samþættingaraðferðir.

PPSSPP — PSP leikjatölvu keppinautur. Forritið er fær um að líkja eftir ræsingu hvers kyns leikja frá diskamyndum sem ætlaðar eru fyrir Sony PSP. Dagskráin kom út 1. nóvember 2012. PPSSPP er með leyfi samkvæmt GPL v2. Hver sem er getur gert umbætur á frumkóði verkefnisins.

PVS-stúdíó — kyrrstöðugreiningartæki til að leita að villum og hugsanlegum veikleikum í forritakóða. Í þessari grein, til tilbreytingar, munum við ræsa PVS-Studio ekki á staðnum á vél þróunaraðila, heldur í skýinu, og leita að villum í PPSSPP.

Uppsetning Travis CI

Við munum þurfa geymslu á GitHub, þar sem verkefnið sem við þurfum er staðsett, sem og lykil fyrir PVS-Studio (þú getur fengið prufulykill eða ókeypis fyrir Open Source verkefni).

Við skulum fara á síðuna Travis C.I.. Eftir heimild með því að nota GitHub reikninginn þinn munum við sjá lista yfir geymslur:

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Fyrir prófið gaf ég PPSSPP.

Við virkum geymsluna sem við viljum safna:

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Í augnablikinu getur Travis CI ekki byggt verkefnið okkar vegna þess að það eru engar leiðbeiningar um byggingu. Svo það er kominn tími á uppsetningu.

Við greininguna munu sumar breytur nýtast okkur, til dæmis lykillinn fyrir PVS-Studio, sem óæskilegt væri að tilgreina í stillingarskránni. Svo skulum við bæta við umhverfisbreytum með því að nota byggingarstillingarnar í Travis CI:

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Við munum þurfa:

  • PVS_USERNAME - notendanafn
  • PVS_KEY - lykill
  • MAIL_USER - tölvupóstur sem verður notaður til að senda skýrsluna
  • MAIL_PASSWORD - lykilorð fyrir tölvupóst

Síðustu tveir eru valfrjálsir. Þetta verður notað til að senda niðurstöður í pósti. Ef þú vilt dreifa skýrslunni á annan hátt þarftu ekki að tilgreina þær.

Þannig að við höfum bætt við umhverfisbreytunum sem við þurfum:

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Nú skulum við búa til skrá .travis.yml og setja það í rót verkefnisins. PPSSPP var þegar með stillingarskrá fyrir Travis CI, hún var hins vegar of stór og algjörlega óhentug fyrir dæmið, svo við urðum að einfalda hana til muna og skilja aðeins eftir grunnþættina.

Í fyrsta lagi skulum við gefa til kynna tungumálið, útgáfu Ubuntu Linux sem við viljum nota í sýndarvélinni og nauðsynlega pakka fyrir smíðina:

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'

Allir pakkar sem eru skráðir eru eingöngu nauðsynlegir fyrir PPSSPP.

Nú tilgreinum við samsetningarfylki:

matrix:
  include:
    - os: linux
      compiler: "gcc"
      env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
    - os: linux
      compiler: "clang"
      env: PPSSPP_BUILD_TYPE=Linux

Aðeins meira um kaflann fylki. Í Travis CI eru tvær leiðir til að búa til byggingarvalkosti: sú fyrsta er að tilgreina lista yfir þýðendur, stýrikerfisgerðir, umhverfisbreytur o.s.frv., eftir það myndast fylki með öllum mögulegum samsetningum; annað er skýr vísbending um fylkið. Auðvitað geturðu sameinað þessar tvær aðferðir og bætt við einstöku tilviki, eða þvert á móti, útilokað það með því að nota hlutann útiloka. Þú getur lesið meira um þetta í Travis CI skjöl.

Það eina sem er eftir er að koma með verksértækar samsetningarleiðbeiningar:

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 gerir þér kleift að bæta við þínum eigin skipunum fyrir mismunandi stig í lífi sýndarvélar. kafla before_install keyrt áður en pakka er sett upp. Þá setja, sem fylgir uppsetningu pakka af listanum addons.aptsem við bentum á hér að ofan. Þingið sjálft fer fram í handrit. Ef allt gekk vel, þá finnum við okkur sjálf eftir_árangur (það er í þessum hluta sem við munum keyra kyrrstöðugreiningu). Þetta eru ekki öll skrefin sem hægt er að breyta, ef þú þarft meira, þá ættirðu að líta inn Travis CI skjöl.

Til að auðvelda lestur voru skipanirnar settar í sérstakt handrit .travis.sh, sem er sett við verkrót.

Svo við höfum eftirfarandi skrá .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

Áður en pakkarnir eru settir upp munum við uppfæra undireiningarnar. Þetta er nauðsynlegt til að byggja upp PPSSPP. Við skulum bæta fyrstu aðgerðinni við .travis.sh (athugið framlenginguna):

travis_before_install() {
  git submodule update --init --recursive
}

Nú komum við beint að því að setja upp sjálfvirka ræsingu PVS-Studio í Travis CI. Fyrst þurfum við að setja upp PVS-Studio pakkann á kerfinu:

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
}

Í upphafi fallsins travis_install við setjum upp þýðendur sem við þurfum með því að nota umhverfisbreytur. Þá ef breyt $PVS_ANALYZE verðmæti verslana (við bentum á það í kaflanum env við uppsetningu byggðarfylkis), setjum við upp pakkann pvs-stúdíó. Auk þessa eru pakkar einnig tilgreindir libio-socket-ssl-perl и libnet-ssleay-perlÞær eru hins vegar nauðsynlegar til að senda niðurstöður, svo þær eru ekki nauðsynlegar ef þú hefur valið aðra aðferð til að koma skýrslunni til skila.

Virka niðurhal_útdráttur hleður niður og pakkar upp tilgreindu skjalasafni:

download_extract() {
  aria2c -x 16 $1 -o $2
  tar -xf $2
}

Það er kominn tími til að setja verkefnið saman. Þetta gerist í kaflanum handrit:

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
}

Reyndar er þetta einfölduð upprunaleg uppsetning, nema þessar línur:

if [ "$PVS_ANALYZE" = "Yes" ]; then
  CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi

Í þessum hluta kóða sem við setjum fyrir cmgerð fána til að flytja út safnskipanir. Þetta er nauðsynlegt fyrir kyrrstöðugreiningartæki. Þú getur lesið meira um þetta í greininni “Hvernig á að keyra PVS-Studio á Linux og macOS".

Ef samkoman heppnaðist vel, þá komumst við að eftir_árangur, þar sem við framkvæmum kyrrstöðugreiningu:

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
}

Við skulum skoða nánar eftirfarandi línur:

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

Fyrsta línan býr til leyfisskrá úr notandanafninu og lyklinum sem við tilgreindum í upphafi þegar Travis CI umhverfisbreyturnar voru settar upp.

Önnur línan byrjar greininguna beint. Fáni -j setur fjölda þráða til greiningar, flaggi -l gefur til kynna leyfi, fána -o skilgreinir skrána til að gefa út logs og fánann -disableLicense ExpirationCheck krafist fyrir prufuútgáfur, þar sem sjálfgefið er pvs-stúdíó-greiningartæki mun vara notandann við því að leyfið sé að renna út. Til að koma í veg fyrir að þetta gerist geturðu tilgreint þennan fána.

Notkunarskráin inniheldur hrátt úttak sem ekki er hægt að lesa án umbreytingar, svo þú verður fyrst að gera skrána læsilega. Við skulum renna stokkunum í gegn plog-breytir, og úttakið er html skrá.

Í þessu dæmi ákvað ég að senda skýrslur í pósti með skipuninni senda tölvupóst.

Fyrir vikið fengum við eftirfarandi skrá .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;

Nú er kominn tími til að ýta undir breytingar á git geymslunni, eftir það mun Travis CI keyra bygginguna sjálfkrafa. Smelltu á „ppsspp“ til að fara í byggingarskýrslurnar:

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Við munum sjá yfirlit yfir núverandi byggingu:

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi
Ef smíði er lokið, munum við fá tölvupóst með niðurstöðum kyrrstöðugreiningarinnar. Auðvitað er póstsending ekki eina leiðin til að fá skýrslu. Þú getur valið hvaða útfærsluaðferð sem er. En það er mikilvægt að muna að eftir að smíði er lokið verður ekki hægt að nálgast sýndarvélaskrárnar.

Villusamantekt

Við höfum lokið erfiðasta hlutanum. Nú skulum við ganga úr skugga um að öll viðleitni okkar sé þess virði. Við skulum skoða nokkra áhugaverða punkta úr kyrrstöðugreiningarskýrslunni sem barst mér í pósti (það var ekki fyrir ekkert sem ég gaf til kynna).

Hættuleg hagræðing

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-Stúdíó viðvörun: V597 Þjálfarinn gæti eytt 'memset' aðgerðakallinu, sem er notað til að skola út 'summa' biðminni. RtlSecureZeroMemory() aðgerðina ætti að nota til að eyða einkagögnunum. sha1.cpp 325

Þetta stykki af kóða er staðsett í öruggu hashing-einingunni, en hann inniheldur hins vegar alvarlegan öryggisgalla (CWE-14). Við skulum skoða samsetningarskráninguna sem myndast þegar kembiforritið er sett saman:

; Line 355
  mov r8d, 20
  xor edx, edx
  lea rcx, QWORD PTR sum$[rsp]
  call memset
; Line 356

Allt er í röð og reglu og virkni memeset er keyrt, og skrifar þar með yfir mikilvæg gögn í vinnsluminni, þó ekki fagna enn sem komið er. Við skulum skoða samsetningarskráningu útgáfu útgáfunnar með hagræðingu:

; 354  :
; 355  :  memset( sum, 0, sizeof( sum ) );
; 356  :}

Eins og sjá má á skráningunni hunsaði þýðandinn símtalið memeset. Þetta er vegna þess að í aðgerðinni sha1 eftir símtalið memeset ekki lengur tilvísun í uppbyggingu ctx. Þess vegna sér þýðandinn engan tilgang í að eyða tíma örgjörva í að skrifa yfir minni sem ekki er notað í framtíðinni. Þú getur lagað þetta með því að nota aðgerðina RtlSecureZeroMemory eða svipað til hennar.

Rétt:

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 ) );
} 

Óþarfa samanburður

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-Stúdíó viðvörun: V547 Tjáning 'leftvol >= 0' er alltaf satt. sceAudio.cpp 120

Gefðu gaum að annarri greininni fyrir það fyrsta if. Kóðinn verður aðeins keyrður að öllum skilyrðum uppfylltum leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || hægrivol < 0 mun reynast rangt. Þess vegna fáum við eftirfarandi fullyrðingar, sem eiga við um hina greinina: leftvol <= 0xFFFF, rightvol <= 0xFFFF, vinstrivoli >= 0 и rightvol >= 0. Taktu eftir síðustu tveimur fullyrðingunum. Er skynsamlegt að athuga hvað er nauðsynlegt skilyrði fyrir framkvæmd þessa kóða?

Svo við getum örugglega fjarlægt þessar skilyrtu yfirlýsingar:

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);
  }
}

Önnur atburðarás. Það er einhvers konar villa falin á bak við þessi óþarfa skilyrði. Kannski athugaðu þeir ekki hvað var krafist.

Ctrl+C Ctrl+V slær til baka

static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
  if (!Memory::IsValidAddress(psmfData) ||
      !Memory::IsValidAddress(psmfData)) {
    return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
  }
  ....
}

V501 Það eru eins undirtjáningar '!Memory::IsValidAddress(psmfData)' vinstra megin og hægra megin við '||' rekstraraðili. scePsmf.cpp 703

Gefðu gaum að ávísuninni inni if. Finnst þér ekki skrítið að við athugum hvort heimilisfangið sé gilt? psmfGögn, tvöfalt meira? Svo þetta finnst mér skrítið... Reyndar er þetta auðvitað innsláttarvilla og hugmyndin var að athuga báðar innsláttarfæribreyturnar.

Réttur valkostur:

static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
  if (!Memory::IsValidAddress(psmfStruct) ||
      !Memory::IsValidAddress(psmfData)) {
    return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
  }
  ....
}

Gleymd breyta

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-Stúdíó viðvörun: V547 Tjáning 'stærð == 8' er alltaf ósönn. syn-att.c 195

Þessi villa er staðsett í möppunni EXT, svo ekki í raun við verkefnið, en villan fannst áður en ég tók eftir því, svo ég ákvað að yfirgefa hana. Þegar öllu er á botninn hvolft snýst þessi grein ekki um að skoða villur, heldur um samþættingu við Travis CI, og engin uppsetning á greiningartækinu var framkvæmd.

Breytilegt stærð er frumstillt með fasta, hins vegar er hann alls ekki notaður í kóðanum, alveg niður til rekstraraðilans if, sem auðvitað gefur rangar við að athuga skilyrðin, því eins og við munum, stærð jafnt og núll. Síðari athuganir hafa heldur engan tilgang.

Svo virðist sem höfundur kóðabrotsins hafi gleymt að skrifa yfir breytuna stærð fyrir það.

Hætta

Þetta er þar sem við munum líklega enda með mistökin. Tilgangur þessarar greinar er að sýna fram á vinnu PVS-Studio ásamt Travis CI, en ekki að greina verkefnið eins ítarlega og hægt er. Ef þú vilt stærri og fallegri mistök geturðu alltaf dáðst að þeim hér :).

Ályktun

Með því að nota vefþjónustur til að byggja upp verkefni ásamt því að æfa stigvaxandi greiningu geturðu fundið mörg vandamál strax eftir sameiningu kóða. Hins vegar gæti ein bygging ekki verið nóg, svo að setja upp próf ásamt kyrrstöðugreiningu mun bæta gæði kóðans verulega.

gagnlegir krækjur

Hvernig á að stilla PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi

Ef þú vilt deila þessari grein með enskumælandi áhorfendum, vinsamlegast notaðu þýðingartengilinn: Maxim Zvyagintsev. Hvernig á að setja upp PVS-Studio í Travis CI með því að nota dæmi um PSP leikjatölvuhermi.

Heimild: www.habr.com

Bæta við athugasemd