run scan-build in CI (#680)

Yet another static analyzer pass, this one is used by SPDK, and as it
did detect some minor issues, it's worth running.

Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
diff --git a/.github/workflows/pull_request.sh b/.github/workflows/pull_request.sh
index 20b8ace..b972bda 100755
--- a/.github/workflows/pull_request.sh
+++ b/.github/workflows/pull_request.sh
@@ -1,5 +1,7 @@
 #!/bin/sh
 
+# NB: we can't use "meson compile -v", as centos 7 doesn't support that option.
+
 set -e
 set -v
 
@@ -8,23 +10,29 @@
 rm -rf $BUILD
 
 # ASAN build with clang
-CC=clang meson $BUILD/asan -Db_sanitize=address -Db_lundef=false
+CC=clang meson setup $BUILD/asan -Db_sanitize=address -Db_lundef=false
 ninja -C $BUILD/asan -v
 meson test -C $BUILD/asan --suite style --print-errorlogs
 meson test -C $BUILD/asan --no-suite style --print-errorlogs
 
+# analyzer build
+meson setup $BUILD/scan-build -Dtran-pipe=true
+# no "meson scan-build" for some reason
+ninja -C $BUILD/scan-build -v scan-build -v
+meson test -C $BUILD/scan-build --no-suite style --print-errorlogs
+
 # debug build with clang
-CC=clang meson build/clang-debug -Dtran-pipe=true
+CC=clang meson setup build/clang-debug -Dtran-pipe=true
 ninja -C $BUILD/clang-debug -v
 meson test -C $BUILD/clang-debug --no-suite style --print-errorlogs
 
 # release build with clang
-CC=clang meson build/clang-release -Dtran-pipe=true -Dbuildtype=release
+CC=clang meson setup build/clang-release -Dtran-pipe=true -Dbuildtype=release
 ninja -C $BUILD/clang-release -v
 meson test -C $BUILD/clang-release --no-suite style --print-errorlogs
 
 # debug build with gcc
-CC=gcc meson build/gcc-debug -Dtran-pipe=true
+CC=gcc meson setup build/gcc-debug -Dtran-pipe=true
 ninja -C $BUILD/gcc-debug -v
 meson test -C $BUILD/gcc-debug --no-suite style --print-errorlogs
 
@@ -34,6 +42,6 @@
 DESTDIR=tmp.install meson install -C $BUILD/gcc-debug
 
 # release build with gcc
-CC=gcc meson build/gcc-release -Dtran-pipe=true -Dbuildtype=release
+CC=gcc meson setup build/gcc-release -Dtran-pipe=true -Dbuildtype=release
 ninja -C $BUILD/gcc-release -v
 meson test -C $BUILD/gcc-release --no-suite style --print-errorlogs
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index e905dd5..2b3b910 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -9,9 +9,9 @@
       - name: pre-push
         run: |
           sudo apt-get update
-          sudo apt-get -y install libjson-c-dev libcmocka-dev clang valgrind \
-                                  python3-pytest debianutils flake8 meson \
-                                  ninja-build
+          sudo apt-get -y install libjson-c-dev libcmocka-dev clang \
+            clang-tools valgrind python3-pytest debianutils flake8 meson \
+            ninja-build
           ./.github/workflows/pull_request.sh
   ubuntu-22:
     timeout-minutes: 10
@@ -21,9 +21,9 @@
       - name: pre-push
         run: |
           sudo apt-get update
-          sudo apt-get -y install libjson-c-dev libcmocka-dev clang valgrind \
-                                  python3-pytest debianutils flake8 meson \
-                                  ninja-build
+          sudo apt-get -y install libjson-c-dev libcmocka-dev clang \
+            clang-tools valgrind python3-pytest debianutils flake8 meson \
+            ninja-build
           ./.github/workflows/pull_request.sh
   centos-7:
     timeout-minutes: 10
@@ -35,7 +35,7 @@
         run: |
           # NB: no working flake8
           yum -y install make gcc-4.8.5 epel-release pciutils
-          yum -y install clang json-c-devel libcmocka-devel \
+          yum -y install clang clang-analyzer json-c-devel libcmocka-devel \
               valgrind python36-pytest which ninja-build meson
           ./.github/workflows/pull_request.sh
   fedora-35:
@@ -47,6 +47,7 @@
       - name: pre-push
         run: |
           dnf -y install --releasever=35 \
-              gcc make clang json-c-devel libcmocka-devel pciutils diffutils \
-              valgrind python3-pytest python3-flake8 which meson ninja-build
+              gcc make clang clang-analyzer json-c-devel libcmocka-devel pciutils \
+              diffutils valgrind python3-pytest python3-flake8 which \
+              meson ninja-build
           ./.github/workflows/pull_request.sh
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index 5b95865..fd2465d 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -469,7 +469,7 @@
                      size_t offset, uint32_t size, uint32_t flags,
                      uint64_t datamatch)
 {
-    vfu_reg_info_t *vfu_reg = &vfu_ctx->reg_info[region_idx];
+    vfu_reg_info_t *vfu_reg;
 
     assert(vfu_ctx != NULL);
     assert(fd >= 0);
diff --git a/lib/tran_pipe.c b/lib/tran_pipe.c
index 34dd075..dea2c3c 100644
--- a/lib/tran_pipe.c
+++ b/lib/tran_pipe.c
@@ -73,6 +73,10 @@
 
     ret = writev(fd, iovecs, nr_iovecs);
 
+    /* Quieten static analysis. */
+    iovecs[0].iov_base = NULL;
+    iovecs[0].iov_len = 0;
+
     if (ret == -1) {
         /* Treat a failed write due to EPIPE the same as a short write. */
         if (errno == EPIPE) {
diff --git a/samples/client.c b/samples/client.c
index 9f4a42b..492dd18 100644
--- a/samples/client.c
+++ b/samples/client.c
@@ -78,20 +78,20 @@
 static int
 init_sock(const char *path)
 {
-    int ret, sock;
-	struct sockaddr_un addr = {.sun_family = AF_UNIX};
+    struct sockaddr_un addr = {.sun_family = AF_UNIX};
+    int sock;
 
-	/* TODO path should be defined elsewhere */
-	ret = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
+    /* TODO path should be defined elsewhere */
+    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
 
-	if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-		err(EXIT_FAILURE, "failed to open socket %s", path);
-	}
+    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+        err(EXIT_FAILURE, "failed to open socket %s", path);
+    }
 
-	if ((ret = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) == -1) {
-		err(EXIT_FAILURE, "failed to connect server");
-	}
-	return sock;
+    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+        err(EXIT_FAILURE, "failed to connect server");
+    }
+    return sock;
 }
 
 static void
diff --git a/test/unit-tests.c b/test/unit-tests.c
index 81288e2..7d5297e 100644
--- a/test/unit-tests.c
+++ b/test/unit-tests.c
@@ -314,8 +314,8 @@
 test_dma_addr_to_sg(void **state UNUSED)
 {
     dma_memory_region_t *r, *r1;
+    struct iovec iov[2] = { };
     dma_sg_t sg[2];
-    struct iovec iov[2];
     int ret;
 
     vfu_ctx.dma->nregions = 1;