Build-wrapper v6.3.0: uncaught exception constructing string

I have a problem with the sonar build-wrapper for one of my projects.
There is an uncaught exception in the build-wrapper itself.
At first I thought the build wrapper was making the test crash somehow but then I realised it was the build-wrapper itself that was crashing.

I’m not sure if this is the right place to report this.
I am also wondering where the source code for the build wrapper is.
I cannot identify which project it is (assuming it is somewhere in SonarSource · GitHub)

It happens when it tries to analyse a couple of tests which use va_arg.
If I disable those tests the wrapper does not fail.

Given enough time I could probably create a smaller test program which reproduces it.
I might be able to create a patch myself if I can locate the build-wrapper source.

The bit of our code that seems to sometimes trigger it is:

void Posix::appendArgv(

std::vector< char * > &argv,

va_list *ap

)

{

char *arg = 0;

do

{

arg = va_arg(*ap, char *);

argv.push_back(arg);

}

while (arg != 0);

}
>./target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --version
build-wrapper, version 6.30 (linux-x86)
Copyright (C) 2014-2021 SonarSource SA, [info@sonarsource.com](mailto:info@sonarsource.com)

>./target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir target/bw-output ./cppunit-testsuite

.................................................................................arg: terminate called after throwing an instance of 'std::logic_error'

what(): basic_string::_M_construct null not valid

OK (81 tests)

Aborted (core dumped)

#0 0x00007fec6793937f in raise () from /usr/lib64/libc.so.6
#1 0x00007fec67923db5 in abort () from /usr/lib64/libc.so.6
#2 0x0000564a629f708e in __gnu_cxx::__verbose_terminate_handler() [clone .cold] ()
#3 0x0000564a62a05c5c in __cxxabiv1::__terminate(void (*)()) ()
#4 0x0000564a62a05cc7 in std::terminate() ()
#5 0x0000564a62a05e29 in __cxa_throw ()
#6 0x0000564a629f850b in std::__throw_logic_error(char const*) ()
#7 0x0000564a629febec in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) ()
#8 0x0000564a629feaec in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<char const*>(char const*, char const*, std::__false_type) ()
#9 0x0000564a629fe983 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*) ()
#10 0x0000564a629fe565 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&) ()
#11 0x0000564a629fb73a in bwrapper::handleCapture(std::basic_ofstream<char, std::char_traits<char> >&, Capture&) ()
#12 0x0000564a629fbce7 in bwrapper::collectCaptures(int) ()
#13 0x0000564a629fdac0 in bwrapper::work(int, char* const*, char* const*) ()
#14 0x0000564a629f9c95 in main ()

Hello @KantarBruceAdams, and welcome!

Yes, it is.

The build wrapper is not open-source, so you can’t find the source code, or create a patch.

The information you are providing are already quite good to help us locate the issue. Thank you. But more information would help us make sure we nail it down. The build wrapper is interested by the processes that are launched, their command line arguments, the environment variables.

In your case, you are launching the cppunit-testsuite that in turn seems to be launching sub-processes. First question: Is this process related to one of the many cppunit libraries out there? Could you provide us with test source code that we could build to reproduce the issue? Are you aware of anything unusual with a process that you might we spawning in one of your tests?

Secondly, within the handleCapture function, we log a lot of what is happening, so if you could send us the build-wrapper.log that is generated when the crash happen, it would allow us to better locate where this null pointer hides. If you want to send it privately, let us known, we’ll send you a PM for that.

Thank you!

Here is the complete build wrapper log. I don’t think anything there needs to be redacted:

Sun Feb 27 09:42:00 2022: build-wrapper, version 6.30 (linux-x86)
Sun Feb 27 09:42:00 2022: System name: Linux Nodename: kmlwg-tddamsrhel8.grpitsrv.com Release: 4.18.0-348.2.1.el8_5.x86_64 Version: #1 SMP Mon Nov 8 13:30:15 EST 2021 Machine: x86_64
Sun Feb 27 09:42:00 2022: socket path: /tmp/build-wrapper-socket.i9m2NL
Sun Feb 27 09:42:00 2022: dynamic library found: /home/brucea/work/git/libbede/target/sonar/build-wrapper-linux-x86/libinterceptor-i686.so
Sun Feb 27 09:42:00 2022: dynamic library found: /home/brucea/work/git/libbede/target/sonar/build-wrapper-linux-x86/libinterceptor-x86_64.so
Sun Feb 27 09:42:00 2022: dynamic library found: /home/brucea/work/git/libbede/target/sonar/build-wrapper-linux-x86/libinterceptor-haswell.so
Sun Feb 27 09:42:00 2022: cwd: </home/brucea/work/git/libbede>
Sun Feb 27 09:42:00 2022: command executed as: <./target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir target/bw-debug>
Sun Feb 27 09:42:00 2022: out-dir absolute path: </home/brucea/work/git/libbede/target/bw-debug>
Sun Feb 27 09:42:00 2022: command line received: <./target/debug/src/test/cpp/posixInterface/testsuite1_bede_posix>
Sun Feb 27 09:42:00 2022: env 0: <LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:>
Sun Feb 27 09:42:00 2022: env 1: <LD_LIBRARY_PATH=:/usr/local/lib:/usr/lib/oracle/10.2.0.4/client/lib:/home/brucea/work/depot/emma/main/lib:/opt/FJSVcbl/lib:/usr/local/lib64:/usr/local/lib:/usr/lib/oracle/10.2.0.4/client/lib:/home/brucea/work/depot/emma/main/lib:/opt/FJSVcbl/lib:/usr/local/lib64>
Sun Feb 27 09:42:00 2022: env 2: <SSH_CONNECTION=10.247.75.77 63816 172.16.12.63 22>
Sun Feb 27 09:42:00 2022: env 3: <IPADDRESS=>
Sun Feb 27 09:42:00 2022: env 4: <LANG=en_GB.UTF-8>
Sun Feb 27 09:42:00 2022: env 5: <HISTCONTROL=ignoredups>
Sun Feb 27 09:42:00 2022: env 6: <DISPLAY=localhost:10.0>
Sun Feb 27 09:42:00 2022: env 7: <HISTTIMEFORMAT=%F %T >
Sun Feb 27 09:42:00 2022: env 8: <HOSTNAME=kmlwg-tddamsrhel8.grpitsrv.com>
Sun Feb 27 09:42:00 2022: env 9: <OLDPWD=/home/brucea/work/git/libbede/src>
Sun Feb 27 09:42:00 2022: env 10: <KUBECONFIG=/home/brucea/notes/kubectl.conf>
Sun Feb 27 09:42:00 2022: env 11: <COLORTERM=truecolor>
Sun Feb 27 09:42:00 2022: env 12: <NO_AT_BRIDGE=1>
Sun Feb 27 09:42:00 2022: env 13: <which_declare=declare -f>
Sun Feb 27 09:42:00 2022: env 14: <EAM=/home/brucea/work/git/eam/TARDIS>
Sun Feb 27 09:42:00 2022: env 15: <CTEST_OUTPUT_ON_FAILURE=ON>
Sun Feb 27 09:42:00 2022: env 16: <XDG_SESSION_ID=4396>
Sun Feb 27 09:42:00 2022: env 17: <USER=brucea>
Sun Feb 27 09:42:00 2022: env 18: <SELINUX_ROLE_REQUESTED=>
Sun Feb 27 09:42:00 2022: env 19: <GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/d03b0d45_4774_4cd1_bbba_23b74c6e0b30>
Sun Feb 27 09:42:00 2022: env 20: <PWD=/home/brucea/work/git/libbede>
Sun Feb 27 09:42:00 2022: env 21: <SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass>
Sun Feb 27 09:42:00 2022: env 22: <HOME=/home/brucea>
Sun Feb 27 09:42:00 2022: env 23: <BOOST_LIBRARYDIR=/usr/lib64/boost169>
Sun Feb 27 09:42:00 2022: env 24: <CMAKE_PREFIX_PATH=/home/brucea/devtestlib/opt/rtm/cmake:/home/brucea/devtestlib/opt/rtm:/home/brucea/devtestlib/opt/rtm/cmake:/home/brucea/devtestlib/opt/rtm:>
Sun Feb 27 09:42:00 2022: env 25: <SSH_CLIENT=10.247.75.77 63816 22>
Sun Feb 27 09:42:00 2022: env 26: <SELINUX_LEVEL_REQUESTED=>
Sun Feb 27 09:42:00 2022: env 27: <https_proxy=http://127.0.0.1:3128>
Sun Feb 27 09:42:00 2022: env 28: <XDG_DATA_DIRS=/home/brucea/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share>
Sun Feb 27 09:42:00 2022: env 29: <http_proxy=http://127.0.0.1:3128>
Sun Feb 27 09:42:00 2022: env 30: <no_proxy=127.0.0.1,localhost,172.16.13.81>
Sun Feb 27 09:42:00 2022: env 31: <SSH_TTY=/dev/pts/0>
Sun Feb 27 09:42:00 2022: env 32: <NO_PROXY=127.0.0.1,localhost,172.16.13.81>
Sun Feb 27 09:42:00 2022: env 33: <MAIL=/var/spool/mail/brucea>
Sun Feb 27 09:42:00 2022: env 34: <SHELL=/bin/bash>
Sun Feb 27 09:42:00 2022: env 35: <TERM=xterm-256color>
Sun Feb 27 09:42:00 2022: env 36: <VTE_VERSION=5204>
Sun Feb 27 09:42:00 2022: env 37: <TC_LIB_DIR=/usr/lib64/tc>
Sun Feb 27 09:42:00 2022: env 38: <SELINUX_USE_CURRENT_RANGE=>
Sun Feb 27 09:42:00 2022: env 39: <INTTESTLIB_LIB_DIR=/home/brucea/devtestlib/opt/rtm/lib/inttestlib>
Sun Feb 27 09:42:00 2022: env 40: <GNOME_TERMINAL_SERVICE=:1.1>
Sun Feb 27 09:42:00 2022: env 41: <INTTESTLIB_REPO_DIR=/home/brucea/repo>
Sun Feb 27 09:42:00 2022: env 42: <SHLVL=2>
Sun Feb 27 09:42:00 2022: env 43: <GDK_BACKEND=x11>
Sun Feb 27 09:42:00 2022: env 44: <LOGNAME=brucea>
Sun Feb 27 09:42:00 2022: env 45: <DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-XFYFuQVSDq,guid=ad0c5417f67679fe043956f5620a1d8a>
Sun Feb 27 09:42:00 2022: env 46: <XDG_RUNTIME_DIR=/run/user/1000>
Sun Feb 27 09:42:00 2022: env 47: <VOD=/home/brucea/work/git/vodassetcreator/target/debug/test-install>
Sun Feb 27 09:42:00 2022: env 48: <PATH=/opt/cmake-3.18.1/bin:/opt/cmake-3.18.1/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/brucea/bin:/sbin:/usr/sbin:/opt/libreoffice/program:/opt/phantomjs-2.1.1-linux-x86_64/bin:/opt/libreoffice4.4/program:/opt/FJSVcbl/bin:/home/brucea/bin:/sbin:/usr/sbin:/opt/libreoffice/program:/opt/phantomjs-2.1.1-linux-x86_64/bin:/opt/libreoffice4.4/program:/opt/FJSVcbl/bin>
Sun Feb 27 09:42:00 2022: env 49: <PS1=${USER}@${HOST}:`$SPWDCMD`>>
Sun Feb 27 09:42:00 2022: env 50: <PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig>
Sun Feb 27 09:42:00 2022: env 51: <HISTSIZE=1000>
Sun Feb 27 09:42:00 2022: env 52: <ftp_proxy=http://127.0.0.1:3128>
Sun Feb 27 09:42:00 2022: env 53: <BOOST_INCLUDEDIR=/usr/include/boost169>
Sun Feb 27 09:42:00 2022: env 54: <LESSOPEN=||/usr/bin/lesspipe.sh %s>
Sun Feb 27 09:42:00 2022: env 55: <BASH_FUNC_which%%=() {  ( alias;
 eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@"
}>
Sun Feb 27 09:42:00 2022: env 56: <_=./target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64>
Sun Feb 27 09:42:00 2022: executing: <./target/debug/src/test/cpp/posixInterface/testsuite1_bede_posix>
Sun Feb 27 09:42:00 2022: initializing json file
Sun Feb 27 09:42:00 2022: process created with pid: 1364335
Sun Feb 27 09:42:00 2022: parent pid: 1364334
Sun Feb 27 09:42:00 2022: working directory: </home/brucea/work/git/libbede>
Sun Feb 27 09:42:00 2022: executable: </home/brucea/work/git/libbede/target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64>
Sun Feb 27 09:42:00 2022: argv[0]: <./target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64>
Sun Feb 27 09:42:00 2022: argv[1]: <-c>
Sun Feb 27 09:42:00 2022: argv[2]: <>
Sun Feb 27 09:42:00 2022: argv[3]: <./target/debug/src/test/cpp/posixInterface/testsuite1_bede_posix>
Sun Feb 27 09:42:00 2022: skipping process with pid: 1364335
Sun Feb 27 09:42:00 2022: process created with pid: 1364336
Sun Feb 27 09:42:00 2022: parent pid: 1364335
Sun Feb 27 09:42:00 2022: working directory: </home/brucea/work/git/libbede>
Sun Feb 27 09:42:00 2022: executable: </home/brucea/work/git/libbede/target/debug/src/test/cpp/posixInterface/testsuite1_bede_posix>
Sun Feb 27 09:42:00 2022: argv[0]: <./target/debug/src/test/cpp/posixInterface/testsuite1_bede_posix>
Sun Feb 27 09:42:00 2022: skipping process with pid: 1364336
Sun Feb 27 09:42:00 2022: process created with pid: 1364341
Sun Feb 27 09:42:00 2022: parent pid: 1364336
Sun Feb 27 09:42:00 2022: working directory: </home/brucea/work/git/libbede>
Sun Feb 27 09:42:00 2022: executable: </usr/bin/true>

I have a simple reproducer. Eliminating cppunit from enquires:


#include <cstdlib>
#include <cstdarg>
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <vector>

namespace
{

void appendArgv(
   std::vector< char * > &argv,
   va_list *ap
   )
{
   char *arg = 0;
   do
   {
      arg = va_arg(*ap, char *);
      argv.push_back(arg);
   }
   while (arg != 0);
}

void wrapexecl(const char *path, const char *arg0, ...)
{
   std::vector< char * > argv;
   va_list ap;
   va_start(ap, arg0);
   appendArgv(argv, &ap);
   va_end(ap);
   static const char* funName = "execl()";
   execve(path, &*argv.begin(), ::environ);
}

void testExeclGood1()
{
   std::cerr.flush();// prevent double write on error

   pid_t p;
   if (0 == (p = ::fork()))
   {// we are the child
      try
      {
         ::wrapexecl("/bin/true", "true", NULL);// should not return or throw
      }
      catch (const std::exception &e)
      {
         std::cerr << e.what() << std::endl;
         std::exit(1);
      }
      catch (...)
      {
         std::exit(1);
      }
      std::exit(2);
   }
   else
   {// we are the parent
      int status = 0;
      ::waitpid(p, &status, 0);
   }
};

}
   
int main (int argc, const char* argv[])
{
   testExeclGood1();
   return 0;
}
gcc -x c++ -std=c++17 -O0 -g3 -fprofile-arcs -ftest-coverage -o breaksonar breaksonar.cpp -lstdc++ &&
gdb ./target/sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 <<EOF 
run --out-dir bw-debug ./breaksonar
where
q
EOF
[Detaching after fork from child process 2428097]
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid

Program received signal SIGABRT, Aborted.
0x00007ffff7a4237f in raise () from /usr/lib64/libc.so.6
(gdb) #0  0x00007ffff7a4237f in raise () from /usr/lib64/libc.so.6
#1  0x00007ffff7a2cdb5 in abort () from /usr/lib64/libc.so.6
#2  0x00005555555cf08e in __gnu_cxx::__verbose_terminate_handler() [clone .cold] ()
#3  0x00005555555ddc5c in __cxxabiv1::__terminate(void (*)()) ()
#4  0x00005555555ddcc7 in std::terminate() ()
#5  0x00005555555dde29 in __cxa_throw ()
#6  0x00005555555d050b in std::__throw_logic_error(char const*) ()
#7  0x00005555555d6bec in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) ()
#8  0x00005555555d6aec in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct_aux<char const*>(char const*, char const*, std::__false_type) ()
#9  0x00005555555d6983 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*) ()
#10 0x00005555555d6565 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&) ()
#11 0x00005555555d373a in bwrapper::handleCapture(std::basic_ofstream<char, std::char_traits<char> >&, Capture&) ()
#12 0x00005555555d3ce7 in bwrapper::collectCaptures(int) ()
#13 0x00005555555d5ac0 in bwrapper::work(int, char* const*, char* const*) ()
#14 0x00005555555d1c95 in main ()
(gdb) A debugging session is active.

	Inferior 1 [process 2428091] will be killed.

Hi @KantarBruceAdams ,

in your code arg0 is not added to argv vector, you are not creating argv correctly, argv vector has size 1 containing a null pointer as the first element, as convention argv[0] should contain the program name. I am not sure this is intended, this is working because true is not doing anything with argv.

For va_args you have a list of char* arguments where a null pointer is used to terminate the list. The vector is used as a C++ wrapper for this C structure. So a valid empty argv vector will have exactly one element which is a null pointer with semantics meaning “no more arguments”.
I had the same thought when I first viewed this code. It just looks wrong until you think about how va_args works.

Hi @KantarBruceAdams,

as conventions argv should contain at least a valid argument being argv[0] containing the program name, so the array should have at least 2 elements: the program name and the null termination.

Why do you need to execute a program without an argv[0] value?

You are correct. I can reproduce the build wrapper crash without using va_args at all.
I guess you have used LD_PRELOAD or similar to replace execv and the build wrapper does not handle the case of argv[0]==nullptr.
Arguably a logic_error as a result of violating a pre-condition is the right behaviour already.
But this could be trapped in the interest of defensive coding.

I agree that argv[0] should be the program name so this should never happen.
We do not use argv[0]==nullptr except in this legacy test code which I can correct.

Hi @KantarBruceAdams ,

yes, it makes sense to protect from the case when argv[0] is not present, ticket created: [CPP-3598] build-wrapper-linux: Support case when programs are called without an argv[0] - SonarSource.

I wanted to first understand if it was coming from a known program or from a custom binary given that no one reported this issue in several years.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.