From 7ebb7bfbd9b110d18860586957919143656709a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Thu, 22 Feb 2024 18:55:43 +0100 Subject: [PATCH] fixed `test/cli/fuzz_test.py` not triggering all the crashes / minimized fuzz data / fixed another fuzzing crash / fixed fuzzing timeout test (#6018) Not all the crashes were triggered by the test as the input has to be treated as C++. Also fixed another crash which was triggered by the reduced `crash-9ef938bba7d752386e24f2438c73cec66f6b972b`. --- lib/programmemory.cpp | 2 ++ ...h-15d71125ba17344f02417a9d46443cdaa30aa17f | Bin 100 -> 23 bytes ...h-26edfe9761d3b681c841dfe80398847dee332f83 | Bin 18 -> 4 bytes ...h-3ea64296c8518edb538e0047c3eba0792d5deeba | Bin 103 -> 27 bytes ...h-7ead2ccf9be8b03b2d9c8c82891f58081390a560 | Bin 106 -> 19 bytes ...h-8a24e81ac1d7627233a227e6cc156dd20d57b058 | 3 +- ...h-9ef938bba7d752386e24f2438c73cec66f6b972b | 13 +------- ...h-e4a26f2d7d0a73836bf086f54e48204d8914b95a | Bin 159 -> 18 bytes test/cli/fuzz_test.py | 4 +-- test/cli/testutils.py | 28 ++++++++++++++++-- 10 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index b5558233206..0f5d4cec960 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -274,6 +274,8 @@ static bool isBasicForLoop(const Token* tok) void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Token* endTok, const Settings* settings, bool then) { auto eval = [&](const Token* t) -> std::vector { + if (!t) + return std::vector{}; if (t->hasKnownIntValue()) return {t->values().front().intvalue}; MathLib::bigint result = 0; diff --git a/test/cli/fuzz-crash/crash-15d71125ba17344f02417a9d46443cdaa30aa17f b/test/cli/fuzz-crash/crash-15d71125ba17344f02417a9d46443cdaa30aa17f index a876152477b62c1c50124a83fdac1ec21cc9f65b..5d268fdf158b3d8b578b961d965eb5ba94bebb1c 100644 GIT binary patch literal 23 ecmXR>$kouS&de)ONQ{onR7lG&(y+GHtOWpB?FVK6 literal 100 zcmd1ID^bWz%*@l!5>3l5Qqag$NXs*{R>)MaQ7{Hl Q+S;069Uyt!vRt)X03awAk^lez diff --git a/test/cli/fuzz-crash/crash-26edfe9761d3b681c841dfe80398847dee332f83 b/test/cli/fuzz-crash/crash-26edfe9761d3b681c841dfe80398847dee332f83 index 37965deed0be75554c596307860cf4987f3c8b3a..ca4faea1d2e8ede3afdf6d21ae57ef746a71a1ed 100644 GIT binary patch literal 4 Lcma!!waEkk184zW literal 18 Zcma#%W-y3lU{J6rF3C*N%izjW001LL1TX*q diff --git a/test/cli/fuzz-crash/crash-3ea64296c8518edb538e0047c3eba0792d5deeba b/test/cli/fuzz-crash/crash-3ea64296c8518edb538e0047c3eba0792d5deeba index f096de3bf78f2d3cfd6f9fdd8db97552501f0059..a12e6966bd50c3118f103b6d167748678c66d6ab 100644 GIT binary patch literal 27 icmc~($kfoRE>Xy|PRlRS$h0-E&a^SM*4Eavt_1*bmk{00sXR-T(jq diff --git a/test/cli/fuzz-crash/crash-7ead2ccf9be8b03b2d9c8c82891f58081390a560 b/test/cli/fuzz-crash/crash-7ead2ccf9be8b03b2d9c8c82891f58081390a560 index 80a938891ac6ecaf058992612cecd407a43a606d..0de3f6a49b33372720a4c494844a1adc12be4a0e 100644 GIT binary patch literal 19 acmc~($kouS&de)ONQ{oPPPC1Vtpxx*V+L9P literal 106 zcmW-ZI|_g>6a-V}6l)i;@q<;&NkWPgDo-$i#5CgFUEOZjVWcGNQ8rWSTZ5C75q%#l sX;n&*Gvp&+IZhaXqXpYe7%Ze|>i^>%9lQjfqg?@I&exe38yS1_3u%iPR{#J2 diff --git a/test/cli/fuzz-crash/crash-8a24e81ac1d7627233a227e6cc156dd20d57b058 b/test/cli/fuzz-crash/crash-8a24e81ac1d7627233a227e6cc156dd20d57b058 index cfb3a566403..8810b86ac93 100644 --- a/test/cli/fuzz-crash/crash-8a24e81ac1d7627233a227e6cc156dd20d57b058 +++ b/test/cli/fuzz-crash/crash-8a24e81ac1d7627233a227e6cc156dd20d57b058 @@ -1,2 +1 @@ -#i~clude -sho main() -{ - std::veCtor items(2); - stdtryector::iterator iter; - for (iter -= items.begin(); i&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ter != items.end();) { - if (*iter == 2) { - iter = items.erase//(iter); - } else { - } - } -} +o n(){r<>items;t iter;for(&&){iter=items.g}} \ No newline at end of file diff --git a/test/cli/fuzz-crash/crash-e4a26f2d7d0a73836bf086f54e48204d8914b95a b/test/cli/fuzz-crash/crash-e4a26f2d7d0a73836bf086f54e48204d8914b95a index 89b9bf0f48b6c7dbef2981c39f35a120410c64ba..ba39dbb8588e3d7656bd70b8d6da7afadc410032 100644 GIT binary patch literal 18 ZcmXR>$kfoRPRlRSu(nQ9)7I9k1pqU<1vdZy literal 159 zcmd1gXJBAp1mcpS%DfVV+{Da0jhy^+O|EJ#1t7=-iX}!H$6AAw00EmqrZre1Ex$-X zBU8av!N6J}Q^7{T*jgbwO-)-{6D$kTni#E}84FfW;usuk9~4r80D=gn6`TpyS(I8* LT2unHrIrf-yLu`4 diff --git a/test/cli/fuzz_test.py b/test/cli/fuzz_test.py index 67a1e237fec..fe9b65d5278 100644 --- a/test/cli/fuzz_test.py +++ b/test/cli/fuzz_test.py @@ -11,7 +11,7 @@ def test_fuzz_crash(): fuzz_crash_dir = os.path.join(__script_dir, 'fuzz-crash') for f in os.listdir(fuzz_crash_dir): - ret, stdout, _ = cppcheck(['-q', '--enable=all', '--inconclusive', f], cwd=fuzz_crash_dir) + ret, stdout, _ = cppcheck(['-q', '--language=c++', '--enable=all', '--inconclusive', f], cwd=fuzz_crash_dir) if ret != 0: failures[f] = stdout @@ -27,7 +27,7 @@ def test_fuzz_timeout(): return for f in os.listdir(fuzz_timeout_dir): try: - ret, stdout, _ = cppcheck(['-q', '--enable=all', '--inconclusive', f], cwd=fuzz_timeout_dir, timeout=5) + ret, stdout, _ = cppcheck(['-q', '--language=c++', '--enable=all', '--inconclusive', f], cwd=fuzz_timeout_dir, timeout=5) except subprocess.TimeoutExpired: failures.append(f) diff --git a/test/cli/testutils.py b/test/cli/testutils.py index cef43267cae..22a646a224c 100644 --- a/test/cli/testutils.py +++ b/test/cli/testutils.py @@ -1,5 +1,6 @@ import logging import os +import signal import subprocess # Create Cppcheck project file @@ -78,7 +79,30 @@ def cppcheck(args, env=None, remove_checkers_report=True, cwd=None, cppcheck_exe logging.info(exe + ' ' + ' '.join(args)) p = subprocess.Popen([exe] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, cwd=cwd) - comm = p.communicate(timeout=timeout) + try: + comm = p.communicate(timeout=timeout) + return_code = p.returncode + p = None + except subprocess.TimeoutExpired: + import psutil + # terminate all the child processes + child_procs = psutil.Process(p.pid).children(recursive=True) + if len(child_procs) > 0: + for child in child_procs: + child.terminate() + try: + # call with timeout since it might be stuck + p.communicate(timeout=5) + p = None + except subprocess.TimeoutExpired: + pass + raise + finally: + if p: + # sending the signal to the process groups causes the parent Python process to terminate as well + #os.killpg(os.getpgid(p.pid), signal.SIGTERM) # Send the signal to all the process groups + p.terminate() + 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') if remove_checkers_report: @@ -95,7 +119,7 @@ def cppcheck(args, env=None, remove_checkers_report=True, cwd=None, cppcheck_exe stderr = '' elif stderr[pos - 1] == '\n': stderr = stderr[:pos] - return p.returncode, stdout, stderr + return return_code, stdout, stderr def assert_cppcheck(args, ec_exp=None, out_exp=None, err_exp=None, env=None):