blob: bf16b2f2b9116922306451ebb74fd14d6b7d8cd4 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
#!/bin/bash
# Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).
# SPDX-License-Identifier: GPL-2.0
#
# Exercises the bounds checking and minimum-size validation added
# by the perf-data-validation hardening series.
err=0
cleanup() {
[ -n "${perfdata}" ] && rm -f "${perfdata}" "${perfdata}.old"
rm -f "${truncated}" "${stderrfile}"
trap - EXIT TERM INT
}
trap 'cleanup; exit 1' TERM INT
trap cleanup EXIT
perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2
truncated=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2
stderrfile=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2
# Record a simple workload
if ! perf record -o "${perfdata}" -- perf test -w noploop 2>/dev/null; then
echo "Skip: perf record failed"
cleanup
exit 2
fi
file_size=$(wc -c < "${perfdata}")
if [ "${file_size}" -lt 512 ]; then
echo "Skip: perf.data too small (${file_size} bytes)"
cleanup
exit 2
fi
# Test truncation at various offsets that exercise different
# parsing stages:
# 8 — file header magic only, no attrs or data
# 64 — partial file header (attr section incomplete)
# 256 — into the first events (partial event headers)
# 75% — mid-stream truncation (partial event data)
for cut_at in 8 64 256 $((file_size * 3 / 4)); do
if [ "${cut_at}" -ge "${file_size}" ]; then
continue
fi
dd if="${perfdata}" of="${truncated}" bs="${cut_at}" count=1 2>/dev/null
# perf report should exit with an error, not crash.
# Capture stderr to detect sanitizer violations.
perf report -i "${truncated}" --stdio > /dev/null 2> "${stderrfile}"
exit_code=$?
# A truncated file should never parse successfully
if [ ${exit_code} -eq 0 ]; then
echo "FAIL: perf report exited 0 (success) on ${cut_at}-byte truncated file — expected an error"
err=1
continue
fi
# Detect sanitizer violations — ASAN/MSAN/TSAN/UBSAN exit
# with code 1 by default, which would otherwise look like a
# clean error exit. Check stderr for their markers.
if grep -qE "^(==[0-9]+==ERROR:|SUMMARY: [A-Za-z]*Sanitizer)" "${stderrfile}" 2>/dev/null; then
sanitizer=$(grep -oE "(Address|Memory|Thread|UndefinedBehavior)Sanitizer" "${stderrfile}" | head -1)
echo "FAIL: perf report triggered ${sanitizer:-sanitizer} on ${cut_at}-byte truncated file"
err=1
continue
fi
# Detect crash signals portably — signal numbers differ
# across architectures (e.g. SIGBUS is 7 on x86/ARM but
# 10 on MIPS/SPARC). Use kill -l to map the number to a
# name on the running system.
if [ ${exit_code} -gt 128 ] && [ ${exit_code} -lt 200 ]; then
sig_name=$(kill -l $((exit_code - 128)) 2>/dev/null)
case ${sig_name} in
KILL|ILL|ABRT|BUS|FPE|SEGV|TRAP|SYS)
echo "FAIL: perf report crashed (SIG${sig_name}) on ${cut_at}-byte truncated file"
err=1
;;
esac
fi
done
cleanup
exit ${err}
|