Logging control, for Address Sanitizer PLUS Undefined Behavior Sanitizer? - address-sanitizer

Several of the Sanitizers (from either GCC or Clang) cannot be combined – i.e. used simultaneously in the same build, but Asan and Ubsan are combinable – i.e. I can build with “-fsanitize=address,undefined -fsanitize-recover=all …” and have an exe that performs the checks from both sanitizers. All good so far.
The LOGGING from the resulting executable seems problematic though.
In all cases, if ‘log_path’ is not set in the options, the defects all get reported on stderr. OK so far. Try to use log_path though, and things get strange:
For an exe built just with Asan, and setting ASAN_OPTIONS to include “log_path=./ASAN”, the Address Saniitizer defects will go into a file named ASAN.
For an exe built just with Ubsan, and setting UBSAN_OPTIONS to include “log_path=./UBSAN”, the Undefined Behavior defects will go into a file named UBSAN.
For an exe built with both Asan and Ubsan
o The Asan output goes to the designated log file, but the ubsan output goes only to stderr
o The above applies even if the log_path is only set via UBSAN_OPTIONS, and ASAN_OPTIONS is unset
o If log_path is set in both ASAN_OPTIONS and UBSAN_OPTIONS, the log_path used is the UBSAN one, yet only contains the ASAN results
Is there some hidden magic that will let both sanitizers write to the same defect log ?
To reproduce, use a simple testcase that has a defect for each sanitizer:
char *hello = "hello";
int main (int argc, char *argv[])
{
int x = 1;
x <<= 32; // Error: (1 << 32) can't be represented in a (32-bit) int
char some_char = hello [argc *10];
}
build and run: (g++ 7.3.0 used here, but other GCC versions, and also clang 7.1.0 have shown the same basic behavior)
Asan only - works as expected
g++ foo.C -fsanitize=address -fsanitize-recover=all -g
setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out
File ASAN. 29648 contains defect starting with
==29648==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000400aca at pc 0x0000004009a5 bp 0x7fffffffe090 sp 0x7fffffffe088
READ of size 1 at 0x000000400aca thread T0
0x4009a4 in main /tmp/foo.C:7
Ubsan only - works as expected
g++ foo.C -fsanitize=undefined -fsanitize-recover=all -g
setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out
File UBSAN.29675 contains
foo.C:6:6: runtime error: shift exponent 32 is too large for 32-bit type 'int'
Asan PLUS Ubsan - strange logging behavior
g++ foo.C -fsanitize=address,undefined -fsanitize-recover=all -g
setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out
ASAN_OPTIONS gets ignored, all defects reported on stderr. Now try setting UBSAN_OPTIONS:
setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out
File UBSAN.30352 contains ONLY the Asan defect:
==30352==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000400aca at pc 0x0000004009a5 bp 0x7fffffffe090 sp 0x7fffffffe088
READ of size 1 at 0x000000400aca thread T0
0x4009a4 in main /tmp/foo.C:7
and the Ubsan defect gets written only to stderr:
foo.C:6:6: runtime error: shift exponent 32 is too large for 32-bit type 'int'

and the Ubsan defect gets written only to stderr:
This sounds like a bug (or at least untested combination of settings).
That said, in general, ASan developers do not consider halt_on_error=0 to be a useful feature -- you should just fix the bugs as you find them, as it is pointless to look for UB after you've already overflown a buffer or used dangling memory. Anything could happen after that point.
So if you do file a bug about this strange logging behavior, I would expect that bug to receive little attention.

Have confirmed that this is actually a bug. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94328 applies

I have been searching for a way to use AddressSantizer with avr-gcc where there is no console to detect that the runtime code has crashed. I still have to experiment with it, but I believe this use case is a counter example to this feature not being useful.

Related

Intel oneAPI dpcpp compiler with google test

I'm kinda new to the world of Intel's HPC toolchain and I'm facing some troubles making even simple DPC++ application to work when gtest is used as a testing framework
This is the CMakeLists "structure" I'm following
cmake_minimum_required(VERSION 3.14)
project(foo)
set(CMAKE_CXX_COMPILER "dpcpp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3 -fsycl")
# add executables
# target linked libraries
# ...
option(ENABLE_TESTS ON)
if(ENABLE_TESTS)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_subdirectory(tests)
endif()
If I remove the last block, it compiles and runs as expected, otherwise I get the following error:
CMake Error at build/_deps/googletest-src/CMakeLists.txt:10 (project):
The CMAKE_CXX_COMPILER:
dpcpp
is not a full path and was not found in the PATH.
Tell CMake where to find the compiler by setting either the environment
variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
to the compiler, or to the compiler name if it is in the PATH.
-- Configuring incomplete, errors occurred!
See also "/home/u141905/foo/build/CMakeFiles/CMakeOutput.log".
See also "/home/u141905/foo/build/CMakeFiles/CMakeError.log".
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_CXX_COMPILER= /usr/bin/c++
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
make: *** [Makefile:2: all] Error 1
Please notice that dpcpp is correctly set, in fact I'm using Intel's devcloud platform.
Setting CXXto the output of whereis dpcpp produces the same error.
The only "workaround" (I doubt it is one though) I found is using clang++ instead (the version from Intel's llvm). Any help or suggestion is much appreciated, thanks in advance!
EDIT: after some more attempts, I noticed that if I set CMAKE_CXX_COMPILER just after fetching gtest, everything works fine. Anyway I don't understand why this happens and how can be properly fixed.
Use the path for dpcpp binary for setting the CMAKE_CXX_COMPILER instead of using"set(CMAKE_CXX_COMPILER "dpcpp")". After adding the path("/opt/intel/oneapi/compiler/2022.0.1/linux/bin/dpcpp") to the CMAKE_CXX_COMPILER, you can run the program successfully.
Please find the below CMakeLists.txt for setting the CMAKE_CXX_COMPILER:
project(foo)
set(CMAKE_CXX_COMPILER "/opt/intel/oneapi/compiler/2022.0.1/linux/bin/dpcpp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3 -fsycl")
# add executables
# target linked libraries
# ...
set(ENABLE_TESTS ON)
include(FetchContent)
if(ENABLE_TESTS)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_subdirectory(tests)
endif()
Thanks & Regards,
Hemanth
Did you run the source /opt/intel/oneapi/setvars.sh intel64 script? I.e. is dpcpp on your path before running cmake?

frama-c mingw __restrict__ keyword

I am new to Frama-C. I would like to run it under Windows enviroments. My compiler is gcc,mingw.
I have tryied to run same examples from Value Analysis tutorial by I have a problem with library header files.
I've found that it's not possible to run frama-c because restrict keyword. It shows error in string.h file
void * __cdecl memcpy(void * __restrict__ _Dst,const void * __restrict__ _Src,size_t _Size) __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
When I manually add #define restrict to all *.c files in SkeinProject
schneier.com/code/skein_NIST_CD_102610.zip
everything works correcly. By doing it by hand is not what I'm looking for.
Next step was to add argument -D__restrict__
frama-c -cpp-extra-args=-D__restrict__ -main=Init -val SHA3api_ref.c
[kernel] preprocessing with "gcc -C -E -I. -D__restrict__ SHA3api_ref.c"
../lib/gcc/i686-w64-mingw32/4.7.2/../../../../i686-w64-mingw32/include/string.h:41:[kernel] user error: syntax error
[kernel] user error: skipping file "SHA3api_ref.c" that has errors.
[kernel] Frama-C aborted because of an invalid user input.
I've also generated precompiled *.i files but error still the same.
gcc -E -D__restrict__ SHA3api_ref.c >SHA3api_ref.i
frama-c -main=Init -val SHA3api_ref.i
../lib/gcc/i686-w64-mingw32/4.7.2/../../../../i686-w64-mingw32/include/string.h:41:[kernel] user error: syntax error
[kernel] user error: skipping file "SHA3api_ref.i" that has errors.
[kernel] Frama-C aborted because of an invalid user input.
What can I do with it?
Your system headers contain non-standard syntax extensions that are not supported by Frama-C. This is normal, as the headers are often provided as part of a complete package with the compiler, so the headers and the compiler only need to work together, not to work with all the other programs that take C source code as input.
Generally speaking, you should always use the headers provided with Frama-C
instead of those from your system.
When using GCC or a compatible compiler such as Clang, this involves
passing the pre-processor the options -nostdinc and -I... where ...
stands for the place where Frama-C's headers were installed. This
location can be obtained from Frama-C with the option -print-share-path.
All in all, on a Unix system, it may look like:
frama-c -cpp-extra-args=-nostdinc -cpp-extra-args=-I`frama-c -print-share-path`/libc .....
Doing the same thing with Windows and MinGW follows the same idea but sometimes involves extra trouble due to the perpetual ambiguity between \ and / as directory separators.
Recently, Frank Dordowsky has been having trouble with using a very new GCC version to pre-process C files for Frama-C. That was only when using -pp-annot, but in any case, the solution was to switch to Clang as pre-processor.

frama-c jessie killed during VC generation

I'm trying to apply frama-c/jessie on a module of a proprietary safety critical system from our customer. The function under analysis is pretty big (image 700 uncommented lines count) with a lot of conditional statements as well as complex (&&, ||, etc).
I got this error message when I ran it on Ubuntu VM 64 bit machine. It appears Error 137 is related to memory size, etc. But I'm not quite sure.
Any suggestion for how to approach this error is greatly appreciated.
[
formal_verification]$ frama-c -jessie test.c
[kernel] preprocessing with "gcc -C -E -I. -dD test.c"
[jessie] Starting Jessie translation
[jessie] Producing Jessie files in subdir test.jessie
[jessie] File test.jessie/test.jc written.
[jessie] File test.jessie/test.cloc written.
[jessie] Calling Jessie tool in subdir tests.jessie
Generating Why function testFun
[jessie] Calling VCs generator.
gwhy-bin [...] why/test.why
Computation of VCs...
Killed
make: *** [test.stat] Error 137
with a lot of conditional statements as well as complex (&&, ||, etc).
You should use the so-called “fast WP” option when analyzing functions with lots of nested conditionals. Otherwise, the target does not even need to be very large to cause a blowup.
It happens to be the example in Jessie's manual for passing options to Why (it is really a Why option):
-jessie-why-opt=<s>
give an option to Why (e.g., -fast-wp)
You would therefore use -jessie-why-opt=-fast-wp.

Is it possible to display compiler warnings in Arduino?

I would like the Arduino IDE to display compiler warnings, and I would rather not have to compile once in the terminal for warnings, and again through Arduino to generate the hex file.
Holding down the shift key while clicking the "Verify" button shows intermediate commands, but none of their output. Is this possible without hacking the Arduino IDE?
Using Arduino IDE 1.6.4 and newer, the warning level can be easily adjusted via menu File → Preferences → Compiler warnings:.
Using Arduino AVR Boards, the compiler flags set via this option are:
"None": -w
"Default":
"More: -Wall
"All": -Wall -Wextra
The default compiler command line options include -w, which suppresses warnings, but you can change that by editing C:\Program Files (x86)\Arduino\hardware\arduino\avr\platform.txt. Since the libraries might contain warnings, but I want -Werror for myself, I removed the -w options, and then added to my source code:
#pragma GCC diagnostic error "-Wall"
#pragma GCC diagnostic error "-Werror"
This feature has been added to the latest Arduino source code, although is not yet in a released version (see Showing compilation warnings when verbose output is enabled).
It's planned to be included in the next major Arduino IDE release (version 1.0) which is currently planned for release at the end of October 2011. The current release candidate has this fix (as of October 25, 2011).
To enable compiler warnings from within the Arduino IDE, open menu File → Preferences, and then tick Show verbose output during: compilation and/or Show verbose output during: upload.
Most answers here seem to be outdated. From Arduino.app 1.5 onwards you must find the file preferences.txt (https://www.arduino.cc/en/Hacking/Preferences) and change the line compiler.warning_level=none to compiler.warning_level=all IMPORTANT: Quit Arduino first, edit, then start the IDE again.
The feature as described by Matthew, not only displays the warnings, but a lot of distracting information on how the compiler was called as well.
See the addendum to my question Have the Arduino IDE set compiler warnings to error. It implements the changes to the Arduino script:
-export PATH="${APPDIR}/java/bin:${PATH}"
+export ORGPATH="${APPDIR}/java/bin:${PATH}"
+export PATH="${APPDIR}/extra:${ORGPATH}"
And make the extra/avr-g++:
#! /usr/bin/env python
import os
import sys
import subprocess
checklibpat = [
'SoftwareSerial',
'GSM_GPRS',
]
werr = '-Werror'
wall = '-Wall'
cmd = ['avr-g++'] + sys.argv[1:]
os.environ['PATH'] = os.environ['ORGPATH']
fname = sys.argv[-2][:]
extend = False
warn = False
if cmd[-2].startswith('/tmp'):
extend = True
warn = True
if not extend:
for l in checklibpat:
if l in cmd[-2]:
warn = True
break
if warn:
#print len(fname), list(fname)
for i, c in enumerate(cmd):
if c == '-w':
cmd[i] = wall
break
if extend:
cmd.insert(1, werr)
## to enable deprecated stuff (Print.cpp) with gcc 4.7.0
#cmd.insert(1, '-D__PROG_TYPES_COMPAT__=1')
subprocess.call(cmd)
Comment out extend = True if you do not want the compiler to interpret warnings in your source as errors.

Is it possible to debug core file generated by a executable compiled without gdb flag?

Is it possible to debug core file generated by a executable compiled without gdb flag ?
If yes, any pointers or tutorials on it ?
Yes you can. It will not be easy though. I will give you an example.
Lets say that I have the following program called foo.c:
main()
{
*((char *) 0) = '\0';
}
I'll compile it and make sure that there is no symbols:
$ cc foo.c
$ strip a.out
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
Ok, time to run it:
$ ./a.out
Segmentation fault (core dumped)
Oops. There seems to be a bug. Let's start a debugger:
$ gdb ./a.out core
[..]
Reading symbols from /tmp/a.out...(no debugging symbols found)...done.
[..]
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x0804839c in ?? ()
(gdb) bt
#0 0x0804839c in ?? ()
#1 0xb7724e37 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6
#2 0x08048301 in ?? ()
Hmm, looks bad. No symbols. Can we figure out what happened?
(gdb) x/i $eip
=> 0x804839c: movb $0x0,(%eax)
Looks like it tried to store a byte with a value of zero to the memory location pointed by the EAX register. Why did it fail?
(gdb) p $eax
$1 = 0
(gdb)
It failed because the EAX register is pointing to a memory address zero and it tried to store a byte at that address. Oops!
Unfortunately I do not have pointers to any good tutorials. Searching for "gdb reverse engineering" gives some links which have potentially helpful bits and pieces.
Update:
I noticed the comment that this is about debugging a core dump at a customer. When you ship stripped binaries to a customer, you should always keep a debug version of that binary.
I would recommend not stripping and even giving the source code though. All code that I write goes to a customer with the source code. I have been on the customer side too many times facing an incompetent vendor which has shipped a broken piece of software but does not know how to fix it. It sucks.
This seems to be actually a duplicate of this question:
Debug core file with no symbols
There is some additional info there.
Yes, you can,
this is what people who i.e. write cracks are doing,
unfortunately i don't have the slides and documents of a course i followed at university anymore, but googling for reverse engineering or disassembly tutorials will give you some starting points. Also knowing your way around in assembly code is essential.
Our class was based on a book mainly chapter 1 & 3 but there is a new edition out now
Computer Systems: A programmer's perspective by R.E. Bryant and D.R. O'Hallaron
which explains the basics behind computer systems and also gives you good knowledge of the working of programs in systems.
Also when learning this be aware that 64bit cpus have different assembly code than 32bit cpu's, just in case.
If the program is compiled without -g flag,you cannot debug core file.
Otherwise you can do so as:
gdb executable corefile
More you can find at:
http://wwwpub.zih.tu-dresden.de/~mlieber/practical_debugging/04_gdb.pdf

Resources