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