-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactored SEH wrapper and added unit test (#7145)
- Loading branch information
Showing
13 changed files
with
251 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
if (BUILD_TESTS) | ||
add_subdirectory(signal) | ||
add_subdirectory(seh) | ||
|
||
file(GLOB hdrs "*.h") | ||
file(GLOB srcs "*.cpp") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
add_executable(test-sehwrapper | ||
test-sehwrapper.cpp | ||
${PROJECT_SOURCE_DIR}/cli/sehwrapper.cpp) | ||
target_include_directories(test-sehwrapper PRIVATE ${PROJECT_SOURCE_DIR}/cli ${PROJECT_SOURCE_DIR}/lib) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Cppcheck - A tool for static C/C++ code analysis | ||
* Copyright (C) 2007-2024 Cppcheck team. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include "config.h" | ||
|
||
#if defined(USE_WINDOWS_SEH) | ||
#include "sehwrapper.h" | ||
|
||
#include <cassert> | ||
#include <cfenv> | ||
#include <cstdlib> | ||
#include <cstring> | ||
|
||
#include <windows.h> | ||
|
||
static int my_assert() | ||
{ | ||
assert(false); | ||
return 0; | ||
} | ||
|
||
static int my_abort() | ||
{ | ||
abort(); | ||
} | ||
|
||
static int my_segv() | ||
{ | ||
// cppcheck-suppress nullPointer | ||
++*(int*)nullptr; | ||
return 0; | ||
} | ||
|
||
// TODO: how to catch these? | ||
static int my_fpe() | ||
{ | ||
const int fpe_res = std::feraiseexcept(FE_ALL_EXCEPT); | ||
if (fpe_res != 0) | ||
return 11; | ||
return sqrt(-1.0); // invalid operation | ||
} | ||
#endif | ||
|
||
int main(int argc, const char * const argv[]) | ||
{ | ||
#if defined(USE_WINDOWS_SEH) | ||
if (argc != 2) | ||
return 1; | ||
|
||
if (strcmp(argv[1], "assert") == 0) { | ||
_set_abort_behavior(0, _WRITE_ABORT_MSG); // suppress the "Debug Error!" MessageBox | ||
CALL_WITH_SEH_WRAPPER(my_assert()); | ||
} | ||
if (strcmp(argv[1], "abort") == 0) { | ||
_set_abort_behavior(0, _WRITE_ABORT_MSG); // suppress the "Debug Error!" MessageBox | ||
CALL_WITH_SEH_WRAPPER(my_abort()); | ||
} | ||
if (strcmp(argv[1], "fpe") == 0) { | ||
CALL_WITH_SEH_WRAPPER(my_fpe()); | ||
} | ||
if (strcmp(argv[1], "segv") == 0) { | ||
CALL_WITH_SEH_WRAPPER(my_segv()); | ||
} | ||
|
||
return 0; | ||
#else | ||
(void)argc; | ||
(void)argv; | ||
return 111; | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import subprocess | ||
import os | ||
import sys | ||
import pytest | ||
|
||
# TODO: only run on Windows | ||
|
||
def _lookup_cppcheck_exe(exe_name): | ||
# path the script is located in | ||
script_path = os.path.dirname(os.path.realpath(__file__)) | ||
|
||
if sys.platform == "win32": | ||
exe_name += ".exe" | ||
|
||
for base in (script_path + '/../../', './'): | ||
for path in ('', 'bin/', 'bin/debug/'): | ||
exe_path = base + path + exe_name | ||
if os.path.isfile(exe_path): | ||
print("using '{}'".format(exe_path)) | ||
return exe_path | ||
|
||
return None | ||
|
||
def _call_process(arg): | ||
exe = _lookup_cppcheck_exe('test-sehwrapper') | ||
if exe is None: | ||
raise Exception('executable not found') | ||
p = subprocess.Popen([exe, arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
comm = p.communicate() | ||
stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') | ||
stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') | ||
return p.returncode, stdout, stderr | ||
|
||
|
||
def test_assert(): | ||
exitcode, stdout, stderr = _call_process('assert') | ||
assert stdout == '' | ||
# Assertion failed: false, file S:\GitHub\cppcheck-fw\test\seh\test-sehwrapper.cpp, line 33 | ||
assert stderr.startswith("Assertion failed: false, file "), stderr | ||
assert stderr.endswith("test-sehwrapper.cpp, line 33\n"), stderr | ||
assert exitcode == 3 | ||
|
||
|
||
def test_abort(): | ||
exitcode, stdout, stderr = _call_process('abort') | ||
# nothing is written in case of abort() | ||
# it will show the "Debug Error!" MessageBox though which we suppress in the test | ||
assert stdout == '' | ||
assert stderr == '' | ||
assert exitcode == 3 | ||
|
||
|
||
def test_segv(): | ||
exitcode, stdout, stderr = _call_process('segv') | ||
assert stderr == '' | ||
lines = stdout.splitlines() | ||
assert lines[0].startswith('Internal error: Access violation (instruction: 0x'), lines[0] | ||
assert lines[0].endswith(') reading from 0x0000000000000000'), lines[0] | ||
assert lines[1].startswith('0. 0x'), lines[1] | ||
assert lines[1].endswith(' in my_segv'), lines[1] | ||
assert lines[2].startswith('1. 0x'), lines[2] | ||
assert lines[2].endswith(' in main'), lines[2] | ||
assert lines[len(lines)-1] == 'Please report this to the cppcheck developers!' | ||
assert exitcode == 4294967295 # returns -1 | ||
|
||
|
||
# TODO: make this work | ||
@pytest.mark.skip | ||
def test_fpe(): | ||
exitcode, stdout, stderr = _call_process('fpe') | ||
assert stderr == '' | ||
lines = stdout.splitlines() | ||
assert lines[0].startswith('Internal error: cppcheck received signal SIGFPE - FPE_FLTDIV (at 0x7f'), lines[0] | ||
assert lines[0].endswith(').'), lines[0] | ||
assert lines[1] == 'Callstack:' | ||
assert lines[2].endswith('my_fpe()'), lines[2] | ||
assert lines[len(lines)-1] == 'Please report this to the cppcheck developers!' | ||
assert exitcode == 4294967295 # returns -1 |
Oops, something went wrong.