This is Veracrypt 1.23, running on Fedora 28 and compiled with:
/usr/bin/make -O -j4 -C src 'TC_EXTRA_CFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O0' 'TC_EXTRA_CXXFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O0' 'TC_EXTRA_LDFLAGS=-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld' NOSTRIP=1
When running the resulting binary, veracrypt crashes upon unlocking a volume, and for many other operations with:
/usr/include/c++/8/bits/stl_vector.h:932: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator [with _Tp = char; _Alloc = std::allocator<char>; std::vector<_Tp, _Alloc>::reference = char&; std::vector<_Tp, _Alloc>::size_type = long unsigned int]</char>: Assertion '__builtin_expect(__n < this->size(), true)' failed.
This is caused by this code in src/Core/Unix/CoreService.cpp, method CoreService::StartElevated (const CoreServiceRequest &request), around line 434:
vector <char> buffer (4096), errOutput (4096);
// allocates a vector of char, 4096 elements long, all initialized to zero
buffer.clear ();
// clears the vector, now buffer.size() == 0
bytesRead = read (fd, &buffer[0], buffer.capacity());
// and &buffer[0] is now an invalid memory reference
The solution is to omit the buffer.clear().
Alternately, it may be more optimal skip initializing the vector with zeroes by just doing:
vector<char> buffer;
buffer.reserve(4096);</char>
The bug is also prevent in 1.22.
I found more instances of this same issue in src/Platform/Unix/Process.cpp.
The attached patches closes both issues, by using the reserve() strategy outlined in the OP.
Note that the fix mentioned there is wrong, you should do:
vector<char> buffer(1);
buffer.reserve(4096);
So that you still have 4096 bytes to read data into the buffer and the &buffer[0] will still work, even with hardening, while avoiding initializing the vector with zeroes.</char>