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