Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Travis CI minangka layanan web sing disebarake kanggo mbangun lan nguji piranti lunak sing nggunakake GitHub minangka hosting kode sumber. Saliyane ing skenario operasi ndhuwur, sampeyan bisa nambah thanks dhewe kanggo opsi konfigurasi ekstensif. Ing artikel iki, kita bakal ngatur Travis CI kanggo nggarap PVS-Studio nggunakake conto kode PPSSPP.

Pambuka

Travis C.I. minangka layanan web kanggo mbangun lan nguji piranti lunak. Biasane digunakake bebarengan karo praktik integrasi sing terus-terusan.

PPSSPP - Emulator konsol game PSP. Program kasebut bisa niru peluncuran game apa wae saka gambar disk sing dimaksudake kanggo Sony PSP. Program iki dirilis tanggal 1 November 2012. PPSSPP dilisensi ing GPL v2. Sapa wae bisa nggawe dandan kode sumber proyek.

PVS Studio - penganalisa kode statis kanggo nggoleki kesalahan lan kerentanan potensial ing kode program. Ing artikel iki, kanggo ngganti, kita bakal miwiti PVS-Studio ora lokal ing mesin pangembang, nanging ing maya, lan goleki kasalahan ing PPSSPP.

Nggawe Travis CI

Kita butuh repositori ing GitHub, ing ngendi proyek sing kita butuhake, uga kunci kanggo PVS-Studio (sampeyan bisa entuk kunci nyoba utawa gratis kanggo proyek Open Source).

Ayo menyang situs Travis C.I.. Sawise wewenang nggunakake akun GitHub, kita bakal weruh dhaptar repositori:

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Kanggo tes, aku nyuwil PPSSPP.

Kita ngaktifake repositori sing pengin diklumpukake:

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Ing wayahe, Travis CI ora bisa mbangun proyek kita amarga ora ana instruksi kanggo mbangun. Dadi wektu kanggo konfigurasi.

Sajrone analisis, sawetara variabel bakal migunani kanggo kita, contone, tombol kanggo PVS-Studio, sing ora dikarepake kanggo nemtokake ing file konfigurasi. Dadi ayo nambah variabel lingkungan nggunakake setelan mbangun ing Travis CI:

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Kita kudu:

  • PVS_USERNAME - jeneng panganggo
  • PVS_KEY - tombol
  • MAIL_USER - email sing bakal digunakake kanggo ngirim laporan
  • MAIL_PASSWORD - sandi email

Loro pungkasan iku opsional. Iki bakal digunakake kanggo ngirim asil liwat mail. Yen sampeyan pengin nyebarake laporan kanthi cara liya, sampeyan ora perlu menehi tandha.

Dadi, kita wis nambahake variabel lingkungan sing dibutuhake:

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Saiki ayo nggawe file .travis.yml lan sijine iku ing ROOT saka project. PPSSPP wis duwe file konfigurasi kanggo Travis CI, Nanging, iku gedhe banget lan ora cocog kanggo contone, supaya kita kudu nemen menakake lan ninggalake mung unsur dhasar.

Pisanan, ayo nuduhake basa, versi Ubuntu Linux sing pengin digunakake ing mesin virtual, lan paket sing dibutuhake kanggo mbangun:

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'

Kabeh paket sing kadhaptar dibutuhake khusus kanggo PPSSPP.

Saiki kita nuduhake matriks perakitan:

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

A sethitik liyane babagan bagean Matriks. Ing Travis CI, ana rong cara kanggo nggawe opsi mbangun: sing pisanan yaiku nemtokake dhaptar kompiler, jinis sistem operasi, variabel lingkungan, lan liya-liyane, sawise matriks kabeh kombinasi sing bisa digawe; kapindho minangka pratondo eksplisit saka matriks. Mesthi, sampeyan bisa nggabungake loro pendekatan kasebut lan nambah kasus sing unik, utawa, sebaliknya, ora kalebu nggunakake bagean kasebut. ngilangi. Sampeyan bisa maca liyane babagan iki ing Dokumentasi Travis CI.

Kabeh sing isih ana yaiku nyedhiyakake instruksi perakitan khusus proyek:

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 ngijini sampeyan kanggo nambah printah dhewe kanggo macem-macem orane tumrap sekolah saka urip mesin virtual. Bagean sadurunge_instal dieksekusi sadurunge nginstal paket. Banjur masang, sing nderek instalasi paket saka dhaptar addons.aptsing wis dituduhake ing ndhuwur. Majelis dhewe njupuk Panggonan ing script. Yen kabeh mlaku kanthi becik, mula kita bakal mlebu sawise_sukses (Ing bagean iki kita bakal mbukak analisis statis). Iki ora kabeh langkah sing bisa diowahi, yen sampeyan butuh luwih akeh, sampeyan kudu ndeleng Dokumentasi Travis CI.

Kanggo gampang diwaca, prentah kasebut diselehake ing naskah sing kapisah .travis.sh, kang diselehake ing ROOT project.

Dadi kita duwe file ing ngisor iki .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

Sadurunge nginstal paket, kita bakal nganyari submodul. Iki perlu kanggo mbangun PPSSPP. Ayo dadi nambah fungsi pisanan kanggo .travis.sh (cathetan ekstensi):

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

Saiki kita langsung nyiyapake peluncuran otomatis PVS-Studio ing Travis CI. Pisanan kita kudu nginstal paket PVS-Studio ing sistem:

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
}

Ing wiwitan fungsi travis_install kita nginstal kompiler sing kita butuhake nggunakake variabel lingkungan. Banjur yen variabel $PVS_ANALYZE nyimpen nilai Ya (kita nuduhake ing bagean kasebut sugeng nalika mbangun konfigurasi matriks), kita nginstal paket kasebut pvs-studio. Saliyane iki, paket uga dituduhake libio-soket-ssl-perl ΠΈ libnet-ssleay-perl, Nanging, iku dibutuhake kanggo asil mail, supaya iku ora perlu yen sampeyan wis milih cara liyane kanggo ngirim laporan.

fungsi download_ekstrak ngundhuh lan mbongkar arsip sing ditemtokake:

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

Iku wektu kanggo sijine proyek bebarengan. Iki kedadeyan ing bagean kasebut 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
}

Nyatane, iki minangka konfigurasi asli sing disederhanakake, kajaba baris kasebut:

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

Ing bagean kode iki kita nyetel kanggo cmake flag kanggo ngekspor printah kompilasi. Iki perlu kanggo penganalisa kode statis. Sampeyan bisa maca liyane babagan iki ing artikel "Cara mbukak PVS-Studio ing Linux lan macOS".

Yen majelis wis sukses, banjur kita njaluk menyang sawise_sukses, ing ngendi kita nindakake analisis statis:

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
}

Ayo katon luwih cetha ing baris ing ngisor iki:

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

Baris pisanan ngasilake file lisensi saka jeneng pangguna lan kunci sing wis ditemtokake ing wiwitan nalika nyetel variabel lingkungan Travis CI.

Baris kapindho miwiti analisis langsung. GendΓ©ra -j nyetel nomer Utas kanggo analisis, flag -l nuduhake lisensi, flag -o nemtokake file kanggo outputting log, lan flag -disableLicenseExpirationCheck dibutuhake kanggo versi nyoba, wiwit minangka standar pvs-studio-analyzer bakal ngelingake pangguna yen lisensi bakal kadaluwarsa. Kanggo nyegah kedadeyan kasebut, sampeyan bisa nemtokake gendera iki.

File log ngemot output mentah sing ora bisa diwaca tanpa konversi, mula sampeyan kudu nggawe file kasebut bisa diwaca. Ayo liwat log liwat plug-converter, lan output minangka file html.

Ing conto iki, aku mutusake ngirim laporan kanthi mail nggunakake printah sendemail.

AkibatΓ©, kita entuk file ing ngisor iki .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;

Saiki wektune kanggo push owah-owahan menyang repositori git, sawise Travis CI bakal kanthi otomatis mbukak mbangun. Klik ing "ppsspp" kanggo pindhah menyang laporan mbangun:

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Kita bakal weruh ringkesan babagan bangunan saiki:

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP
Yen mbangun kasil rampung, kita bakal nampa email karo asil analisis statis. Mesthi, surat ora mung cara kanggo nampa laporan. Sampeyan bisa milih cara implementasine. Nanging penting kanggo elinga yen sawise mbangun rampung, ora bakal bisa ngakses file mesin virtual.

Ringkesan kesalahan

Kita wis kasil ngrampungake bagean sing paling angel. Saiki ayo padha mesthekake yen kabeh usaha kita bakal entuk manfaat. Ayo goleki sawetara poin sing menarik saka laporan analisis statis sing teka ing emailku (ora ana gunane sing dakkandhakake).

Optimasi mbebayani

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 warning: V597 Compiler bisa mbusak telpon fungsi 'memset', kang digunakake kanggo flush 'sum' buffer. Fungsi RtlSecureZeroMemory () kudu digunakake kanggo mbusak data pribadi. sha1.cpp 325

Potongan kode iki ana ing modul hashing sing aman, nanging ngemot cacat keamanan sing serius (CWE-14). Ayo goleki dhaptar perakitan sing digawe nalika nyusun versi Debug:

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

Kabeh ana ing urutan lan fungsi memeset wis kaleksanan, mangkono nimpa data penting ing RAM, Nanging, aja bungah mung durung. Ayo ndeleng dhaptar perakitan versi Rilis kanthi optimalisasi:

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

Kaya sing bisa dideleng saka dhaptar, kompiler ora nggatekake telpon kasebut memeset. Iki amarga kasunyatan sing ing fungsi sha1 sawise telpon memeset ora ana maneh referensi kanggo struktur CTX. Mulane, compiler weruh ora ana titik kanggo mbuang wektu prosesor overwriting memori sing ora digunakake ing mangsa. Sampeyan bisa ndandani iki kanthi nggunakake fungsi kasebut RtlSecureZeroMemory utawa meh padha dheweke.

Bener:

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

Perbandingan sing ora perlu

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 warning: V547 Ekspresi 'leftvol >= 0' mesthi bener. sceAudio.cpp 120

Pay manungsa waé menyang cabang liyane kanggo pisanan if. Kode bakal dieksekusi mung yen kabeh kahanan leftvol > 0xFFFF || volume tengen > 0xFFFF || kiwavol < 0 || volume tengen <0 bakal dadi palsu. Mulane, kita entuk pernyataan ing ngisor iki, sing bakal bener kanggo cabang liya: volume kiwa <= 0xFFFF, volume tengen <= 0xFFFF, volume kiri >= 0 и volume tengen > = 0. Wigati rong statement pungkasan. Apa ana pangertèn kanggo mriksa apa syarat sing dibutuhake kanggo eksekusi kode kasebut?

Supaya kita bisa mbusak statement kondisional iki kanthi aman:

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

Skenario liyane. Ana sawetara jinis kesalahan sing didhelikake ing mburi kahanan sing berlebihan iki. Mbok menawa dheweke ora mriksa apa sing dibutuhake.

Ctrl+C Ctrl+V Strike 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");
  }
  ....
}

V501 Ana sub-ekspresi sing padha '!Memory::IsValidAddress(psmfData)' ing sisih kiwa lan ing sisih tengen '||' operator. scePsmf.cpp 703

Pay manungsa waé menyang mriksa nang if. Apa sampeyan ora mikir aneh yen kita mriksa alamat kasebut bener? psmfData, ping pindho? Dadi iki misale jek aneh kanggo kula ... Ing kasunyatan, iki, mesthi, typo, lan idea iki kanggo mriksa loro paramèter input.

Pilihan sing bener:

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

variabel lali

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 warning: V547 Ekspresi 'ukuran == 8' tansah palsu. syn-att.c 195

Kesalahan iki dumunung ing folder kasebut ext, dadi ora cocog karo proyek kasebut, nanging bug kasebut ditemokake sadurunge aku weruh, mula aku mutusake ninggalake. Sawise kabeh, artikel iki dudu babagan mriksa kesalahan, nanging babagan integrasi karo Travis CI, lan ora ana konfigurasi analisa sing ditindakake.

Variabel ukuran wis initialized dening pancet, Nanging, iku ora digunakake ing kabeh ing kode, hak mudhun kanggo operator if, kang, mesthi, menehi palsu nalika mriksa kahanan, amarga kita elinga, ukuran padha karo nul. Priksa sabanjure uga ora ana gunane.

Ketoke, penulis fragmen kode kelalen nimpa variabel kasebut ukuran sadurunge iku.

mungkasi

Iki ngendi kita bakal mungkasi karo kesalahan. Tujuan saka artikel iki kanggo nduduhake karya PVS-Studio bebarengan karo Travis CI, lan ora kanggo njelasno project sak tenane sabisa. Yen sampeyan pengin kesalahan sing luwih gedhe lan luwih apik, sampeyan bisa tansah ngujo kene :).

kesimpulan

Nggunakake layanan web kanggo mbangun proyek bebarengan karo praktik analisis tambahan ngidini sampeyan nemokake akeh masalah langsung sawise nggabungake kode. Nanging, siji mbangun bisa uga ora cukup, supaya nyetel testing bebarengan karo analisis statis bakal Ngartekno nambah kualitas kode.

link migunani

Carane ngatur PVS-Studio ing Travis CI nggunakake conto emulator console game PSP

Yen sampeyan pengin nuduhake artikel iki karo pamirsa sing nganggo basa Inggris, gunakake tautan terjemahan: Maxim Zvyagintsev. Cara nyiyapake PVS-Studio ing Travis CI nggunakake conto emulator konsol game PSP.

Source: www.habr.com

Add a comment