Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
This is the list of currently configured Coverity components:
|
||||
|
||||
alpha
|
||||
~ .*/qemu((/include)?/hw/alpha/.*|/target/alpha/.*)
|
||||
|
||||
arm
|
||||
~ .*/qemu((/include)?/hw/arm/.*|(/include)?/hw/.*/(arm|allwinner-a10|bcm28|digic|exynos|imx|omap|stellaris|pxa2xx|versatile|zynq|cadence).*|/hw/ssi/xilinx_spips.c|/target/arm/.*)
|
||||
|
||||
avr
|
||||
~ .*/qemu((/include)?/hw/avr/.*|/target/avr/.*)
|
||||
|
||||
hexagon-gen (component should be ignored in analysis)
|
||||
~ .*/qemu(/target/hexagon/.*generated.*)
|
||||
|
||||
hexagon
|
||||
~ .*/qemu(/target/hexagon/.*)
|
||||
|
||||
hppa
|
||||
~ .*/qemu((/include)?/hw/hppa/.*|/target/hppa/.*)
|
||||
|
||||
i386
|
||||
~ .*/qemu((/include)?/hw/i386/.*|/target/i386/.*|/hw/intc/[^/]*apic[^/]*\.c)
|
||||
|
||||
loongarch
|
||||
~ .*/qemu((/include)?/hw/(loongarch/.*|.*/loongarch.*)|/target/loongarch/.*)
|
||||
|
||||
m68k
|
||||
~ .*/qemu((/include)?/hw/m68k/.*|/target/m68k/.*|(/include)?/hw(/.*)?/mcf.*|(/include)?/hw/nubus/.*)
|
||||
|
||||
microblaze
|
||||
~ .*/qemu((/include)?/hw/microblaze/.*|/target/microblaze/.*)
|
||||
|
||||
mips
|
||||
~ .*/qemu((/include)?/hw/mips/.*|/target/mips/.*)
|
||||
|
||||
openrisc
|
||||
~ .*/qemu((/include)?/hw/openrisc/.*|/target/openrisc/.*)
|
||||
|
||||
ppc
|
||||
~ .*/qemu((/include)?/hw/ppc/.*|/target/ppc/.*|/hw/pci-host/(uninorth.*|dec.*|prep.*|ppc.*)|/hw/misc/macio/.*|(/include)?/hw/.*/(xics|openpic|spapr).*)
|
||||
|
||||
riscv
|
||||
~ .*/qemu((/include)?/hw/riscv/.*|/target/riscv/.*|/hw/.*/(riscv_|ibex_|sifive_).*)
|
||||
|
||||
rx
|
||||
~ .*/qemu((/include)?/hw/rx/.*|/target/rx/.*)
|
||||
|
||||
s390
|
||||
~ .*/qemu((/include)?/hw/s390x/.*|/target/s390x/.*|/hw/.*/s390_.*)
|
||||
|
||||
sh4
|
||||
~ .*/qemu((/include)?/hw/sh4/.*|/target/sh4/.*)
|
||||
|
||||
sparc
|
||||
~ .*/qemu((/include)?/hw/sparc(64)?.*|/target/sparc/.*|/hw/.*/grlib.*|/hw/display/cg3.c)
|
||||
|
||||
tricore
|
||||
~ .*/qemu((/include)?/hw/tricore/.*|/target/tricore/.*)
|
||||
|
||||
xtensa
|
||||
~ .*/qemu((/include)?/hw/xtensa/.*|/target/xtensa/.*)
|
||||
|
||||
9pfs
|
||||
~ .*/qemu(/hw/9pfs/.*|/fsdev/.*)
|
||||
|
||||
audio
|
||||
~ .*/qemu((/include)?/(audio|hw/audio)/.*)
|
||||
|
||||
block
|
||||
~ .*/qemu(/block.*|(/include?)/(block|storage-daemon)/.*|(/include)?/hw/(block|ide|nvme)/.*|/qemu-(img|io).*|/util/(aio|async|thread-pool).*)
|
||||
|
||||
char
|
||||
~ .*/qemu((/include)?/hw/char/.*)
|
||||
|
||||
chardev
|
||||
~ .*/qemu((/include)?/chardev/.*)
|
||||
|
||||
crypto
|
||||
~ .*/qemu((/include)?/crypto/.*|/hw/.*/.*crypto.*|(/include/system|/backends)/cryptodev.*|/host/include/.*/host/crypto/.*)
|
||||
|
||||
disas
|
||||
~ .*/qemu((/include)?/disas.*)
|
||||
|
||||
fpu
|
||||
~ .*/qemu((/include)?(/fpu|/libdecnumber)/.*)
|
||||
|
||||
io
|
||||
~ .*/qemu((/include)?/io/.*)
|
||||
|
||||
ipmi
|
||||
~ .*/qemu((/include)?/hw/ipmi/.*)
|
||||
|
||||
migration
|
||||
~ .*/qemu((/include)?/migration/.*)
|
||||
|
||||
monitor
|
||||
~ .*/qemu((/include)?/(qapi|qobject|monitor)/.*|/job-qmp.c)
|
||||
|
||||
nbd
|
||||
~ .*/qemu(/nbd/.*|/include/block/nbd.*|/qemu-nbd\.c)
|
||||
|
||||
net
|
||||
~ .*/qemu((/include)?(/hw)?/(net|rdma)/.*)
|
||||
|
||||
pci
|
||||
~ .*/qemu(/include)?/hw/(cxl/|pci).*
|
||||
|
||||
qemu-ga
|
||||
~ .*/qemu(/qga/.*)
|
||||
|
||||
scsi
|
||||
~ .*/qemu(/scsi/.*|/hw/scsi/.*|/include/hw/scsi/.*)
|
||||
|
||||
trace
|
||||
~ .*/qemu(/.*trace.*\.[ch])
|
||||
|
||||
ui
|
||||
~ .*/qemu((/include)?(/ui|/hw/display|/hw/input)/.*)
|
||||
|
||||
usb
|
||||
~ .*/qemu(/hw/usb/.*|/include/hw/usb/.*)
|
||||
|
||||
user
|
||||
~ .*/qemu(/linux-user/.*|/bsd-user/.*|/user-exec\.c|/thunk\.c|/include/user/.*)
|
||||
|
||||
util
|
||||
~ .*/qemu(/util/.*|/include/qemu/.*)
|
||||
|
||||
vfio
|
||||
~ .*/qemu(/include)?/hw/vfio/.*
|
||||
|
||||
virtio
|
||||
~ .*/qemu(/include)?/hw/virtio/.*
|
||||
|
||||
xen
|
||||
~ .*/qemu(.*/xen.*)
|
||||
|
||||
hvf
|
||||
~ .*/qemu(.*/hvf.*)
|
||||
|
||||
kvm
|
||||
~ .*/qemu(.*/kvm.*)
|
||||
|
||||
tcg
|
||||
~ .*/qemu(/accel/tcg|/replay|/tcg)/.*
|
||||
|
||||
system
|
||||
~ .*/qemu(/system/.*|/accel/.*)
|
||||
|
||||
plugins
|
||||
~ .*/qemu(/contrib|/tests/tcg)?/plugins/.*
|
||||
|
||||
(headers)
|
||||
~ .*/qemu(/include/.*)
|
||||
|
||||
testlibs
|
||||
~ .*/qemu(/tests/qtest(/libqos/.*|/libqtest.*|/libqmp.*))
|
||||
|
||||
tests
|
||||
~ .*/qemu(/tests/.*)
|
||||
@@ -0,0 +1,166 @@
|
||||
# syntax=docker/dockerfile:1.0.0-experimental
|
||||
#
|
||||
# Docker setup for running the "Coverity Scan" tools over the source
|
||||
# tree and uploading them to the website, as per
|
||||
# https://scan.coverity.com/projects/qemu/builds/new
|
||||
# We do this on a fixed config (currently Fedora 30 with a known
|
||||
# set of dependencies and a configure command that enables a specific
|
||||
# set of options) so that random changes don't result in our accidentally
|
||||
# dropping some files from the scan.
|
||||
#
|
||||
# We don't build on top of the fedora.docker file because we don't
|
||||
# want to accidentally change or break the scan config when that
|
||||
# is updated.
|
||||
|
||||
# The work of actually doing the build is handled by the
|
||||
# run-coverity-scan script.
|
||||
|
||||
FROM registry.fedoraproject.org/fedora:37
|
||||
|
||||
RUN dnf install -y nosync && \
|
||||
echo -e '#!/bin/sh\n\
|
||||
if test -d /usr/lib64\n\
|
||||
then\n\
|
||||
export LD_PRELOAD=/usr/lib64/nosync/nosync.so\n\
|
||||
else\n\
|
||||
export LD_PRELOAD=/usr/lib/nosync/nosync.so\n\
|
||||
fi\n\
|
||||
exec "$@"' > /usr/bin/nosync && \
|
||||
chmod +x /usr/bin/nosync && \
|
||||
nosync dnf update -y && \
|
||||
nosync dnf install -y \
|
||||
SDL2-devel \
|
||||
SDL2_image-devel \
|
||||
alsa-lib-devel \
|
||||
bash \
|
||||
bc \
|
||||
bison \
|
||||
brlapi-devel \
|
||||
bzip2 \
|
||||
bzip2-devel \
|
||||
ca-certificates \
|
||||
capstone-devel \
|
||||
ccache \
|
||||
clang \
|
||||
ctags \
|
||||
cyrus-sasl-devel \
|
||||
daxctl-devel \
|
||||
dbus-daemon \
|
||||
device-mapper-multipath-devel \
|
||||
diffutils \
|
||||
findutils \
|
||||
flex \
|
||||
fuse3-devel \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
gcovr \
|
||||
genisoimage \
|
||||
gettext \
|
||||
git \
|
||||
glib2-devel \
|
||||
glib2-static \
|
||||
glibc-langpack-en \
|
||||
glibc-static \
|
||||
gnutls-devel \
|
||||
gtk3-devel \
|
||||
hostname \
|
||||
jemalloc-devel \
|
||||
json-c-devel \
|
||||
libaio-devel \
|
||||
libasan \
|
||||
libattr-devel \
|
||||
libbpf-devel \
|
||||
libcacard-devel \
|
||||
libcap-ng-devel \
|
||||
libcmocka-devel \
|
||||
libcurl-devel \
|
||||
libdrm-devel \
|
||||
libepoxy-devel \
|
||||
libfdt-devel \
|
||||
libffi-devel \
|
||||
libgcrypt-devel \
|
||||
libiscsi-devel \
|
||||
libjpeg-devel \
|
||||
libnfs-devel \
|
||||
libpmem-devel \
|
||||
libpng-devel \
|
||||
librbd-devel \
|
||||
libseccomp-devel \
|
||||
libselinux-devel \
|
||||
libslirp-devel \
|
||||
libssh-devel \
|
||||
libtasn1-devel \
|
||||
libubsan \
|
||||
liburing-devel \
|
||||
libusbx-devel \
|
||||
libzstd-devel \
|
||||
llvm \
|
||||
lttng-ust-devel \
|
||||
lzo-devel \
|
||||
make \
|
||||
mesa-libgbm-devel \
|
||||
meson \
|
||||
ncurses-devel \
|
||||
nettle-devel \
|
||||
ninja-build \
|
||||
nmap-ncat \
|
||||
numactl-devel \
|
||||
openssh-clients \
|
||||
pam-devel \
|
||||
pcre-static \
|
||||
pixman-devel \
|
||||
pkgconfig \
|
||||
pulseaudio-libs-devel \
|
||||
python3 \
|
||||
python3-PyYAML \
|
||||
python3-numpy \
|
||||
python3-opencv \
|
||||
python3-pillow \
|
||||
python3-pip \
|
||||
python3-sphinx \
|
||||
python3-sphinx_rtd_theme \
|
||||
rdma-core-devel \
|
||||
rpm \
|
||||
sed \
|
||||
snappy-devel \
|
||||
socat \
|
||||
sparse \
|
||||
spice-protocol \
|
||||
spice-server-devel \
|
||||
systemd-devel \
|
||||
systemtap-sdt-devel \
|
||||
tar \
|
||||
tesseract \
|
||||
tesseract-langpack-eng \
|
||||
usbredir-devel \
|
||||
util-linux \
|
||||
virglrenderer-devel \
|
||||
vte291-devel \
|
||||
which \
|
||||
xen-devel \
|
||||
xfsprogs-devel \
|
||||
zlib-devel \
|
||||
zlib-static \
|
||||
zstd && \
|
||||
nosync dnf autoremove -y && \
|
||||
nosync dnf clean all -y && \
|
||||
rpm -qa | sort > /packages.txt && \
|
||||
mkdir -p /usr/libexec/ccache-wrappers && \
|
||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
|
||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \
|
||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \
|
||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
|
||||
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
|
||||
|
||||
ENV CCACHE_WRAPPERSDIR=/usr/libexec/ccache-wrappers
|
||||
ENV LANG=en_US.UTF-8
|
||||
ENV MAKE=/usr/bin/make
|
||||
ENV NINJA=/usr/bin/ninja
|
||||
ENV PYTHON=/usr/bin/python3
|
||||
ENV QEMU_CONFIGURE_OPTS=--meson=internal
|
||||
|
||||
RUN dnf install -y curl wget
|
||||
ENV COVERITY_TOOL_BASE=/coverity-tools
|
||||
COPY coverity_tool.tgz coverity_tool.tgz
|
||||
RUN mkdir -p /coverity-tools/coverity_tool && cd /coverity-tools/coverity_tool && tar xf /coverity_tool.tgz
|
||||
COPY run-coverity-scan run-coverity-scan
|
||||
@@ -0,0 +1,284 @@
|
||||
/* Coverity Scan model
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Markus Armbruster <[email protected]>
|
||||
* Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or, at your
|
||||
* option, any later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This is the source code for our Coverity user model file. The
|
||||
* purpose of user models is to increase scanning accuracy by explaining
|
||||
* code Coverity can't see (out of tree libraries) or doesn't
|
||||
* sufficiently understand. Better accuracy means both fewer false
|
||||
* positives and more true defects. Memory leaks in particular.
|
||||
*
|
||||
* - A model file can't import any header files. Some built-in primitives are
|
||||
* available but not wchar_t, NULL etc.
|
||||
* - Modeling doesn't need full structs and typedefs. Rudimentary structs
|
||||
* and similar types are sufficient.
|
||||
* - An uninitialized local variable signifies that the variable could be
|
||||
* any value.
|
||||
*
|
||||
* The model file must be uploaded by an admin in the analysis settings of
|
||||
* http://scan.coverity.com/projects/378
|
||||
*/
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef char int8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef long ssize_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long long int64_t;
|
||||
typedef _Bool bool;
|
||||
|
||||
typedef struct va_list_str *va_list;
|
||||
|
||||
/* Tainting */
|
||||
|
||||
typedef struct {} name2keysym_t;
|
||||
static int get_keysym(const name2keysym_t *table,
|
||||
const char *name)
|
||||
{
|
||||
int result;
|
||||
if (result > 0) {
|
||||
__coverity_tainted_string_sanitize_content__(name);
|
||||
return result;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replay data is considered trusted. */
|
||||
uint8_t replay_get_byte(void)
|
||||
{
|
||||
uint8_t byte;
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GLib memory allocation functions.
|
||||
*
|
||||
* Note that we ignore the fact that g_malloc of 0 bytes returns NULL,
|
||||
* and g_realloc of 0 bytes frees the pointer.
|
||||
*
|
||||
* Modeling this would result in Coverity flagging a lot of memory
|
||||
* allocations as potentially returning NULL, and asking us to check
|
||||
* whether the result of the allocation is NULL or not. However, the
|
||||
* resulting pointer should never be dereferenced anyway, and in fact
|
||||
* it is not in the vast majority of cases.
|
||||
*
|
||||
* If a dereference did happen, this would suppress a defect report
|
||||
* for an actual null pointer dereference. But it's too unlikely to
|
||||
* be worth wading through the false positives, and with some luck
|
||||
* we'll get a buffer overflow reported anyway.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocation primitives, cannot return NULL
|
||||
* See also Coverity's library/generic/libc/all/all.c
|
||||
*/
|
||||
|
||||
void *g_malloc_n(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
__coverity_negative_sink__(nmemb);
|
||||
__coverity_negative_sink__(size);
|
||||
ptr = __coverity_alloc__(nmemb * size);
|
||||
if (!ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
__coverity_mark_as_uninitialized_buffer__(ptr);
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *g_malloc0_n(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
__coverity_negative_sink__(nmemb);
|
||||
__coverity_negative_sink__(size);
|
||||
ptr = __coverity_alloc__(nmemb * size);
|
||||
if (!ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
__coverity_writeall0__(ptr);
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *g_realloc_n(void *ptr, size_t nmemb, size_t size)
|
||||
{
|
||||
__coverity_negative_sink__(nmemb);
|
||||
__coverity_negative_sink__(size);
|
||||
__coverity_escape__(ptr);
|
||||
ptr = __coverity_alloc__(nmemb * size);
|
||||
if (!ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
/*
|
||||
* Memory beyond the old size isn't actually initialized. Can't
|
||||
* model that. See Coverity's realloc() model
|
||||
*/
|
||||
__coverity_writeall__(ptr);
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void g_free(void *ptr)
|
||||
{
|
||||
__coverity_free__(ptr);
|
||||
__coverity_mark_as_afm_freed__(ptr, AFM_free);
|
||||
}
|
||||
|
||||
/*
|
||||
* Derive the g_try_FOO_n() from the g_FOO_n() by adding indeterminate
|
||||
* out of memory conditions
|
||||
*/
|
||||
|
||||
void *g_try_malloc_n(size_t nmemb, size_t size)
|
||||
{
|
||||
int nomem;
|
||||
|
||||
if (nomem) {
|
||||
return NULL;
|
||||
}
|
||||
return g_malloc_n(nmemb, size);
|
||||
}
|
||||
|
||||
void *g_try_malloc0_n(size_t nmemb, size_t size)
|
||||
{
|
||||
int nomem;
|
||||
|
||||
if (nomem) {
|
||||
return NULL;
|
||||
}
|
||||
return g_malloc0_n(nmemb, size);
|
||||
}
|
||||
|
||||
void *g_try_realloc_n(void *ptr, size_t nmemb, size_t size)
|
||||
{
|
||||
int nomem;
|
||||
|
||||
if (nomem) {
|
||||
return NULL;
|
||||
}
|
||||
return g_realloc_n(ptr, nmemb, size);
|
||||
}
|
||||
|
||||
/* Derive the g_FOO() from the g_FOO_n() */
|
||||
|
||||
void *g_malloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
__coverity_negative_sink__(size);
|
||||
ptr = __coverity_alloc__(size);
|
||||
if (!ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
__coverity_mark_as_uninitialized_buffer__(ptr);
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *g_malloc0(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
__coverity_negative_sink__(size);
|
||||
ptr = __coverity_alloc__(size);
|
||||
if (!ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
__coverity_writeall0__(ptr);
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *g_realloc(void *ptr, size_t size)
|
||||
{
|
||||
__coverity_negative_sink__(size);
|
||||
__coverity_escape__(ptr);
|
||||
ptr = __coverity_alloc__(size);
|
||||
if (!ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
/*
|
||||
* Memory beyond the old size isn't actually initialized. Can't
|
||||
* model that. See Coverity's realloc() model
|
||||
*/
|
||||
__coverity_writeall__(ptr);
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *g_try_malloc(size_t size)
|
||||
{
|
||||
int nomem;
|
||||
|
||||
if (nomem) {
|
||||
return NULL;
|
||||
}
|
||||
return g_malloc(size);
|
||||
}
|
||||
|
||||
void *g_try_malloc0(size_t size)
|
||||
{
|
||||
int nomem;
|
||||
|
||||
if (nomem) {
|
||||
return NULL;
|
||||
}
|
||||
return g_malloc0(size);
|
||||
}
|
||||
|
||||
void *g_try_realloc(void *ptr, size_t size)
|
||||
{
|
||||
int nomem;
|
||||
|
||||
if (nomem) {
|
||||
return NULL;
|
||||
}
|
||||
return g_realloc(ptr, size);
|
||||
}
|
||||
|
||||
/* Other glib functions */
|
||||
|
||||
typedef struct pollfd GPollFD;
|
||||
|
||||
int poll();
|
||||
|
||||
int g_poll (GPollFD *fds, unsigned nfds, int timeout)
|
||||
{
|
||||
return poll(fds, nfds, timeout);
|
||||
}
|
||||
|
||||
typedef struct _GIOChannel GIOChannel;
|
||||
GIOChannel *g_io_channel_unix_new(int fd)
|
||||
{
|
||||
/* cannot use incomplete type, the actual struct is roughly this size. */
|
||||
GIOChannel *c = g_malloc0(20 * sizeof(void *));
|
||||
__coverity_escape__(fd);
|
||||
return c;
|
||||
}
|
||||
|
||||
void g_assertion_message_expr(const char *domain,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *expr)
|
||||
{
|
||||
__coverity_panic__();
|
||||
}
|
||||
Executable
+458
@@ -0,0 +1,458 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# Upload a created tarball to Coverity Scan, as per
|
||||
# https://scan.coverity.com/projects/qemu/builds/new
|
||||
|
||||
# This work is licensed under the terms of the GNU GPL version 2,
|
||||
# or (at your option) any later version.
|
||||
# See the COPYING file in the top-level directory.
|
||||
#
|
||||
# Copyright (c) 2017-2020 Linaro Limited
|
||||
# Written by Peter Maydell
|
||||
|
||||
# Note that this script will automatically download and
|
||||
# run the (closed-source) coverity build tools, so don't
|
||||
# use it if you don't trust them!
|
||||
|
||||
# This script assumes that you're running it from a QEMU source
|
||||
# tree, and that tree is a fresh clean one, because we do an in-tree
|
||||
# build. (This is necessary so that the filenames that the Coverity
|
||||
# Scan server sees are relative paths that match up with the component
|
||||
# regular expressions it uses; an out-of-tree build won't work for this.)
|
||||
# The host machine should have as many of QEMU's dependencies
|
||||
# installed as possible, for maximum coverity coverage.
|
||||
|
||||
# To do an upload you need to be a maintainer in the Coverity online
|
||||
# service, and you will need to know the "Coverity token", which is a
|
||||
# secret 8 digit hex string. You can find that from the web UI in the
|
||||
# project settings, if you have maintainer access there.
|
||||
|
||||
# Command line options:
|
||||
# --check-upload-only : return success if upload is possible
|
||||
# --dry-run : run the tools, but don't actually do the upload
|
||||
# --docker : create and work inside a container
|
||||
# --docker-engine : specify the container engine to use (docker/podman/auto);
|
||||
# implies --docker
|
||||
# --update-tools-only : update the cached copy of the tools, but don't run them
|
||||
# --no-update-tools : do not update the cached copy of the tools
|
||||
# --tokenfile : file to read Coverity token from
|
||||
# --version ver : specify version being analyzed (default: ask git)
|
||||
# --description desc : specify description of this version (default: ask git)
|
||||
# --srcdir : QEMU source tree to analyze (default: current working dir)
|
||||
# --results-tarball : path to copy the results tarball to (default: don't
|
||||
# copy it anywhere, just upload it)
|
||||
# --src-tarball : tarball to untar into src dir (default: none); this
|
||||
# is intended mainly for internal use by the Docker support
|
||||
#
|
||||
# User-specifiable environment variables:
|
||||
# COVERITY_TOKEN -- Coverity token (default: looks at your
|
||||
# coverity.token config)
|
||||
# COVERITY_EMAIL -- the email address to use for uploads (default:
|
||||
# looks at your git coverity.email or user.email config)
|
||||
# COVERITY_BUILD_CMD -- make command (default: 'make -jN' where N is
|
||||
# number of CPUs as determined by 'nproc')
|
||||
# COVERITY_TOOL_BASE -- set to directory to put coverity tools
|
||||
# (default: /tmp/coverity-tools)
|
||||
#
|
||||
# You must specify the token, either by environment variable or by
|
||||
# putting it in a file and using --tokenfile. Everything else has
|
||||
# a reasonable default if this is run from a git tree.
|
||||
|
||||
upload_permitted() {
|
||||
# Check whether we can do an upload to the server; will exit *the script*
|
||||
# with status 99 if the check failed (usually a bad token);
|
||||
# will return from the function with status 1 if the check indicated
|
||||
# that we can't upload yet (ie we are at quota)
|
||||
# Assumes that COVERITY_TOKEN and PROJNAME have been initialized.
|
||||
|
||||
echo "Checking upload permissions..."
|
||||
|
||||
if ! up_perm="$(wget https://scan.coverity.com/api/upload_permitted --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -q -O -)"; then
|
||||
echo "Coverity Scan API access denied: bad token?"
|
||||
exit 99
|
||||
fi
|
||||
|
||||
# Really up_perm is a JSON response with either
|
||||
# {upload_permitted:true} or {next_upload_permitted_at:<date>}
|
||||
# We do some hacky string parsing instead of properly parsing it.
|
||||
case "$up_perm" in
|
||||
*upload_permitted*true*)
|
||||
return 0
|
||||
;;
|
||||
*next_upload_permitted_at*)
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
echo "Coverity Scan upload check: unexpected result $up_perm"
|
||||
exit 99
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
check_upload_permissions() {
|
||||
# Check whether we can do an upload to the server; will exit the script
|
||||
# with status 99 if the check failed (usually a bad token);
|
||||
# will exit the script with status 0 if the check indicated that we
|
||||
# can't upload yet (ie we are at quota)
|
||||
# Assumes that COVERITY_TOKEN, PROJNAME and DRYRUN have been initialized.
|
||||
|
||||
if upload_permitted; then
|
||||
echo "Coverity Scan: upload permitted"
|
||||
else
|
||||
if [ "$DRYRUN" = yes ]; then
|
||||
echo "Coverity Scan: upload quota reached, continuing dry run"
|
||||
else
|
||||
echo "Coverity Scan: upload quota reached; stopping here"
|
||||
# Exit success as this isn't a build error.
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
build_docker_image() {
|
||||
# build docker container including the coverity-scan tools
|
||||
echo "Building docker container..."
|
||||
# TODO: This re-unpacks the tools every time, rather than caching
|
||||
# and reusing the image produced by the COPY of the .tgz file.
|
||||
# Not sure why.
|
||||
tests/docker/docker.py --engine ${DOCKER_ENGINE} build \
|
||||
-t coverity-scanner -f scripts/coverity-scan/coverity-scan.docker \
|
||||
--extra-files scripts/coverity-scan/run-coverity-scan \
|
||||
"$COVERITY_TOOL_BASE"/coverity_tool.tgz
|
||||
}
|
||||
|
||||
update_coverity_tools () {
|
||||
# Check for whether we need to download the Coverity tools
|
||||
# (either because we don't have a copy, or because it's out of date)
|
||||
# Assumes that COVERITY_TOOL_BASE, COVERITY_TOKEN and PROJNAME are set.
|
||||
|
||||
mkdir -p "$COVERITY_TOOL_BASE"
|
||||
cd "$COVERITY_TOOL_BASE"
|
||||
|
||||
echo "Checking for new version of coverity build tools..."
|
||||
wget https://scan.coverity.com/download/cxx/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new
|
||||
|
||||
if ! cmp -s coverity_tool.md5 coverity_tool.md5.new; then
|
||||
# out of date md5 or no md5: download new build tool
|
||||
# blow away the old build tool
|
||||
echo "Downloading coverity build tools..."
|
||||
rm -rf coverity_tool coverity_tool.tgz
|
||||
wget https://scan.coverity.com/download/cxx/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -O coverity_tool.tgz
|
||||
if ! (cat coverity_tool.md5.new; echo " coverity_tool.tgz") | md5sum -c --status; then
|
||||
echo "Downloaded tarball didn't match md5sum!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DOCKER" != yes ]; then
|
||||
# extract the new one, keeping it corralled in a 'coverity_tool' directory
|
||||
echo "Unpacking coverity build tools..."
|
||||
mkdir -p coverity_tool
|
||||
cd coverity_tool
|
||||
tar xf ../coverity_tool.tgz
|
||||
cd ..
|
||||
mv coverity_tool.md5.new coverity_tool.md5
|
||||
fi
|
||||
fi
|
||||
rm -f coverity_tool.md5.new
|
||||
cd "$SRCDIR"
|
||||
|
||||
if [ "$DOCKER" = yes ]; then
|
||||
build_docker_image
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Check user-provided environment variables and arguments
|
||||
DRYRUN=no
|
||||
UPDATE=yes
|
||||
DOCKER=no
|
||||
PROJNAME=QEMU
|
||||
|
||||
while [ "$#" -ge 1 ]; do
|
||||
case "$1" in
|
||||
--check-upload-only)
|
||||
shift
|
||||
DRYRUN=check
|
||||
;;
|
||||
--dry-run)
|
||||
shift
|
||||
DRYRUN=yes
|
||||
;;
|
||||
--no-update-tools)
|
||||
shift
|
||||
UPDATE=no
|
||||
;;
|
||||
--update-tools-only)
|
||||
shift
|
||||
UPDATE=only
|
||||
;;
|
||||
--version)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--version needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
VERSION="$1"
|
||||
shift
|
||||
;;
|
||||
--description)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--description needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
DESCRIPTION="$1"
|
||||
shift
|
||||
;;
|
||||
--tokenfile)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--tokenfile needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
COVERITY_TOKEN="$(cat "$1")"
|
||||
shift
|
||||
;;
|
||||
--srcdir)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--srcdir needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
SRCDIR="$1"
|
||||
shift
|
||||
;;
|
||||
--results-tarball)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--results-tarball needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
RESULTSTARBALL="$1"
|
||||
shift
|
||||
;;
|
||||
--src-tarball)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--src-tarball needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
SRCTARBALL="$1"
|
||||
shift
|
||||
;;
|
||||
--docker)
|
||||
DOCKER=yes
|
||||
DOCKER_ENGINE=auto
|
||||
shift
|
||||
;;
|
||||
--docker-engine)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "--docker-engine needs an argument"
|
||||
exit 1
|
||||
fi
|
||||
DOCKER=yes
|
||||
DOCKER_ENGINE="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unexpected argument '$1'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$COVERITY_TOKEN" ]; then
|
||||
COVERITY_TOKEN="$(git config coverity.token)"
|
||||
fi
|
||||
if [ -z "$COVERITY_TOKEN" ]; then
|
||||
echo "COVERITY_TOKEN environment variable not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DRYRUN" = check ]; then
|
||||
upload_permitted
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ -z "$COVERITY_BUILD_CMD" ]; then
|
||||
NPROC=$(nproc)
|
||||
COVERITY_BUILD_CMD="make -j$NPROC"
|
||||
echo "COVERITY_BUILD_CMD: using default '$COVERITY_BUILD_CMD'"
|
||||
fi
|
||||
|
||||
if [ -z "$COVERITY_TOOL_BASE" ]; then
|
||||
echo "COVERITY_TOOL_BASE: using default /tmp/coverity-tools"
|
||||
COVERITY_TOOL_BASE=/tmp/coverity-tools
|
||||
fi
|
||||
|
||||
if [ -z "$SRCDIR" ]; then
|
||||
SRCDIR="$PWD"
|
||||
fi
|
||||
|
||||
TARBALL=cov-int.tar.xz
|
||||
|
||||
if [ "$UPDATE" = only ]; then
|
||||
# Just do the tools update; we don't need to check whether
|
||||
# we are in a source tree or have upload rights for this,
|
||||
# so do it before some of the command line and source tree checks.
|
||||
|
||||
if [ "$DOCKER" = yes ] && [ ! -z "$SRCTARBALL" ]; then
|
||||
echo --update-tools-only --docker is incompatible with --src-tarball.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
update_coverity_tools
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -e "$SRCDIR" ]; then
|
||||
mkdir "$SRCDIR"
|
||||
fi
|
||||
|
||||
cd "$SRCDIR"
|
||||
|
||||
if [ ! -z "$SRCTARBALL" ]; then
|
||||
echo "Untarring source tarball into $SRCDIR..."
|
||||
tar xvf "$SRCTARBALL"
|
||||
fi
|
||||
|
||||
echo "Checking this is a QEMU source tree..."
|
||||
if ! [ -e "$SRCDIR/VERSION" ]; then
|
||||
echo "Not in a QEMU source tree?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fill in defaults used by the non-update-only process
|
||||
if [ -z "$VERSION" ]; then
|
||||
VERSION="$(git describe --always HEAD)"
|
||||
fi
|
||||
|
||||
if [ -z "$DESCRIPTION" ]; then
|
||||
DESCRIPTION="$(git rev-parse HEAD)"
|
||||
fi
|
||||
|
||||
if [ -z "$COVERITY_EMAIL" ]; then
|
||||
COVERITY_EMAIL="$(git config coverity.email)"
|
||||
fi
|
||||
if [ -z "$COVERITY_EMAIL" ]; then
|
||||
COVERITY_EMAIL="$(git config user.email)"
|
||||
fi
|
||||
|
||||
# Otherwise, continue with the full build and upload process.
|
||||
|
||||
check_upload_permissions
|
||||
|
||||
if [ "$UPDATE" != no ]; then
|
||||
update_coverity_tools
|
||||
fi
|
||||
|
||||
# Run ourselves inside docker if that's what the user wants
|
||||
if [ "$DOCKER" = yes ]; then
|
||||
# Put the Coverity token into a temporary file that only
|
||||
# we have read access to, and then pass it to docker build
|
||||
# using a volume. A volume is enough for the token not to
|
||||
# leak into the Docker image.
|
||||
umask 077
|
||||
SECRETDIR=$(mktemp -d)
|
||||
if [ -z "$SECRETDIR" ]; then
|
||||
echo "Failed to create temporary directory"
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$SECRETDIR"' INT TERM EXIT
|
||||
echo "Created temporary directory $SECRETDIR"
|
||||
SECRET="$SECRETDIR/token"
|
||||
echo "$COVERITY_TOKEN" > "$SECRET"
|
||||
echo "Archiving sources to be analyzed..."
|
||||
./scripts/archive-source.sh "$SECRETDIR/qemu-sources.tgz"
|
||||
ARGS="--no-update-tools"
|
||||
if [ "$DRYRUN" = yes ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
fi
|
||||
echo "Running scanner..."
|
||||
# If we need to capture the output tarball, get the inner run to
|
||||
# save it to the secrets directory so we can copy it out before the
|
||||
# directory is cleaned up.
|
||||
if [ ! -z "$RESULTSTARBALL" ]; then
|
||||
ARGS="$ARGS --results-tarball /work/cov-int.tar.xz"
|
||||
fi
|
||||
# Arrange for this docker run to get access to the sources with -v.
|
||||
# We pass through all the configuration from the outer script to the inner.
|
||||
export COVERITY_EMAIL COVERITY_BUILD_CMD
|
||||
tests/docker/docker.py run -it --env COVERITY_EMAIL --env COVERITY_BUILD_CMD \
|
||||
-v "$SECRETDIR:/work" coverity-scanner \
|
||||
./run-coverity-scan --version "$VERSION" \
|
||||
--description "$DESCRIPTION" $ARGS --tokenfile /work/token \
|
||||
--srcdir /qemu --src-tarball /work/qemu-sources.tgz
|
||||
if [ ! -z "$RESULTSTARBALL" ]; then
|
||||
echo "Copying results tarball to $RESULTSTARBALL..."
|
||||
cp "$SECRETDIR/cov-int.tar.xz" "$RESULTSTARBALL"
|
||||
fi
|
||||
echo "Docker work complete."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TOOLBIN="$(cd "$COVERITY_TOOL_BASE" && echo $PWD/coverity_tool/cov-analysis-*/bin)"
|
||||
|
||||
if ! test -x "$TOOLBIN/cov-build"; then
|
||||
echo "Couldn't find cov-build in the coverity build-tool directory??"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PATH="$TOOLBIN:$PATH"
|
||||
|
||||
cd "$SRCDIR"
|
||||
|
||||
echo "Nuking build directory..."
|
||||
rm -rf +build
|
||||
mkdir +build
|
||||
cd +build
|
||||
|
||||
echo "Configuring..."
|
||||
# We configure with a fixed set of enables here to ensure that we don't
|
||||
# accidentally reduce the scope of the analysis by doing the build on
|
||||
# the system that's missing a dependency that we need to build part of
|
||||
# the codebase.
|
||||
../configure --disable-modules --enable-sdl --enable-gtk \
|
||||
--enable-opengl --enable-vte --enable-gnutls \
|
||||
--enable-nettle --enable-curses --enable-curl \
|
||||
--audio-drv-list=oss,alsa,sdl,pa --enable-virtfs \
|
||||
--enable-vnc --enable-vnc-sasl --enable-vnc-jpeg --enable-png \
|
||||
--enable-xen --enable-brlapi \
|
||||
--enable-linux-aio --enable-attr \
|
||||
--enable-cap-ng --enable-trace-backends=log --enable-spice --enable-rbd \
|
||||
--enable-libusb --enable-usb-redir \
|
||||
--enable-libiscsi --enable-seccomp \
|
||||
--enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \
|
||||
--enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \
|
||||
--enable-mpath \
|
||||
--enable-virtfs --enable-zstd
|
||||
|
||||
echo "Running cov-build..."
|
||||
rm -rf cov-int
|
||||
mkdir cov-int
|
||||
cov-build --dir cov-int $COVERITY_BUILD_CMD
|
||||
|
||||
echo "Creating results tarball..."
|
||||
tar cvf - cov-int | xz > "$TARBALL"
|
||||
|
||||
if [ ! -z "$RESULTSTARBALL" ]; then
|
||||
echo "Copying results tarball to $RESULTSTARBALL..."
|
||||
cp "$TARBALL" "$RESULTSTARBALL"
|
||||
fi
|
||||
|
||||
echo "Uploading results tarball..."
|
||||
|
||||
if [ "$DRYRUN" = yes ]; then
|
||||
echo "Dry run only, not uploading $TARBALL"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
curl --form token="$COVERITY_TOKEN" --form email="$COVERITY_EMAIL" \
|
||||
--form file=@"$TARBALL" --form version="$VERSION" \
|
||||
--form description="$DESCRIPTION" \
|
||||
https://scan.coverity.com/builds?project="$PROJNAME"
|
||||
|
||||
echo "Done."
|
||||
Reference in New Issue
Block a user