86 lines · 2.8 KB · Shell
RawDownload
#!/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 INTtrap cleanup EXIT perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2truncated=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2stderrfile=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 # Record a simple workloadif ! perf record -o "${perfdata}" -- perf test -w noploop 2>/dev/null; then	echo "Skip: perf record failed"	cleanup	exit 2fi file_size=$(wc -c < "${perfdata}")if [ "${file_size}" -lt 512 ]; then	echo "Skip: perf.data too small (${file_size} bytes)"	cleanup	exit 2fi # 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	fidone cleanupexit ${err}