Add segfault-focused fuzzing test without GNU parallel dependency

Replaces script.sh and script3.sh with new comprehensive fuzzing test:
- Tests all system binaries with random flag combinations
- Uses 22 diverse fuzz files (malformed JSON/XML, binary garbage, edge cases)
- Reports only real crashes (SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS)
- Bash background jobs for parallelization (max 10 jobs, no GNU parallel)
- Skips GUI apps (GNOME, KDE, Qt, X11) and GNU parallel tools
- Renamed sql.txt to sql_injection.txt to avoid socket conflicts
- Removed parallel package dependency from main.fmf

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Petr Sklenar 2026-04-20 12:21:29 +02:00
commit 68f7483be4
6 changed files with 386 additions and 296 deletions

View file

@ -0,0 +1,7 @@
Description: test
Owner: Petr Sklenar <psklenar@redhat.com>
RunFor:
RunTest: ./runtest.sh
Path: /mnt/tests/system-in-use/run-them-all
Requires: parallel
TestTime: 6h

View file

@ -5,8 +5,6 @@ test: ./runtest.sh
framework: beakerlib
duration: 6h
enabled: false
recommend:
- parallel
adjust:
- when: "force == yes"
enabled: true

View file

@ -1,5 +1,4 @@
#!/usr/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Author: psklenar@redhat.com <psklenar@redhat.com>
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -11,12 +10,8 @@ rlJournalStart
CORES_COUNT_OLD=$(coredumpctl list|wc -l)
rlPhaseEnd
rlPhaseStartTest "run version 1"
bash script.sh
rlPhaseEnd
rlPhaseStartTest "run version 3"
bash script3.sh
rlPhaseStartTest "run"
bash try-all-binaries-help-options.sh
rlPhaseEnd
rlPhaseStartTest

View file

@ -1,91 +0,0 @@
#!/bin/bash
# see parallel , for athor note!
mkdir -p ~/.parallel
touch ~/.parallel/will-cite
# --- CONFIGURATION ---
TARGET_DIRS="/usr/bin /usr/sbin"
LOG_FILE="smoke_test_$(date +%Y%m%d_%H%M%S).log"
SUMMARY_FILE="summary_report.txt"
# LIST OF BINARIES TO SKIP
# Allready reported
SKIP_LIST=(
"/usr/bin/unoconv"
"/usr/bin/ibus-setup"
"/usr/bin/ffmpeg"
"/usr/bin/ffprobe"
"/usr/bin/ffplay"
"/usr/bin/gnome-keyring-3"
"/usr/bin/gnome-boxes"
"/usr/bin/ibus-setup"
"/usr/bin/unix_chkpwd"
"/usr/bin/unix_update"
"/usr/bin/cracklib-check"
"/usr/bin/code2color"
"/usr/bin/fsidd"
"/usr/bin/stund"
"/usr/bin/beakerlib"
"/usr/bin/vimcolor"
)
# Prepare skip pattern for grep
SKIP_PATTERN=$(printf "|%s" "${SKIP_LIST[@]}")
SKIP_PATTERN=${SKIP_PATTERN:1}
# Attempt to increase file descriptor limits
ulimit -n 65535 2>/dev/null
echo "--- STARTING DESTRUCTION ENGINE ---"
echo "Logging to: $LOG_FILE"
echo "Skipping known issues: ${SKIP_LIST[*]}"
echo "-----------------------------------"
# Initialize log file
> "$LOG_FILE"
# THE CORE ENGINE
# 1. Find executables
# 2. Filter out skipped binaries
# 3. Run in parallel (100 jobs at once, 5s timeout)
find $TARGET_DIRS -maxdepth 1 -executable -type f | grep -vE "($SKIP_PATTERN)" | parallel --no-notice --jobs 100 --timeout 5 --tag \
"tmp_err=\$(mktemp); \
yes 'chaos_input' | {} --help >/dev/null 2>\"\$tmp_err\"; \
EXIT_CODE=\$?; \
if grep -Ei 'traceback|stack dump|segfault|exception|core dumped|assertion|invalid pointer' \"\$tmp_err\"; then \
{ \
echo '=================================================='; \
echo 'COMMAND: {}'; \
echo 'TIMESTAMP: \$(date +%H:%M:%S)'; \
echo 'EXIT CODE: \$EXIT_CODE'; \
echo 'ERROR LOG:'; \
cat \"\$tmp_err\"; \
echo '=================================================='; \
echo ''; \
} >> $LOG_FILE; \
fi; \
rm -f \"\$tmp_err\""
# --- POST-PROCESSING & STATISTICS ---
echo "--- ANALYZING RESULTS ---"
TOTAL_CRASHES=$(grep -c "COMMAND:" "$LOG_FILE" 2>/dev/null || echo 0)
SEGFAULTS=$(grep -ci "segfault" "$LOG_FILE" 2>/dev/null || echo 0)
TRACEBACKS=$(grep -ci "traceback" "$LOG_FILE" 2>/dev/null || echo 0)
{
echo "SMOKE TEST SUMMARY - $(date)"
echo "------------------------------------------"
echo "Total binaries tested (approx): $(find $TARGET_DIRS -maxdepth 1 -executable | wc -l)"
echo "Skipped binaries: ${#SKIP_LIST[@]}"
echo "Binaries with detected issues: $TOTAL_CRASHES"
echo "Segmentation faults: $SEGFAULTS"
echo "Python/Other Tracebacks: $TRACEBACKS"
echo ""
echo "TOP 10 DETECTED ISSUES:"
grep "COMMAND:" "$LOG_FILE" | head -n 10
} > "$SUMMARY_FILE"
echo "Done! Summary in $SUMMARY_FILE, full details in $LOG_FILE."

View file

@ -1,196 +0,0 @@
#!/bin/bash
# Fuzzing audit of /usr/bin and /usr/sbin: runs each binary with random options
# from --help, using input files or stdin. Logs crashes (segfault, traceback).
# Dumps coredumps for failed binaries. Output: $HOME/fuzz_lab/fuzz_*.log, summary.txt, coredumps/
set -uo pipefail
# === CONFIGURATION ===
BIN_DIRS="/usr/bin /usr/sbin"
WORKSPACE="${HOME}/fuzz_lab"
LOG_FILE="${WORKSPACE}/fuzz_$(date +%Y%m%d_%H%M%S).log"
SUMMARY_FILE="${WORKSPACE}/summary.txt"
RUNS_PER_BIN=15
MAX_JOBS=1 # run this many binaries in parallel (background jobs)
TIMEOUT_SEC=5 # seconds before SIGTERM - more time for crashes to manifest
KILL_AFTER=15 # seconds before SIGKILL after SIGTERM
# Skip list: binary names only (use .re: for regex)
SKIP_NAMES=(
bash rm dd mkfs reboot shutdown poweroff dnf yum rpm vi nano vim login kill pkill
sfdisk fdisk parted systemd-ask-password sulogin chronyc chronyd xfs_freeze
unoconv ibus-setup ffmpeg ffprobe ffplay gnome-keyring-3 gnome-boxes
unix_chkpwd unix_update cracklib-check code2color fsidd stund vimcolor
ip nmcli nmtui ifconfig route arp iptables ip6tables nft firewall-cmd
dhclient dhcpcd wpa_supplicant brctl bridge aws
'.re:^beakerlib|gnome|gui|qt|wayland|vlc'
'.re:^ip-|^nm-|^NetworkManager|^ovs-'
# '.re:^[jJ]'
'.re:^[iI]'
'.re:^[hH]'
# '.re:^[a-sA-S]'
)
# Debug: run only binaries whose name starts with this letter (e.g. "g"); empty = run all
DEBUG_LETTER=""
should_skip() {
local name=$(basename "$1") s
for s in "${SKIP_NAMES[@]}"; do
if [[ "$s" == .re:* ]]; then
[[ "$name" =~ ${s#.re:} ]] && return 0
else
[[ "$name" == "$s" ]] && return 0
fi
done
return 1
}
# === SETUP ===
mkdir -p "$WORKSPACE"
ulimit -n 65535 2>/dev/null || true
# Debug: if script stops unexpectedly, check these files:
# current_run.txt = last BIN + ARGS being executed (which cmd caused the stop)
# script_stopped.txt, progress_*.txt
# Tip: run in tmux/screen to survive SSH disconnects (SIGHUP)
STOP_LOG="$WORKSPACE/script_stopped.txt"
PROGRESS_LOG="$WORKSPACE/progress_$$.txt"
CURRENT_RUN_FILE="$WORKSPACE/current_run.txt"
trap 'ec=$?; echo "$(date -Iseconds) EXIT code=$ec line=$LINENO" >> "$STOP_LOG"' EXIT
trap 'echo "$(date -Iseconds) SIGNAL (HUP=disconnect?)" >> "$STOP_LOG"; exit 129' HUP INT TERM
trap '' TSTP TTIN TTOU # ignore Ctrl+Z / job-control from fuzzed binaries
# Test data
printf 'line1\nline2\n123\n' > "$WORKSPACE/input.txt"
touch "$WORKSPACE/empty.txt"
# Build list of binaries to test
ALL_BINS=()
while IFS= read -r b; do
should_skip "$b" && continue
if [[ -n "$DEBUG_LETTER" ]]; then
name=$(basename "$b")
[[ "${name,,}" != "${DEBUG_LETTER,,}"* ]] && continue
fi
ALL_BINS+=("$b")
done < <(find $BIN_DIRS -maxdepth 1 -executable -type f 2>/dev/null | sort -u)
TOTAL=${#ALL_BINS[@]}
[[ -n "$DEBUG_LETTER" ]] && echo "DEBUG: only binaries starting with '$DEBUG_LETTER'"
echo "=== FUZZING AUDIT (parallel, max $MAX_JOBS jobs) ==="
echo "Binaries to test: $TOTAL"
echo "Log: $LOG_FILE"
echo "===================="
> "$LOG_FILE"
RESULT_DIR="$WORKSPACE/result_$$"
mkdir -p "$RESULT_DIR"
process_bin() {
local bin="$1" name flags err ex pkg r n chosen args use_stdin
name=$(basename "$bin")
local out="$RESULT_DIR/$(echo "$bin" | tr '/' '_').log"
flags=()
flags_tmp=$(mktemp)
timeout -k $KILL_AFTER ${TIMEOUT_SEC}s "$bin" --help 2>&1 | tr -d '\0' |
grep -a -oE -e '--[a-zA-Z0-9][a-zA-Z0-9_-]*' -e '-[a-zA-Z0-9]' |
grep -a -vE 'help|version|usage' | sort -u | head -n 20 > "$flags_tmp"
while IFS= read -r f; do flags+=("$f"); done < "$flags_tmp"
rm -f "$flags_tmp"
[[ ${#flags[@]} -eq 0 ]] && flags=(-v -a -q -f)
for ((r=0; r<RUNS_PER_BIN; r++)); do
n=$((1 + RANDOM % 3))
chosen=$(printf '%s\n' "${flags[@]}" | shuf -n "$n" | tr '\n' ' ')
args="$chosen"
use_stdin=0
case $((RANDOM % 4)) in
0) args+=" $WORKSPACE/input.txt" ;;
1) args+=" $WORKSPACE/empty.txt" ;;
2) args+=" -"; use_stdin=1 ;;
3) ;;
esac
err=$(mktemp)
echo "BIN: $bin | ARGS: $args" > "$CURRENT_RUN_FILE"
(
trap '[[ $? -gt 128 ]] && echo "BIN: $bin | ARGS: $args" >&2' EXIT
ulimit -v 307200 2>/dev/null || true
export MALLOC_CHECK_=3 LC_ALL=C
unset DISPLAY WAYLAND_DISPLAY
if [[ $use_stdin -eq 1 ]]; then
timeout -k $KILL_AFTER --foreground ${TIMEOUT_SEC}s bash -c "cat $WORKSPACE/input.txt | $bin $args" >/dev/null 2>"$err"
else
timeout -k $KILL_AFTER --foreground ${TIMEOUT_SEC}s bash -c "$bin $args" >/dev/null 2>"$err"
fi
)
ex=$?
if [[ $ex -gt 128 ]] || grep -qiE 'traceback|segfault|core dumped|assertion|invalid pointer' "$err" 2>/dev/null; then
pkg=$(rpm -qf "$bin" --qf '%{NAME}' 2>/dev/null || echo "unknown")
{
echo "---"
echo "CMD: $bin $args"
echo "PKG: $pkg | EXIT: $ex"
head -n 10 "$err"
echo ""
} >> "$out"
fi
rm -f "$err"
done
}
# === PARALLEL LOOP (background jobs, no GNU parallel) ===
for ((i=0; i<TOTAL; i+=MAX_JOBS)); do
for ((j=0; j<MAX_JOBS && i+j<TOTAL; j++)); do
process_bin "${ALL_BINS[i+j]}" &
done
wait
echo -n "."
echo "$(date -Iseconds) batch $((i/MAX_JOBS + 1)) done, tested up to $((i + j))/$TOTAL" >> "$PROGRESS_LOG"
done
# Merge result files into LOG_FILE
for f in "$RESULT_DIR"/*.log; do
[[ -f "$f" ]] && cat "$f" >> "$LOG_FILE"
done
rm -rf "$RESULT_DIR"
tested=$TOTAL
issues=$( (grep -c "CMD:" "$LOG_FILE" 2>/dev/null || echo 0) | head -1 | tr -d '\n')
issues=${issues:-0}
echo ""
# === SUMMARY ===
{
echo "FUZZ AUDIT SUMMARY - $(date)"
echo "=========================="
echo "Binaries tested: $tested"
echo "Issues found: $issues"
echo ""
if [[ $issues -gt 0 ]]; then
echo "TOP PACKAGES:"
grep "PKG:" "$LOG_FILE" | sed 's/.*PKG: //' | cut -d'|' -f1 | sort | uniq -c | sort -rn | head -10
echo ""
echo "SAMPLE COMMANDS:"
grep "CMD:" "$LOG_FILE" | tail -5
fi
} > "$SUMMARY_FILE"
# === COREDUMP DUMP for each failed binary ===
if [[ $issues -gt 0 ]]; then
COREDUMP_DIR="$WORKSPACE/coredumps"
mkdir -p "$COREDUMP_DIR"
grep "CMD:" "$LOG_FILE" | sed 's/^CMD: //' | awk '{print $1}' | sort -u | while read -r bin; do
[[ -z "$bin" ]] && continue
name=$(basename "$bin")
out="$COREDUMP_DIR/coredump_${name}.dump"
if coredumpctl dump "$bin" -o "$out" 2>/dev/null; then
echo "Dumped coredump for $bin -> $out"
fi
done
fi
echo "Done. Issues: $issues | Summary: $SUMMARY_FILE"

View file

@ -0,0 +1,377 @@
#!/bin/bash
# Segfault-Focused Fuzz Test
# Extracts flags from --help, tests with diverse fuzz files
# Reports ONLY real crashes (segfault, abort, illegal instruction, etc.)
set -uo pipefail
# === CONFIGURATION ===
BIN_DIRS="/usr/bin /usr/sbin"
WORKSPACE="${HOME}/fuzz_lab"
LOG_FILE="${WORKSPACE}/segfault_fuzz_$(date +%Y%m%d_%H%M%S).log"
SUMMARY_FILE="${WORKSPACE}/segfault_summary.txt"
RUNS_PER_BIN=20 # More runs per binary for better coverage
MAX_PARALLEL=10 # Maximum parallel jobs (no rush)
TIMEOUT_SEC=5 # Timeout before SIGTERM
KILL_AFTER=10 # Timeout before SIGKILL
# === SKIP LIST ===
SKIP_NAMES=(
# Destructive/dangerous
bash rm dd mkfs reboot shutdown poweroff halt init telinit
sfdisk fdisk parted cfdisk gdisk sgdisk mkswap
# System critical
login kill pkill killall systemd-ask-password sulogin chronyc chronyd
xfs_freeze fsck e2fsck xfs_repair
# Network tools
ip nmcli nmtui ifconfig route arp brctl bridge
iptables ip6tables nft ebtables arptables firewall-cmd
dhclient dhcpcd wpa_supplicant hostapd
# Package managers
dnf yum rpm zypper apt apt-get dpkg pacman
# Editors
vi vim nvim nano emacs ed
# Cloud tools
aws gcloud kubectl docker podman
# GNU parallel tools (creates sockets, interferes with fuzz files)
sql env_parallel parallel niceload parsort
# Already reported bugs
unoconv ibus-setup ffmpeg ffprobe ffplay
gnome-keyring-3 gnome-boxes unix_chkpwd unix_update
cracklib-check code2color fsidd stund vimcolor
# GUI/Interactive (regex patterns)
'.re:^gnome-|^gtk|^gdk|^gio-|^gsettings'
'.re:^kde|^plasma|^kwin|^dolphin|^konsole'
'.re:^xfce|^mate-|^cinnamon|^lxde|^lxqt'
'.re:^qt|^Qt|^wayland|^weston'
'.re:^X|^x11|^xorg|^xinit|^xterm'
'.re:^vlc|^totem|^rhythmbox|^brasero'
'.re:^firefox|^thunderbird|^chrome|^chromium'
'.re:^gedit|^kate|^kwrite|^pluma'
'.re:gui|^beakerlib'
'.re:^ip-|^nm-|^NetworkManager|^ovs-'
'.re:^[iI]'
'.re:^[hH]'
)
# === HELPER FUNCTIONS ===
should_skip() {
local name=$(basename "$1") s
for s in "${SKIP_NAMES[@]}"; do
if [[ "$s" == .re:* ]]; then
[[ "$name" =~ ${s#.re:} ]] && return 0
else
[[ "$name" == "$s" ]] && return 0
fi
done
return 1
}
# === SETUP ===
mkdir -p "$WORKSPACE"
ulimit -n 65535 2>/dev/null || true
# === DIVERSE FUZZ FILES ===
echo "Creating fuzz test files..."
# 1. Empty file
touch "$WORKSPACE/empty.dat"
# 2. Small text file
printf 'line1\nline2\n123\ntest\n' > "$WORKSPACE/small.txt"
# 3. Malformed JSON
cat > "$WORKSPACE/bad.json" <<'EOF'
{"key": "value", "broken": [1, 2, 3,
EOF
# 4. Malformed XML
cat > "$WORKSPACE/bad.xml" <<'EOF'
<?xml version="1.0"?>
<root>
<unclosed>
<tag>value
EOF
# 5. Binary garbage
dd if=/dev/urandom of="$WORKSPACE/random.bin" bs=1K count=10 2>/dev/null
# 6. Binary with null bytes
printf '\x00\x00\xff\xff\xde\xad\xbe\xef\x00\x00' > "$WORKSPACE/nulls.bin"
# 7. Large file (triggers buffer issues)
dd if=/dev/zero of="$WORKSPACE/large.dat" bs=1M count=50 2>/dev/null
# 8. UTF-8 edge cases
printf '\xc3\x28\xe2\x82\x28\xf0\x28\x8c\x28' > "$WORKSPACE/bad_utf8.txt"
# 9. Format string attempts
printf '%%s%%s%%s%%n%%x%%x' > "$WORKSPACE/format.txt"
# 10. Path traversal patterns
printf '../../../etc/passwd\n..\\..\\..\\windows\\system32' > "$WORKSPACE/paths.txt"
# 11. SQL-like injection patterns
printf "' OR 1=1 --\n\"; DROP TABLE users; --" > "$WORKSPACE/sql_injection.txt"
# 12. Command injection patterns
printf '; ls -la\n| cat /etc/passwd\n`whoami`' > "$WORKSPACE/cmd.txt"
# 13. Very long line (buffer overflow test)
python3 -c "print('A' * 100000)" > "$WORKSPACE/longline.txt"
# 14. Many short lines
seq 1 100000 > "$WORKSPACE/manylines.txt"
# 15. Mixed binary/text
cat "$WORKSPACE/small.txt" "$WORKSPACE/random.bin" > "$WORKSPACE/mixed.dat"
# 16. Compressed data patterns
printf '\x1f\x8b\x08\x00\x00\x00\x00\x00' > "$WORKSPACE/gzip.dat"
printf '\x50\x4b\x03\x04' > "$WORKSPACE/zip.dat"
# 17. Image-like headers (but corrupted)
printf '\xff\xd8\xff\xe0\x00\x10JFIF' > "$WORKSPACE/fake.jpg"
printf '\x89PNG\r\n\x1a\n' > "$WORKSPACE/fake.png"
# 18. ELF header (but truncated)
printf '\x7fELF\x02\x01\x01\x00' > "$WORKSPACE/fake.elf"
# 19. Script with shebang
printf '#!/bin/sh\necho test' > "$WORKSPACE/script.sh"
# 20. Just dashes (flag-like)
printf -- '---\n-\n--help\n--version\n-v\n' > "$WORKSPACE/dashes.txt"
# List of fuzz files (as string for export)
FUZZ_FILE_COUNT=22
FUZZ_FILE_NAMES="empty.dat small.txt bad.json bad.xml random.bin nulls.bin large.dat bad_utf8.txt format.txt paths.txt sql_injection.txt cmd.txt longline.txt manylines.txt mixed.dat gzip.dat zip.dat fake.jpg fake.png fake.elf script.sh dashes.txt"
# Tracking files
STOP_LOG="$WORKSPACE/script_stopped.txt"
CURRENT_RUN_FILE="$WORKSPACE/current_run.txt"
trap 'ec=$?; echo "$(date -Iseconds) EXIT code=$ec" >> "$STOP_LOG"' EXIT
trap 'echo "$(date -Iseconds) SIGNAL RECEIVED" >> "$STOP_LOG"; exit 129' HUP INT TERM
# Build list of binaries to test
echo "=== BUILDING BINARY LIST ==="
ALL_BINS=()
while IFS= read -r b; do
should_skip "$b" && continue
ALL_BINS+=("$b")
done < <(find $BIN_DIRS -maxdepth 1 -executable -type f 2>/dev/null | sort -u)
TOTAL=${#ALL_BINS[@]}
echo "Total binaries to test: $TOTAL"
echo "Runs per binary: $RUNS_PER_BIN"
echo "Max parallel jobs: $MAX_PARALLEL"
echo "Fuzz files: $FUZZ_FILE_COUNT"
echo "Log file: $LOG_FILE"
echo "===================="
> "$LOG_FILE"
fuzz_binary() {
local bin="$1"
local name=$(basename "$bin")
local pkg=$(rpm -qf "$bin" --qf '%{NAME}' 2>/dev/null || echo "unknown")
# Extract flags from --help
local flags=()
local flags_tmp=$(mktemp)
timeout -k 5 3s "$bin" --help 2>&1 | tr -d '\0' |
grep -aoE -e '--[a-zA-Z0-9][a-zA-Z0-9_-]*' -e '-[a-zA-Z0-9]' |
grep -avE 'help|version|usage' | sort -u | head -n 50 > "$flags_tmp"
while IFS= read -r f; do flags+=("$f"); done < "$flags_tmp"
rm -f "$flags_tmp"
# Fallback if no flags found
[[ ${#flags[@]} -eq 0 ]] && flags=(-v -a -q -f -d -i -o)
# Run multiple fuzz iterations
for ((r=0; r<RUNS_PER_BIN; r++)); do
# Randomly select 1-4 flags
local n=$((1 + RANDOM % 4))
local chosen=$(printf '%s\n' "${flags[@]}" | shuf -n "$n" | tr '\n' ' ')
local args="$chosen"
local use_stdin=0
# Detect if flags suggest file input
local needs_file=0
if [[ "$chosen" =~ (--file|--input|--config|--from|-f|-i|-c|--load|--read) ]]; then
needs_file=1
fi
# Add fuzz file intelligently
if [[ $needs_file -eq 1 ]] || [[ $((RANDOM % 3)) -eq 0 ]]; then
# Pick random fuzz file from workspace
local fuzz_files_arr=($FUZZ_FILE_NAMES)
local fuzz_idx=$((RANDOM % ${#fuzz_files_arr[@]}))
local fuzz_file="$WORKSPACE/${fuzz_files_arr[$fuzz_idx]}"
if [[ $((RANDOM % 5)) -eq 0 ]]; then
# Sometimes stdin
use_stdin=1
args+=" -"
else
# File argument
args+=" $fuzz_file"
fi
fi
local err=$(mktemp)
local exit_code=0
# Track current execution
echo "BIN: $bin | ARGS: $args | PKG: $pkg" > "$CURRENT_RUN_FILE"
# Execute with safety limits
(
ulimit -v 512000 2>/dev/null || true # 500MB memory limit
ulimit -f 102400 2>/dev/null || true # 100MB file size limit
export MALLOC_CHECK_=3 LC_ALL=C
unset DISPLAY WAYLAND_DISPLAY
if [[ $use_stdin -eq 1 ]]; then
local first_fuzz="$WORKSPACE/$(echo $FUZZ_FILE_NAMES | awk '{print $1}')"
timeout -k $KILL_AFTER --foreground ${TIMEOUT_SEC}s bash -c \
"cat $first_fuzz | $bin $args" >/dev/null 2>"$err"
else
timeout -k $KILL_AFTER --foreground ${TIMEOUT_SEC}s \
"$bin" $args >/dev/null 2>"$err"
fi
)
exit_code=$?
# ONLY report real crashes (not usage errors)
# Exit codes: 139=SIGSEGV, 134=SIGABRT, 136=SIGFPE, 132=SIGILL, 133=SIGTRAP, 135=SIGBUS
if [[ $exit_code -eq 139 ]] || [[ $exit_code -eq 134 ]] || [[ $exit_code -eq 136 ]] || \
[[ $exit_code -eq 132 ]] || [[ $exit_code -eq 133 ]] || [[ $exit_code -eq 135 ]] || \
grep -qiE 'segmentation fault|segfault|core dumped|double free|heap corruption|buffer overflow|stack smashing|memory corruption|use after free|ASAN|UBSAN' "$err" 2>/dev/null; then
# Log the crash
{
echo "=================================================="
echo "REAL CRASH DETECTED"
echo "COMMAND: $bin $args"
echo "PACKAGE: $pkg"
echo "EXIT CODE: $exit_code"
case $exit_code in
139) echo "SIGNAL: SIGSEGV (Segmentation fault)" ;;
134) echo "SIGNAL: SIGABRT (Abort)" ;;
136) echo "SIGNAL: SIGFPE (Floating point exception)" ;;
132) echo "SIGNAL: SIGILL (Illegal instruction)" ;;
133) echo "SIGNAL: SIGTRAP (Trace trap)" ;;
135) echo "SIGNAL: SIGBUS (Bus error)" ;;
esac
echo "TIMESTAMP: $(date -Iseconds)"
echo "--------------------------------------------------"
echo "ERROR OUTPUT:"
head -n 30 "$err"
echo "=================================================="
echo ""
}
fi
rm -f "$err"
done
}
# === PARALLEL EXECUTION ===
echo "Starting parallel fuzzing (segfaults only)..."
running_jobs=0
for bin in "${ALL_BINS[@]}"; do
# Wait if we hit max parallel jobs
while [[ $running_jobs -ge $MAX_PARALLEL ]]; do
wait -n 2>/dev/null || true
((running_jobs--))
done
# Start fuzzing in background
{
fuzz_binary "$bin" >> "$LOG_FILE" 2>&1
} &
((running_jobs++))
done
# Wait for all remaining jobs
wait
echo ""
echo "Fuzzing complete!"
# === STATISTICS & SUMMARY ===
echo "Generating summary..."
total_crashes=$(grep -c "REAL CRASH DETECTED" "$LOG_FILE" 2>/dev/null || echo 0)
segfaults=$(grep -c "SIGSEGV" "$LOG_FILE" 2>/dev/null || echo 0)
aborts=$(grep -c "SIGABRT" "$LOG_FILE" 2>/dev/null || echo 0)
sigfpe=$(grep -c "SIGFPE" "$LOG_FILE" 2>/dev/null || echo 0)
sigill=$(grep -c "SIGILL" "$LOG_FILE" 2>/dev/null || echo 0)
sigbus=$(grep -c "SIGBUS" "$LOG_FILE" 2>/dev/null || echo 0)
{
echo "SEGFAULT-FOCUSED FUZZ TEST SUMMARY - $(date)"
echo "============================================"
echo "Binaries tested: $TOTAL"
echo "Runs per binary: $RUNS_PER_BIN"
echo "Total test iterations: $((TOTAL * RUNS_PER_BIN))"
echo "Fuzz files used: $FUZZ_FILE_COUNT"
echo ""
echo "REAL CRASHES FOUND:"
echo " Total: $total_crashes"
echo " Segmentation faults: $segfaults"
echo " Aborts (SIGABRT): $aborts"
echo " FP exceptions: $sigfpe"
echo " Illegal instruction: $sigill"
echo " Bus errors: $sigbus"
echo ""
if [[ $total_crashes -gt 0 ]]; then
echo "AFFECTED PACKAGES:"
grep "PACKAGE:" "$LOG_FILE" | sed 's/.*PACKAGE: //' | sort | uniq -c | sort -rn
echo ""
echo "ALL CRASHES:"
grep "COMMAND:" "$LOG_FILE"
echo ""
fi
echo "Full log: $LOG_FILE"
} > "$SUMMARY_FILE"
# === COREDUMP COLLECTION ===
if [[ $total_crashes -gt 0 ]] && command -v coredumpctl &>/dev/null; then
echo "Collecting coredumps..."
COREDUMP_DIR="$WORKSPACE/coredumps_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$COREDUMP_DIR"
grep "COMMAND:" "$LOG_FILE" | sed 's/^.*COMMAND: //' | awk '{print $1}' | sort -u | while read -r bin; do
[[ -z "$bin" ]] && continue
name=$(basename "$bin")
out="$COREDUMP_DIR/coredump_${name}.dump"
if coredumpctl dump "$bin" -o "$out" 2>/dev/null; then
echo " Dumped: $name"
fi
done
echo "Coredumps saved to: $COREDUMP_DIR"
fi
# === FINAL OUTPUT ===
echo ""
echo "========================================"
cat "$SUMMARY_FILE"
echo "========================================"
echo ""
echo "Done! Check $SUMMARY_FILE for summary."