Coverity Scan

From Crypto++ Wiki
Jump to navigation Jump to search

The Crypto++ library performs regular scans of the library using Coverity Scan service with its test program cryptest.exe. The project's page for the scan service can be found at Coverity | Cryptopp (there were character set restrictions).

Coverity kindly donates the scan service for FOSS projects. Its an awesome service and we are grateful to Coverity for providing it. The service has uncovered at least three bugs we knew existed but were not able to track down with reviews and audits (in addition to other tools missing them).

Coverity Scan is one of six analysis tools we use to help keep the library fit. You can read about the use of static and dynamic analysis at Release Process | Analysis Tools. The results of the Coverity Scan service are world readable since we believe in complete transparency. Coverity requires you have an account to view the defect reports.

The page below offers the processes and files we use to navigate the scan build process. It also offers hints for things we have discovered since the documentation is kind of scant.

As of May 2018 we have been locked out of the cryptopp account. We have not been able to run a scan since April 2018. Synopsis Tech Support was not able to help us.

Preparation

You must prepare before starting the scan build process. You will need supporting tools and files. The Crypto++ project supplies the supporting files. Coverity and your platform supplies the supporting tools.

Source Files

Obviously, you will need the Crypto++ source files. You can get the latest source files with the following. Its sometimes useful to use a new directory since it can take some time to clear a Coverity finding (especially if we exhaust our weekly limit during experimentation).

git clone https://github.com/weidai11/cryptopp.git cryptopp-coverity
cd cryptopp-coverity

The remainder of the document presumes you are working from the root Crypto++ directory.

Supporting Files

The Crypto++ project uses a handful of files to support the scan build process. The files are located in the TestScript directory even though they are not scripts per se. The files are listed below.

  • cryptest-coverity.cpp - the Coverity modeling file. As it is updated, the file is re-uploaded to the Scan Service. We are still learning how to use it.
  • coverity-linux.txt - the scan build procedure used on Unix, Linux and OS X. Painting with a broad brush, they are commands issued in a terminal when performing the steps in the process.
  • coverity-windows.txt - the scan build procedure used on Windows. Painting with a broad brush, they are commands issued in a terminal when performing the steps in the process.
  • cryptest.nmake - a Nmake based file used for building Crypto++ from the command line. The file is multipurpose even though the library supplies Visual Studio solution and project files.

Supporting Tools

You will need the following supporting tools, depending on your platform. The tools are a compiler, a linker and archiver and a non-anemic Make like GNU Make on Unix or Nmake on Windows. Windows users don't need Visual Studio. Instead, they can use the free Visual C++ Build Tools.

Be sure your tools are on-path. You should open a Developer Command Prompt for Visual Studio to ensure the Visual C++ Build Tools are on path on Windows.

Unix, Linux, OS X

  • Build Essentials (gmake, gcc, ld, ar, etc)
  • tar
  • curl

Windows

Self-Build Installation

The Self-Build Installation instructions that follow are for Unix, Linux, OS X and Windows. The installation of the Coverity client component is simple once you find it on Coverity's website. The client component is called self-build. To navigate to it, Click Submit Build on the right side of the page. Then click the big red button labeled Download Coverity Scan Self-Build. You must be logged into the service to download the self-build client.

The cov-analysis-* files are large. For example, Linux's package is cov-analysis-linux-8.5.0.3, and its 480 MB compressed. Within cov-analysis-* is cov-build. You only need the bin/ on path to ensure cov-build is accessible. The instructions below provides recipes for Unix, Linux and OS X.

Unix, Linux, OS X

First unpack the tarball and move it into /usr/local/bin. Be sure to use the correct tarball name.

$ tar xzf cov-analysis-linux-8.5.0.3.tar.gz
$ sudo mv cov-analysis-linux-8.5.0.3 /usr/local/bin/

For OS X only remove the quarantine bits:

$ sudo xattr -r -d com.apple.quarantine /usr/local/bin/cov-analysis-macosx-8.5.0.3/bin/

Second, create a script in /usr/local/bin/ called cov-build which sets the path and calls the real cov-build:

$ cat /usr/local/bin/cov-build 
#!/usr/bin/env bash

PATH=/usr/local/bin/cov-analysis-linux-8.5.0.3/bin:$PATH; /usr/local/bin/cov-analysis-linux-8.5.0.3/bin/cov-build "$@"

Third, make the script executable:

$ sudo chmod a+x /usr/local/bin/cov-build

Finally, test it:

$ command -v cov-build
/usr/local/bin/cov-build

$ cov-build --help
Coverity Build Capture (32-bit) version 8.5.0.3 on Linux 3.13.0-96-generic i686
Internal version numbers: db70178643 p-kent-push-26368.949
...

Windows

Download and install cov-build (from cov-analysis-windows.zip), 7zip and cURL. If you don't have Visual Studio, then you can use Visual C++ Build Tools. Visual C++ Build Tools provides everything you need for a scan build submission. Install then in Program Files or the Windows System directory.

Generally speaking, a path without spaces causes the least trouble, so C:\Windows is often a good choice. Just move the tools' topmost directory into C:\Windows, and then ensure the binary is on path (see two paragraphs down).

Be sure 7z.exe and curl.exe are on path, and cacerts.pem is available to cURL. See Configuring System and User Environment Variables from MSDN for instructions on modifying your path. The additional paths should include similar to the following:

  • C:\Windows\cov-analysis-win64-8.5.0.3\bin
  • C:\Windows\curl_7_50_3
  • C:\Windows\7-Zip

You can verify the programs on path by checking their version from the command line:

C:\Users\cryptopp>curl.exe --version
curl 7.50.3 (x86_64-pc-win32) libcurl/7.50.3 OpenSSL/1.0.2j nghttp2/1.15.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp
smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM SSL HTTP2

Scan Building

The Scan Building instructions that follow are for Unix, Linux, OS X and Windows. The process creates a binary with additional Coverity instrumentation that can be analyzed by the Scan Service.

Unix, Linux, and Windows work as expected. OS X is having trouble. We have not been able to get the scan service client to build the library on OS X 10.8 or 10.9.

Unix and Linux

The project uses the GNUmakefile and cov-build for Unix and Linux. The script should be run from the root of the Crypto++ directory. Its really just a text file, and we copy/paste it into a terminal. The script is shown below, and it relies on two variables.

COVERITY_SCAN_NAME is the friendly name displayed on the Crypto++ project Coverity scan page. CRYPTOPP_COVERITY_TOKEN is the token Coverity provides to access the service.

In the script below, the order of arguments when building the cov-build is significant. CXXFLAGS must proceed the command. A temporary directly like --dir cov-int must be supplied as an argument. Finally we tell the command to invoke our makefile with make -j 2.

$ cat coverity-linux.txt
reset

make distclean &>/dev/null

# Usually we test with these flags
# CXXFLAGS="-DNDEBUG -g3 -O2"

# Testing for Issue 302 (http://github.com/weidai11/cryptopp/issues/302)
CXXFLAGS="-DNDEBUG -g2 -O3 -march=i686 -msse -msse2 -msse3 -mssse3 -mno-aes" cov-build --dir cov-int make -j 2

tar czvf cryptopp.tgz cov-int

CRYPTOPP_COVERITY_TOKEN=XXXXXXXXXXXXXXXX
COVERITY_SCAN_NAME="Rijndael-AliasedTable-SSE2-Linux-i686"

curl \
  --form token="$CRYPTOPP_COVERITY_TOKEN" \
  --form [email protected] \
  --form [email protected] \
  --form version="$COVERITY_SCAN_NAME" \
  --form description="$COVERITY_SCAN_NAME" \
  https://scan.coverity.com/builds?project=Cryptopp

OS X

The project uses the GNUmakefile and cov-build for OS X. The procedure is the same as Unix and Linux. If all goes well on OS X, then the following will work as expected. If things don't go well, then there are two work-arounds, and one of them should work.

reset

make distclean &>/dev/null

CXXFLAGS="-DNDEBUG -g2 -O3" cov-build --dir cov-int make -j 2

tar czvf cryptopp.tgz cov-int

CRYPTOPP_COVERITY_TOKEN=XXXXXXXXXXXXXXXX
COVERITY_SCAN_NAME="Cryptopp-OSX-x86_64"

curl \
  --form token="$CRYPTOPP_COVERITY_TOKEN" \
  --form [email protected] \
  --form [email protected] \
  --form version="$COVERITY_SCAN_NAME" \
  --form description="$COVERITY_SCAN_NAME" \
  https://scan.coverity.com/builds?project=Cryptopp

First Work-around

If the process fails with the following error:

Coverity Build Capture (64-bit) version 8.5.0.3 on Darwin 12.6.0 x86_64
Internal version numbers: db70178643 p-kent-push-26368.949
    
Platform info:
Sysname = Darwin
Release = 12.6.0
Machine = x86_64

[ERROR] This platform is not supported by Coverity.
[ERROR] See documentation for the list of supported platforms.

Then Flash Sheridan and Caleb from Stack Overflow suggests using COVERITY_UNSUPPORTED=1.

$ COVERITY_UNSUPPORTED=1 CXXFLAGS="-DNDEBUG -g3 -O2" cov-build --dir cov-int make -j 8

Unfortunately, the workaround failed on OS X 10.8.5:

[WARNING] Emitted 1 C/C++ compilation units (0%) successfully

1 C/C++ compilation units (0%) are ready for analysis
 For more details, please look at: 
    /Users/cryptopp/cov-int/build-log.txt

Second Work-around

Check you build log and see if it fingers Xcode 5.x, and produces multiple errors like the following.

"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/
clang/5.0/include/stddef.h", line 29: error #109:

expression preceding parentheses of apparent call must have

(pointer-to-) function type

#if !defined(_PTRDIFF_T) || __has_feature(modules)


"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/
clang/5.0/include/stddef.h", line 31: error #59:

function call is not allowed in a constant expression

#if !__has_feature(modules)

The second work-around is to use a different compiler with the first work-around. Below, we use MacPorts Clang 3.7 to perform a scan build. You may need to use -std=c++11 to avoid C++03 findings based on C++11 code.

$ CXX=/opt/local/bin/clang++-mp-3.7 COVERITY_UNSUPPORTED=1 CXXFLAGS="-DNDEBUG -g3 -O2 -std=c++11" cov-build --dir cov-int make -j 8
Coverity Build Capture (64-bit) version 8.5.0.3 on Darwin 12.6.0 x86_64
Internal version numbers: db70178643 p-kent-push-26368.949

/opt/local/bin/clang++-mp-3.7 -DNDEBUG -g3 -O2 -std=c++11 -fPIC -march=native -pipe -c cryptlib.cpp
/opt/local/bin/clang++-mp-3.7 -DNDEBUG -g3 -O2 -std=c++11 -fPIC -march=native -pipe -c cpu.cpp
...

Emitted 134 C/C++ compilation units (100%) successfully

134 C/C++ compilation units (100%) are ready for analysis
The cov-build utility completed successfully.

Windows

The project uses the cryptest.nmake and cov-build for Windows. cryptest.nmake is the equivalent of the Unix and Linux makefile. The scan build is performed from a Developer Tools command line prompt similar to Unix and Linux. You may be able to perform a scan build with msbuild or Visual Studio, but we have not attempted it.

cryptest.nmake has a selection of CXXFLAGS for testing under X86, X64 ad ARM. You should open cryptest.nmake and uncomment the one that matches your Developer Tools command line prompt. Below is the block for X86, and you would use it if you opened an X86 Developer Tools command line prompt.

!IF "$(PLATFORM)" == "x86" || "$(PLATFORM)" == "X86"
# CXXFLAGS = $(CXXFLAGS) /arch:SSE2
# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP
AS = ml.exe
ASFLAGS = /nologo /D_M_X86 /W3 /Cx /Zi /safeseh
LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm
LIB_OBJS = $(LIB_OBJS) rdrand.obj rdrand-x86.obj
LDLIBS = $(LDLIBS) ws2_32.lib kernel32.lib
!ENDIF

After you uncomment the CXXFLAGS of interest, perform the following from the command line prompt. COVERITY_SCAN_NAME is the friendly name displayed on the Crypto++ Coverity scan page. CRYPTOPP_COVERITY_TOKEN is the token which Coverity provides to access the service.

C:\cryptopp> type coverity-windows.txt

cls

del /f cryptopp.zip
rmdir /q /s cov-int
nmake /f cryptest.nmake clean

cov-build.exe --dir cov-int nmake /f cryptest.nmake

7z.exe a -r -tzip cryptopp.zip cov-int

set CRYPTOPP_COVERITY_TOKEN=XXXXXXXXXXXXXXXX
set COVERITY_SCAN_NAME=Rijndael-AliasedTable-SSE2-Windows-X64

curl.exe ^
  --form token="%CRYPTOPP_COVERITY_TOKEN%" ^
  --form [email protected] ^
  --form [email protected] ^
  --form version="%COVERITY_SCAN_NAME%" ^
  --form description="%COVERITY_SCAN_NAME%" ^
  https://scan.coverity.com/builds?project=Cryptopp

Errata and Fodder

The following is a collection of errata items.

Self-signed Certificate

If you receive an error similar to:

$ curl  \
    --form token="$CRYPTOPP_COVERITY_TOKEN" \
    --form [email protected] \
    --form [email protected] \
    --form version="$COVERITY_SCAN_NAME" \
    --form description="$COVERITY_SCAN_NAME" \
    https://scan.coverity.com/builds?project=Cryptopp

curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html
...

Then you should update the certificate bundle used by cURL. To update the certificate bundle run build-cacert.sh from Noloader's GitHub. After updating the bundle re-reun the command with CURL_CA_BUNDLE set to the bundle:

$ CURL_CA_BUNDLE="$HOME/.cacert/cacert.pem" curl  \
    --form token="$CRYPTOPP_COVERITY_TOKEN" \
    --form [email protected] \
    --form [email protected] \
    --form version="$COVERITY_SCAN_NAME" \
    --form description="$COVERITY_SCAN_NAME" \
    https://scan.coverity.com/builds?project=Cryptopp

OS X and UNCAUGHT_EXCEPT

When scan building on OS X 10.8.5 with both work-arounds in place, we found Coverity flagged a C++03 issue under a C++11 compiler. Its due to out use of CRYPTOPP_THROW macro for C++11 and throwing destructors. You can safely ignore it:

CID 171374 (1 of 1): Uncaught exception (UNCAUGHT_EXCEPT)
exn_spec_violation: An exception of type CryptoPP::InvalidArgument is thrown but the throw
list throw() doesn't allow it to be thrown. This will cause a call to unexpected() which
usually calls terminate().
   fun_call_w_exception: Called function throws an exception of type CryptoPP::InvalidArgument.
 17 class GFP2Element { ... };