Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Το Travis CI είναι μια κατανεμημένη υπηρεσία web για την κατασκευή και τη δοκιμή λογισμικού που χρησιμοποιεί το GitHub ως φιλοξενία πηγαίου κώδικα. Εκτός από τα παραπάνω σενάρια λειτουργίας, μπορείτε να προσθέσετε τα δικά σας χάρη στις εκτεταμένες επιλογές διαμόρφωσης. Σε αυτό το άρθρο θα διαμορφώσουμε το Travis CI ώστε να λειτουργεί με το PVS-Studio χρησιμοποιώντας το παράδειγμα κώδικα PPSSPP.

Εισαγωγή

Travis CI είναι μια διαδικτυακή υπηρεσία για την κατασκευή και τη δοκιμή λογισμικού. Συνήθως χρησιμοποιείται σε συνδυασμό με πρακτικές συνεχούς ολοκλήρωσης.

PPSSPP - Εξομοιωτής κονσόλας παιχνιδιών PSP. Το πρόγραμμα είναι σε θέση να μιμηθεί την εκκίνηση οποιωνδήποτε παιχνιδιών από εικόνες δίσκου που προορίζονται για το Sony PSP. Το πρόγραμμα κυκλοφόρησε την 1η Νοεμβρίου 2012. Το PPSSPP έχει άδεια χρήσης σύμφωνα με την GPL v2. Οποιοσδήποτε μπορεί να κάνει βελτιώσεις σε τον πηγαίο κώδικα του έργου.

PVS-Στούντιο — ένας αναλυτής στατικού κώδικα για την αναζήτηση σφαλμάτων και πιθανών τρωτών σημείων στον κώδικα προγράμματος. Σε αυτό το άρθρο, για μια αλλαγή, θα εκκινήσουμε το PVS-Studio όχι τοπικά στο μηχάνημα του προγραμματιστή, αλλά στο cloud και θα αναζητήσουμε σφάλματα στο PPSSPP.

Ρύθμιση του Travis CI

Θα χρειαστούμε ένα αποθετήριο στο GitHub, όπου βρίσκεται το έργο που χρειαζόμαστε, καθώς και ένα κλειδί για το PVS-Studio (μπορείτε να πάρετε δοκιμαστικό κλειδί ή δωρεάν για έργα ανοιχτού κώδικα).

Πάμε στον ιστότοπο Travis CI. Μετά την εξουσιοδότηση χρησιμοποιώντας τον λογαριασμό σας στο GitHub, θα δούμε μια λίστα αποθετηρίων:

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Για το τεστ, διχαλωσα το PPSSPP.

Ενεργοποιούμε το αποθετήριο που θέλουμε να συλλέξουμε:

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Προς το παρόν, η Travis CI δεν μπορεί να κατασκευάσει το έργο μας επειδή δεν υπάρχουν οδηγίες για την κατασκευή. Ήρθε λοιπόν η ώρα για τη διαμόρφωση.

Κατά τη διάρκεια της ανάλυσης, ορισμένες μεταβλητές θα μας είναι χρήσιμες, για παράδειγμα, το κλειδί για το PVS-Studio, το οποίο δεν θα ήταν επιθυμητό να καθοριστεί στο αρχείο διαμόρφωσης. Ας προσθέσουμε λοιπόν μεταβλητές περιβάλλοντος χρησιμοποιώντας τις ρυθμίσεις κατασκευής στο Travis CI:

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Χρειαζόμαστε:

  • PVS_USERNAME - όνομα χρήστη
  • PVS_KEY - κλειδί
  • MAIL_USER - email που θα χρησιμοποιηθεί για την αποστολή της αναφοράς
  • MAIL_PASSWORD - κωδικός πρόσβασης email

Τα δύο τελευταία είναι προαιρετικά. Αυτά θα χρησιμοποιηθούν για την αποστολή αποτελεσμάτων μέσω ταχυδρομείου. Εάν θέλετε να διανείμετε την αναφορά με άλλο τρόπο, δεν χρειάζεται να τις υποδείξετε.

Έτσι, προσθέσαμε τις μεταβλητές περιβάλλοντος που χρειαζόμαστε:

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Τώρα ας δημιουργήσουμε ένα αρχείο .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, υπάρχουν δύο τρόποι για τη δημιουργία επιλογών κατασκευής: ο πρώτος είναι να ορίσετε μια λίστα μεταγλωττιστών, τύπων λειτουργικών συστημάτων, μεταβλητές περιβάλλοντος κ.λπ., μετά την οποία δημιουργείται μια μήτρα όλων των πιθανών συνδυασμών. το δεύτερο είναι μια ρητή ένδειξη του πίνακα. Φυσικά, μπορείτε να συνδυάσετε αυτές τις δύο προσεγγίσεις και να προσθέσετε μια μοναδική περίπτωση ή, αντίθετα, να την εξαιρέσετε χρησιμοποιώντας την ενότητα αποκλείουν. Μπορείτε να διαβάσετε περισσότερα για αυτό στο Τεκμηρίωση 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 CI.

Για ευκολία στην ανάγνωση, οι εντολές τοποθετήθηκαν σε ξεχωριστό σενάριο .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 αποθηκεύει την αξία Ναι (το υποδείξαμε στην ενότητα env κατά τη διαμόρφωση της μήτρας κατασκευής), εγκαθιστούμε το πακέτο pvs-studio. Εκτός από αυτό, υποδεικνύονται και πακέτα libio-socket-ssl-perl и libnet-ssleay-perl, ωστόσο, απαιτούνται για την αποστολή αποτελεσμάτων, επομένως δεν είναι απαραίτητα εάν έχετε επιλέξει άλλη μέθοδο για την παράδοση της αναφοράς σας.

Λειτουργία download_extract κατεβάζει και αποσυσκευάζει το καθορισμένο αρχείο:

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

Σε αυτήν την ενότητα κώδικα ορίσαμε για κέικ Σημαία για εξαγωγή εντολών μεταγλώττισης. Αυτό είναι απαραίτητο για έναν αναλυτή στατικού κώδικα. Μπορείτε να διαβάσετε περισσότερα για αυτό στο άρθρο "Πώς να εκτελέσετε το PVS-Studio σε Linux και macOS".

Εάν η συναρμολόγηση ήταν επιτυχής, τότε φτάνουμε μετά_επιτυχία, όπου εκτελούμε στατική ανάλυση:

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 ορίζει τον αριθμό των νημάτων για ανάλυση, επισήμανση -μεγάλο δηλώνει άδεια, σημαία -ο ορίζει το αρχείο για την έξοδο των αρχείων καταγραφής και τη σημαία -απενεργοποιήστε τον Έλεγχο Λήξης Άδειας απαιτείται για δοκιμαστικές εκδόσεις, αφού από προεπιλογή pvs-studio-analyzer θα προειδοποιήσει τον χρήστη ότι η άδεια χρήσης πρόκειται να λήξει. Για να μην συμβεί αυτό, μπορείτε να καθορίσετε αυτήν τη σημαία.

Το αρχείο καταγραφής περιέχει πρωτογενή έξοδο που δεν μπορεί να διαβαστεί χωρίς μετατροπή, επομένως πρέπει πρώτα να κάνετε το αρχείο αναγνώσιμο. Ας περάσουμε τα κούτσουρα Plog-μετατροπέας, και η έξοδος είναι ένα αρχείο html.

Σε αυτό το παράδειγμα, αποφάσισα να στείλω αναφορές μέσω ταχυδρομείου χρησιμοποιώντας την εντολή να στείλετε e-mail.

Ως αποτέλεσμα, πήραμε το ακόλουθο αρχείο .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 θα εκτελέσει αυτόματα το build. Κάντε κλικ στο "ppsspp" για να μεταβείτε στις αναφορές κατασκευής:

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Θα δούμε μια επισκόπηση της τρέχουσας κατασκευής:

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP
Εάν η κατασκευή ολοκληρωθεί με επιτυχία, θα λάβουμε ένα email με τα αποτελέσματα της στατικής ανάλυσης. Φυσικά, η αλληλογραφία δεν είναι ο μόνος τρόπος για να λάβετε μια αναφορά. Μπορείτε να επιλέξετε οποιαδήποτε μέθοδο υλοποίησης. Αλλά είναι σημαντικό να θυμάστε ότι μετά την ολοκλήρωση της κατασκευής, δεν θα είναι δυνατή η πρόσβαση στα αρχεία της εικονικής μηχανής.

Σύνοψη σφαλμάτων

Έχουμε ολοκληρώσει με επιτυχία το πιο δύσκολο κομμάτι. Τώρα ας βεβαιωθούμε ότι όλες οι προσπάθειές μας αξίζουν τον κόπο. Ας δούμε μερικά ενδιαφέροντα σημεία από την αναφορά στατικής ανάλυσης που μου ήρθε μέσω ταχυδρομείου (δεν ήταν για τίποτε που το υπέδειξα).

Επικίνδυνη βελτιστοποίηση

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: V597 Ο μεταγλωττιστής θα μπορούσε να διαγράψει την κλήση της συνάρτησης «memset», η οποία χρησιμοποιείται για την έκπλυση του buffer «sum». Η συνάρτηση RtlSecureZeroMemory() θα πρέπει να χρησιμοποιηθεί για τη διαγραφή των ιδιωτικών δεδομένων. sha1.cpp 325

Αυτό το κομμάτι κώδικα βρίσκεται στη μονάδα ασφαλούς κατακερματισμού, ωστόσο, περιέχει ένα σοβαρό ελάττωμα ασφαλείας (CWE-14). Ας δούμε τη λίστα συναρμολόγησης που δημιουργείται κατά τη μεταγλώττιση της έκδοσης Debug:

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

Όλα είναι εντάξει και η λειτουργία υπόμνημα εκτελείται, αντικαθιστώντας έτσι σημαντικά δεδομένα στη μνήμη RAM, ωστόσο, μην χαίρεστε ακόμα. Ας δούμε τη λίστα συναρμολόγησης της έκδοσης έκδοσης με βελτιστοποίηση:

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

Όπως φαίνεται από την καταχώριση, ο μεταγλωττιστής αγνόησε την κλήση υπόμνημα. Αυτό οφείλεται στο γεγονός ότι στη συνάρτηση sha1 μετά την κλήση υπόμνημα όχι άλλη αναφορά στη δομή 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: V547 Η έκφραση 'leftvol >= 0' είναι πάντα αληθής. sceAudio.cpp 120

Δώστε προσοχή στο άλλο κλαδί για το πρώτο if. Ο κώδικας θα εκτελεστεί μόνο εάν όλες οι συνθήκες leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || δεξιά τόμος < 0 θα αποδειχτεί ψευδής. Επομένως, λαμβάνουμε τις ακόλουθες δηλώσεις, οι οποίες θα ισχύουν για τον κλάδο else: leftvol <= 0xFFFF, rightvol <= 0xFFFF, leftvol >= 0 и rightvol >= 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");
  }
  ....
}

V501 Υπάρχουν πανομοιότυπες υπο-εκφράσεις "!Memory::IsValidAddress(psmfData)" στα αριστερά και στα δεξιά του "||" χειριστής. scePsmf.cpp 703

Δώστε προσοχή στον έλεγχο στο εσωτερικό 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: V547 Η έκφραση 'μέγεθος == 8' είναι πάντα ψευδής. syn-att.c 195

Αυτό το σφάλμα βρίσκεται στο φάκελο ext, επομένως δεν σχετίζεται πραγματικά με το έργο, αλλά το σφάλμα βρέθηκε πριν το προσέξω, οπότε αποφάσισα να το αφήσω. Εξάλλου, αυτό το άρθρο δεν αφορά τον έλεγχο σφαλμάτων, αλλά την ενσωμάτωση με το Travis CI και δεν πραγματοποιήθηκε καμία ρύθμιση παραμέτρων του αναλυτή.

Μεταβλητή μέγεθος αρχικοποιείται από μια σταθερά, ωστόσο, δεν χρησιμοποιείται καθόλου στον κώδικα, μέχρι τον τελεστή if, που φυσικά δίνει ψευδής ελέγχοντας τις συνθήκες, γιατί, όπως θυμόμαστε, μέγεθος ίσο με μηδέν. Οι μετέπειτα έλεγχοι επίσης δεν έχουν νόημα.

Προφανώς, ο συγγραφέας του τμήματος κώδικα ξέχασε να αντικαταστήσει τη μεταβλητή μέγεθος πριν από αυτό.

στάση

Εδώ μάλλον θα τελειώσουμε με τα λάθη. Ο σκοπός αυτού του άρθρου είναι να καταδείξει τη δουλειά του PVS-Studio μαζί με τον Travis CI και όχι να αναλύσει το έργο όσο το δυνατόν λεπτομερέστερα. Αν θέλετε μεγαλύτερα και πιο όμορφα λάθη, μπορείτε πάντα να τα θαυμάζετε εδώ :).

Συμπέρασμα

Η χρήση υπηρεσιών web για την κατασκευή έργων μαζί με την πρακτική της σταδιακής ανάλυσης σάς επιτρέπει να βρείτε πολλά προβλήματα αμέσως μετά τη συγχώνευση κώδικα. Ωστόσο, μια κατασκευή μπορεί να μην είναι αρκετή, επομένως η ρύθμιση της δοκιμής μαζί με τη στατική ανάλυση θα βελτιώσει σημαντικά την ποιότητα του κώδικα.

χρήσιμοι σύνδεσμοι

Πώς να διαμορφώσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα ενός εξομοιωτή κονσόλας παιχνιδιών PSP

Εάν θέλετε να μοιραστείτε αυτό το άρθρο με ένα αγγλόφωνο κοινό, χρησιμοποιήστε τον σύνδεσμο μετάφρασης: Maxim Zvyagintsev. Πώς να ρυθμίσετε το PVS-Studio στο Travis CI χρησιμοποιώντας το παράδειγμα του εξομοιωτή κονσόλας παιχνιδιών PSP.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο