ProHoster > Blog > administración > Cómo configurar PVS-Studio en Travis CI usando el ejemplo de un emulador de consola de juegos PSP
Cómo configurar PVS-Studio en Travis CI usando el ejemplo de un emulador de consola de juegos PSP
Travis CI es un servicio web distribuido para crear y probar software que utiliza GitHub como alojamiento de código fuente. Además de los escenarios operativos anteriores, puede agregar los suyos propios gracias a las amplias opciones de configuración. En este artículo configuraremos Travis CI para que funcione con PVS-Studio usando el ejemplo de código PPSSPP.
introducción
Travis CI es un servicio web para construir y probar software. Generalmente se utiliza junto con prácticas de integración continua.
PPSSPP - Emulador de consola de juegos PSP. El programa puede emular el lanzamiento de cualquier juego a partir de imágenes de disco destinadas a Sony PSP. El programa fue lanzado el 1 de noviembre de 2012. PPSSPP tiene licencia GPL v2. Cualquiera puede realizar mejoras en código fuente del proyecto.
PVS-Estudio — un analizador de código estático para buscar errores y posibles vulnerabilidades en el código del programa. En este artículo, para variar, iniciaremos PVS-Studio no localmente en la máquina del desarrollador, sino en la nube, y buscaremos errores en PPSSPP.
vamos al sitio Travis CI. Después de la autorización usando su cuenta de GitHub, veremos una lista de repositorios:
Para la prueba, bifurqué PPSSPP.
Activamos el repositorio que queremos recopilar:
Por el momento, Travis CI no puede construir nuestro proyecto porque no hay instrucciones para construirlo. Entonces es hora de la configuración.
Durante el análisis, algunas variables nos serán útiles, por ejemplo, la clave para PVS-Studio, que no sería deseable especificar en el archivo de configuración. Entonces, agreguemos variables de entorno usando la configuración de compilación en Travis CI:
Necesitamos:
PVS_USERNAME - nombre de usuario
PVS_KEY - clave
MAIL_USER: correo electrónico que se utilizará para enviar el informe
MAIL_PASSWORD - contraseña de correo electrónico
Los dos últimos son opcionales. Estos se utilizarán para enviar los resultados por correo. Si desea distribuir el informe de otra forma no es necesario que las indique.
Entonces, hemos agregado las variables de entorno que necesitamos:
Ahora creemos un archivo. .travis.yml y colóquelo en la raíz del proyecto. PPSSPP ya tenía un archivo de configuración para Travis CI, sin embargo, era demasiado grande y completamente inadecuado para el ejemplo, por lo que tuvimos que simplificarlo mucho y dejar solo los elementos básicos.
Primero indiquemos el idioma, la versión de Ubuntu Linux que queremos usar en la máquina virtual y los paquetes necesarios para la compilación:
Todos los paquetes enumerados son necesarios exclusivamente para PPSSPP.
Ahora indicamos la matriz de montaje:
matrix:
include:
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
Un poco más sobre la sección. matriz. En Travis CI, hay dos formas de crear opciones de compilación: la primera es especificar una lista de compiladores, tipos de sistemas operativos, variables de entorno, etc., después de lo cual se genera una matriz de todas las combinaciones posibles; el segundo es una indicación explícita de la matriz. Por supuesto, puedes combinar estos dos enfoques y agregar un caso único o, por el contrario, excluirlo usando la sección excluir. Puedes leer más sobre esto en Documentación de Travis CI.
Sólo queda proporcionar instrucciones de montaje específicas del proyecto:
Travis CI le permite agregar sus propios comandos para varias etapas de la vida de una máquina virtual. Sección antes_instalar ejecutado antes de instalar los paquetes. Entonces instalar, que sigue a la instalación de paquetes de la lista complementos.aptque indicamos anteriormente. La asamblea en sí se lleva a cabo en guión. Si todo ha ido bien, entonces nos encontraremos en después_éxito (Es en esta sección donde ejecutaremos el análisis estático). Estos no son todos los pasos que se pueden modificar, si necesita más, entonces debe buscar en Documentación de Travis CI.
Para facilitar la lectura, los comandos se colocaron en un guión separado. .travis.sh, que se coloca en la raíz del proyecto.
Entonces tenemos el siguiente archivo .travis.yml:
Antes de instalar los paquetes, actualizaremos los submódulos. Esto es necesario para construir PPSSPP. Agreguemos la primera función a .travis.sh (tenga en cuenta la extensión):
Ahora pasamos directamente a configurar el inicio automático de PVS-Studio en Travis CI. Primero necesitamos instalar el paquete PVS-Studio en el sistema:
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
}
Al comienzo de la función. instalación_travis Instalamos los compiladores que necesitamos usando variables de entorno. Entonces si la variable $PVS_ANALYZE almacena valor Sí (lo indicamos en el apartado env durante la configuración de la matriz de compilación), instalamos el paquete pvs-estudio. Además de esto, también se indican los paquetes. libio-socket-ssl-perl и libnet-ssleay-perl, sin embargo, son necesarios para enviar los resultados por correo, por lo que no son necesarios si ha elegido otro método para entregar su informe.
Función descargar_extraer descarga y descomprime el archivo especificado:
Es hora de armar el proyecto. Esto sucede en la sección guión:
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
}
De hecho, esta es una configuración original simplificada, excepto por estas líneas:
if [ "$PVS_ANALYZE" = "Yes" ]; then
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi
En esta sección de código configuramos para cmake bandera para exportar comandos de compilación. Esto es necesario para un analizador de código estático. Puedes leer más sobre esto en el artículo “Cómo ejecutar PVS-Studio en Linux y macOS«.
Si la asamblea fue exitosa, entonces llegamos a después_éxito, donde realizamos análisis estático:
La primera línea genera un archivo de licencia a partir del nombre de usuario y la clave que especificamos al principio al configurar las variables de entorno de Travis CI.
La segunda línea inicia el análisis directamente. Bandera -j establece el número de subprocesos para el análisis, marca -l indica licencia, bandera -o define el archivo para generar registros y la bandera -disableLicenseExpirationCheck requerido para las versiones de prueba, ya que por defecto analizador-pvs-studio Advertirá al usuario que la licencia está a punto de caducar. Para evitar que esto suceda, puede especificar esta bandera.
El archivo de registro contiene resultados sin procesar que no se pueden leer sin conversión, por lo que primero debe hacer que el archivo sea legible. Pasemos los registros. convertidor-plog, y el resultado es un archivo html.
En este ejemplo, decidí enviar informes por correo usando el comando enviar correo electrónico.
Como resultado, obtuvimos el siguiente archivo .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;
Ahora es el momento de enviar los cambios al repositorio de git, después de lo cual Travis CI ejecutará automáticamente la compilación. Haga clic en "ppsspp" para ir a los informes de compilación:
Veremos una descripción general de la compilación actual:
Si la compilación se completa con éxito, recibiremos un correo electrónico con los resultados del análisis estático. Por supuesto, el envío por correo no es la única forma de recibir un informe. Puede elegir cualquier método de implementación. Pero es importante recordar que una vez completada la compilación, no será posible acceder a los archivos de la máquina virtual.
Resumen de errores
Hemos completado con éxito la parte más difícil. Ahora asegurémonos de que todos nuestros esfuerzos valgan la pena. Veamos algunos puntos interesantes del informe de análisis estático que me llegó por correo (no en vano lo indiqué).
Advertencia de PVS-Studio: V597 El compilador podría eliminar la llamada a la función 'memset', que se utiliza para vaciar el búfer de 'suma'. La función RtlSecureZeroMemory() debe usarse para borrar los datos privados. sha1.cpp 325
Este fragmento de código se encuentra en el módulo de hash seguro; sin embargo, contiene una falla de seguridad grave (CWE-14). Veamos el listado del ensamblado que se genera al compilar la versión de depuración:
; Line 355
mov r8d, 20
xor edx, edx
lea rcx, QWORD PTR sum$[rsp]
call memset
; Line 356
Todo está en orden y en funcionamiento. conjunto de miembros se ejecuta, sobrescribiendo así datos importantes en la RAM, pero no se regocije todavía. Veamos el listado de ensamblaje de la versión de lanzamiento con optimización:
Como puede verse en el listado, el compilador ignoró la llamada. conjunto de miembros. Esto se debe a que en la función sha1 después de la llamada conjunto de miembros no más referencia a la estructura ctx. Por lo tanto, el compilador no ve ningún sentido en perder tiempo del procesador sobrescribiendo memoria que no se utilizará en el futuro. Puedes solucionar este problema usando la función RtlSecureZeroMemoria o similar a ella
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);
}
}
Advertencia de PVS-Studio: V547 La expresión 'leftvol >= 0' siempre es verdadera. sceAudio.cpp 120
Preste atención a la rama else por primera vez. if. El código se ejecutará solo si se cumplen todas las condiciones. volizquierdo > 0xFFFF || volderecho > 0xFFFF || volizquierdo < 0 || volderecho < 0 resultará falso. Por lo tanto, obtenemos las siguientes afirmaciones, que serán válidas para la rama else: vol izquierdo <= 0xFFFF, volderecho <= 0xFFFF, volizquierdo >= 0 и volderecho >= 0. Observe las dos últimas declaraciones. ¿Tiene sentido comprobar cuál es la condición necesaria para la ejecución de este fragmento de código?
Entonces podemos eliminar de forma segura estas declaraciones condicionales:
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);
}
}
Otro escenario. Hay algún tipo de error escondido detrás de estas condiciones redundantes. Quizás no comprobaron lo que se requería.
V501 Hay subexpresiones idénticas '!Memory::IsValidAddress(psmfData)' a la izquierda y a la derecha de '||' operador. scePsmf.cpp 703
Presta atención al cheque en el interior. if. ¿No te parece extraño que comprobemos si la dirección es válida? psmfDatos, ¿el doble? Entonces esto me parece extraño... De hecho, esto es, por supuesto, un error tipográfico, y la idea era verificar ambos parámetros de entrada.
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");
}
....
}
Advertencia de PVS-Studio: V547 La expresión 'tamaño == 8' siempre es falsa. syn-att.c 195
Este error se encuentra en la carpeta. ext, por lo que no es realmente relevante para el proyecto, pero el error se encontró antes de que me diera cuenta, así que decidí dejarlo. Después de todo, este artículo no trata sobre la revisión de errores, sino sobre la integración con Travis CI, y no se realizó ninguna configuración del analizador.
Variable tamaño se inicializa mediante una constante, sin embargo, no se utiliza en absoluto en el código, hasta el operador if, lo que, por supuesto, da false mientras comprobamos las condiciones, porque, como recordamos, tamaño igual a cero. Los controles posteriores tampoco tienen sentido.
Aparentemente, el autor del fragmento de código olvidó sobrescribir la variable. tamaño antes de que.
Detener
Aquí es donde probablemente terminaremos con los errores. El propósito de este artículo es demostrar el trabajo de PVS-Studio junto con Travis CI y no analizar el proyecto lo más a fondo posible. Si quieres errores más grandes y bellos, siempre podrás admirarlos. aquí :).
Conclusión
El uso de servicios web para crear proyectos junto con la práctica del análisis incremental le permite encontrar muchos problemas inmediatamente después de fusionar el código. Sin embargo, una compilación puede no ser suficiente, por lo que configurar las pruebas junto con el análisis estático mejorará significativamente la calidad del código.