Travis CI๋ GitHub๋ฅผ ์์ค ์ฝ๋ ํธ์คํ
์ผ๋ก ์ฌ์ฉํ๋ ์ํํธ์จ์ด๋ฅผ ๊ตฌ์ถํ๊ณ ํ
์คํธํ๊ธฐ ์ํ ๋ถ์ฐ ์น ์๋น์ค์
๋๋ค. ์์ ์ด์ ์๋๋ฆฌ์ค ์ธ์๋ ๊ด๋ฒ์ํ ๊ตฌ์ฑ ์ต์
๋๋ถ์ ์์ ๋ง์ ์๋๋ฆฌ์ค๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ด ๊ธฐ์ฌ์์๋ PPSSPP ์ฝ๋ ์์ ๋ฅผ ์ฌ์ฉํ์ฌ PVS-Studio์ ์๋ํ๋๋ก Travis CI๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
์๊ฐ
ํธ๋๋น์ค CI ์ค์
ํ์ํ ํ๋ก์ ํธ๊ฐ ์๋ GitHub์ ์ ์ฅ์์ PVS-Studio์ฉ ํค๊ฐ ํ์ํฉ๋๋ค.
์ฌ์ดํธ๋ก ๋ค์ด๊ฐ๋ณด์
ํ
์คํธ๋ฅผ ์ํด PPSSPP๋ฅผ ํฌํฌํ์ต๋๋ค.
์์งํ๋ ค๋ ์ ์ฅ์๋ฅผ ํ์ฑํํฉ๋๋ค.
ํ์ฌ Travis CI์๋ ๋น๋ ์ง์นจ์ด ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ ํ๋ก์ ํธ๋ฅผ ๋น๋ํ ์ ์์ต๋๋ค. ์ด์ ๊ตฌ์ฑํ ์ฐจ๋ก์
๋๋ค.
๋ถ์ ์ค์ ์ผ๋ถ ๋ณ์(์: ๊ตฌ์ฑ ํ์ผ์ ์ง์ ํ๋ ๊ฒ์ด ๋ฐ๋์งํ์ง ์์ PVS-Studio์ ํค)๊ฐ ์ ์ฉํฉ๋๋ค. Travis CI์ ๋น๋ ์ค์ ์ ์ฌ์ฉํ์ฌ ํ๊ฒฝ ๋ณ์๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค :
- PVS_USERNAME - ์ฌ์ฉ์ ์ด๋ฆ
- PVS_KEY - ํค
- MAIL_USER - ๋ณด๊ณ ์๋ฅผ ๋ณด๋ด๋ ๋ฐ ์ฌ์ฉ๋๋ ์ด๋ฉ์ผ
- MAIL_PASSWORD - ์ด๋ฉ์ผ ๋น๋ฐ๋ฒํธ
๋ง์ง๋ง ๋ ๊ฐ๋ ์ ํ์ฌํญ์ ๋๋ค. ์ด๋ ๊ฒฐ๊ณผ๋ฅผ ์ฐํธ์ผ๋ก ๋ณด๋ด๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ณด๊ณ ์๋ฅผ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ๋ฐฐํฌํ๋ ค๋ ๊ฒฝ์ฐ ์ด๋ฅผ ํ์ํ ํ์๊ฐ ์์ต๋๋ค.
๋ฐ๋ผ์ ํ์ํ ํ๊ฒฝ ๋ณ์๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
์ด์ ํ์ผ์ ๋ง๋ค์ด๋ณด์ .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์๋ ๋น๋ ์ต์
์ ์์ฑํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ ์ปดํ์ผ๋ฌ, ์ด์ ์ฒด์ ์ ํ, ํ๊ฒฝ ๋ณ์ ๋ฑ์ ๋ชฉ๋ก์ ์ง์ ํ ํ ๊ฐ๋ฅํ ๋ชจ๋ ์กฐํฉ์ ๋งคํธ๋ฆญ์ค๊ฐ ์์ฑ๋๋ ๊ฒ์
๋๋ค. ๋ ๋ฒ์งธ๋ ๋งคํธ๋ฆญ์ค๋ฅผ ๋ช
์์ ์ผ๋ก ํ์ํ๋ ๊ฒ์
๋๋ค. ๋ฌผ๋ก ์ด ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ ๊ฒฐํฉํ์ฌ ๊ณ ์ ํ ์ฌ๋ก๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ๋ฐ๋๋ก ์น์
์ ์ฌ์ฉํ์ฌ ์ ์ธํ ์ ์์ต๋๋ค. ์ ์ธ. ์ด์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ค์์์ ์ฝ์ ์ ์์ต๋๋ค.
๋จ์ ๊ฒ์ ํ๋ก์ ํธ๋ณ ์กฐ๋ฆฝ ์ง์นจ์ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค.
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.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
}
์ด์ Travis CI์์ PVS-Studio ์๋ ์คํ์ ์ง์ ์ค์ ํ๊ฒ ์ต๋๋ค. ๋จผ์ ์์คํ ์ 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 ๊ฐ์น๋ฅผ ์ ์ฅํ๋ค ๊ฐ๋ฅ (์น์ ์ ํ์ํ์ต๋๋ค. ํ๊ฒฝ ๋น๋ ๋งคํธ๋ฆญ์ค ๊ตฌ์ฑ ์ค) ํจํค์ง๋ฅผ ์ค์นํฉ๋๋ค. pvs-์คํ๋์ค. ์ด ์ธ์๋ ํจํค์ง๋ ํ์๋์ด ์์ต๋๋ค. libio-์์ผ-ssl-perl ะธ libnet-ssleay-perl๊ทธ๋ฌ๋ ๊ฒฐ๊ณผ๋ฅผ ์ฐํธ์ผ๋ก ๋ณด๋ด๋ ๋ฐ ํ์ํ๋ฏ๋ก ๋ณด๊ณ ์ ์ ๋ฌ์ ์ํด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ ํํ ๊ฒฝ์ฐ์๋ ํ์ํ์ง ์์ต๋๋ค.
๊ธฐ๋ฅ ๋ค์ด๋ก๋_์ถ์ถ ์ง์ ๋ ์์นด์ด๋ธ๋ฅผ ๋ค์ด๋ก๋ํ๊ณ ์์ถ์ ํผ๋ค:
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
์ด ์ฝ๋ ์น์
์์๋ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ์ต๋๋ค. cmake ์ปดํ์ผ ๋ช
๋ น์ ๋ด๋ณด๋ด๊ธฐ ์ํ ํ๋๊ทธ์
๋๋ค. ์ด๋ ์ ์ ์ฝ๋ ๋ถ์๊ธฐ์ ํ์ํฉ๋๋ค. ์ด์ ๋ํ ์์ธํ ๋ด์ฉ์ "
์กฐ๋ฆฝ์ด ์ฑ๊ณตํ๋ค๋ฉด ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋๋ค. ์ฑ๊ณต ํ, ์ฌ๊ธฐ์ ์ ์ ๋ถ์์ ์ํํฉ๋๋ค.
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 ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ ๋ ๋งจ ์ฒ์์ ์ง์ ํ ์ฌ์ฉ์ ์ด๋ฆ๊ณผ ํค์์ ๋ผ์ด์ผ์ค ํ์ผ์ ์์ฑํฉ๋๋ค.
๋ ๋ฒ์งธ ์ค์์๋ ๋ถ์์ ์ง์ ์์ํฉ๋๋ค. ๊น๋ฐ -์ ์ด ๋ถ์ํ ์ค๋ ๋ ์๋ฅผ ์ค์ ํ๊ณ ํ๋๊ทธ๋ฅผ ์ง์ ํฉ๋๋ค. -์ ๋ผ์ด์ผ์ค, ํ๋๊ทธ๋ฅผ ๋ํ๋ ๋๋ค. -์ํ ๋ก๊ทธ ์ถ๋ ฅ์ ์ํ ํ์ผ๊ณผ ํ๋๊ทธ๋ฅผ ์ ์ํฉ๋๋ค. -disableLicenseExpirationCheck ํ๊ฐํ์๋ ํ์์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก pvs-์คํ๋์ค-๋ถ์๊ธฐ ๋ผ์ด์ผ์ค๊ฐ ๊ณง ๋ง๋ฃ๋ ๊ฒ์์ ์ฌ์ฉ์์๊ฒ ๊ฒฝ๊ณ ํฉ๋๋ค. ์ด๋ฐ ์ผ์ด ๋ฐ์ํ์ง ์๋๋ก ํ๋ ค๋ฉด ์ด ํ๋๊ทธ๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
๋ก๊ทธ ํ์ผ์๋ ๋ณํ ์์ด๋ ์ฝ์ ์ ์๋ ์์ ์ถ๋ ฅ์ด ํฌํจ๋์ด ์์ผ๋ฏ๋ก ๋จผ์ ํ์ผ์ ์ฝ์ ์ ์๋๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ๋ก๊ทธ๋ฅผ ์ ๋ฌํด ๋ณด๊ฒ ์ต๋๋ค. ํ๋ก๊ทธ ๋ณํ๊ธฐ์ด๋ฉฐ ์ถ๋ ฅ์ html ํ์ผ์ ๋๋ค.
์ด ์์์๋ ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๋ณด๊ณ ์๋ฅผ ๋ฉ์ผ๋ก ๋ณด๋ด๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์ด๋ฉ์ผ์ ๋ณด๋ด.
๊ทธ ๊ฒฐ๊ณผ ์๋์ ๊ฐ์ ํ์ผ์ ์ป์์ต๋๋ค. .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๊ฐ ์๋์ผ๋ก ๋น๋๋ฅผ ์คํํฉ๋๋ค. ๋น๋ ๋ณด๊ณ ์๋ก ์ด๋ํ๋ ค๋ฉด "ppsspp"๋ฅผ ํด๋ฆญํ์ธ์.
ํ์ฌ ๋น๋์ ๊ฐ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋น๋๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋๋ฉด ์ ์ ๋ถ์ ๊ฒฐ๊ณผ๊ฐ ํฌํจ๋ ์ด๋ฉ์ผ์ ๋ฐ๊ฒ ๋ฉ๋๋ค. ๋ฌผ๋ก ์ฐํธ์ผ๋ก ๋ณด๊ณ ์๋ฅผ ๋ฐ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ์๋๋๋ค. ๊ตฌํ ๋ฐฉ๋ฒ์ ์ ํํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋น๋๊ฐ ์๋ฃ๋ ํ์๋ ๊ฐ์ ๋จธ์ ํ์ผ์ ์ก์ธ์คํ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ค๋ฅ ์์ฝ
์ฐ๋ฆฌ๋ ๊ฐ์ฅ ์ด๋ ค์ด ๋ถ๋ถ์ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃํ์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ์ ๋ชจ๋ ๋ ธ๋ ฅ์ด ๊ทธ๋งํ ๊ฐ์น๊ฐ ์๋์ง ํ์ธํฉ์๋ค. ๋ฉ์ผ๋ก ๋ฐ์ ์ ์ ๋ถ์ ๋ณด๊ณ ์์์ ๋ช ๊ฐ์ง ํฅ๋ฏธ๋ก์ด ์ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค(๊ดํ ํ์ํ ๊ฒ์ด ์๋๋๋ค).
์ํํ ์ต์ ํ
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 ๊ฒฝ๊ณ :
์ด ์ฝ๋ ์กฐ๊ฐ์ ๋ณด์ ํด์ฑ ๋ชจ๋์ ์์ง๋ง ์ฌ๊ฐํ ๋ณด์ ๊ฒฐํจ(
; 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. ๋ฐ๋ผ์ ์ปดํ์ผ๋ฌ๋ ๋์ค์ ์ฌ์ฉ๋์ง ์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฎ์ด์ฐ๋ฉด์ ํ๋ก์ธ์ ์๊ฐ์ ๋ญ๋นํ๋ ๊ฒ์ ์๋ฏธํ์ง ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค. RtlSecureZero๋ฉ๋ชจ๋ฆฌ ๋๋
์ฌ๋ฐ๋ฅด๊ฒ :
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 ๊ฒฝ๊ณ :
๋จผ์ else ๋ถ๊ธฐ์ ์ฃผ๋ชฉํ์ธ์. if. ๋ชจ๋ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๊ฒฝ์ฐ์๋ง ์ฝ๋๊ฐ ์คํ๋ฉ๋๋ค. leftvol > 0xFFFF || ์ค๋ฅธ์ชฝ๋ณผ > 0xFFFF || leftvol < 0 || ์ค๋ฅธ์ชฝ ๋ณผ๋ฅจ < 0 ๊ฑฐ์ง์ผ๋ก ๋ฐํ์ง๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ else ๋ถ๊ธฐ์ ์ ์ฉ๋๋ ๋ค์ ๋ช ๋ น๋ฌธ์ ์ป์ต๋๋ค. ์ผ์ชฝ๋ณผ <= 0xFFFF, ์ค๋ฅธ์ชฝ๋ณผ <= 0xFFFF, ์ผ์ชฝ ๋ณผ๋ฅจ >= 0 ะธ ์ค๋ฅธ์ชฝ ๋ณผ๋ฅจ >= 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");
}
....
}
๋ด๋ถ ์ํ์์ฃผ์ํ์ญ์์ค if. ์ฃผ์๊ฐ ์ ํจํ์ง ํ์ธํ๋ ๊ฒ์ด ์ด์ํ๋ค๊ณ ์๊ฐํ์ง ์๋์? psmf๋ฐ์ดํฐ, ๋ ๋ฐฐ? ๊ทธ๋์ ์ ๊ฒ๋ ์ด์ํ๊ฒ ๋ณด์ ๋๋ค... ์ฌ์ค ์ด๊ฒ์ ๋ฌผ๋ก ์คํ์ด๋ฉฐ ๋ ์ ๋ ฅ ๋งค๊ฐ๋ณ์๋ฅผ ๋ชจ๋ ํ์ธํ๋ ค๋ ์์ด๋์ด์์ต๋๋ค.
์ฌ๋ฐ๋ฅธ ์ต์ :
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 ๊ฒฝ๊ณ :
์ด ์ค๋ฅ๋ ํด๋์ ์์ต๋๋ค ๋ด์ , ๊ทธ๋์ ํ๋ก์ ํธ์ ๋ณ๋ก ๊ด๋ จ์ด ์์ง๋ง, ๋ฒ๊ทธ๊ฐ ์ ๊ฐ ๊นจ๋ซ๊ธฐ๋ ์ ์ ๋ฐ๊ฒฌ๋์๊ธฐ ๋๋ฌธ์ ๋ ๋๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ๊ฒฐ๊ตญ ์ด ๊ธ์ ์ค๋ฅ ๊ฒํ ์ ๊ดํ ๊ฒ์ด ์๋๋ผ Travis CI์์ ํตํฉ์ ๊ดํ ๊ฒ์ด๋ฉฐ ๋ถ์๊ธฐ ๊ตฌ์ฑ์ ์ํ๋์ง ์์์ต๋๋ค.
๋ณ์ ํฌ๊ธฐ ์์๋ก ์ด๊ธฐํ๋์ง๋ง ์ฝ๋์์ ์ฐ์ฐ์๊น์ง ์ ํ ์ฌ์ฉ๋์ง ์์ต๋๋ค. if, ๋ฌผ๋ก ์ด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๊ทธ๋ฆ๋ ์กฐ๊ฑด์ ํ์ธํ๋ ๋์ ์ฐ๋ฆฌ๊ฐ ๊ธฐ์ตํ๋ ๊ฒ์ฒ๋ผ ํฌ๊ธฐ XNUMX๊ณผ ๊ฐ์ต๋๋ค. ํ์ ์ ๊ฒ๋ ์๋ฏธ๊ฐ ์์ต๋๋ค.
๋ถ๋ช ํ ์ฝ๋ ์กฐ๊ฐ ์์ฑ์๊ฐ ๋ณ์๋ฅผ ๋ฎ์ด์ฐ๋ ๊ฒ์ ์์์ต๋๋ค. ํฌ๊ธฐ ๊ทธ๊ฒ ์์.
์ค์ง
์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ ์๋ง๋ ์ค์๋ก ๋๋ ๊ฒ์
๋๋ค. ์ด ๊ธ์ ๋ชฉ์ ์ Travis CI์ ํจ๊ป PVS-Studio์ ์์
์ ์์ฐํ๋ ๊ฒ์ด์ง ํ๋ก์ ํธ๋ฅผ ์ต๋ํ ์ฒ ์ ํ๊ฒ ๋ถ์ํ๋ ๊ฒ์ด ์๋๋๋ค. ๋ ํฌ๊ณ ์๋ฆ๋ค์ด ์ค์๋ฅผ ์ํ๋ค๋ฉด ์ธ์ ๋ ์ง ๊ฐํํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก
์น ์๋น์ค๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๊ณ ์ฆ๋ถ ๋ถ์์ ์ํํ๋ฉด ์ฝ๋ ๋ณํฉ ํ ์ฆ์ ๋ง์ ๋ฌธ์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํ๋์ ๋น๋๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ ์์ผ๋ฏ๋ก ์ ์ ๋ถ์๊ณผ ํจ๊ป ํ ์คํธ๋ฅผ ์ค์ ํ๋ฉด ์ฝ๋ ํ์ง์ด ํฌ๊ฒ ํฅ์๋ฉ๋๋ค.
์ ์ฉํ ๋งํฌ
์ด ๊ธฐ์ฌ๋ฅผ ์์ด๊ถ ์ฒญ์ค๊ณผ ๊ณต์ ํ๋ ค๋ฉด ๋ฒ์ญ ๋งํฌ์ธ Maxim Zvyagintsev๋ฅผ ์ฌ์ฉํ์ญ์์ค.
์ถ์ฒ : habr.com