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