108 lines
3.8 KiB
Bash
Executable File
108 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# Smoke test: large file read through FUSE mount (pcl-26j)
|
|
#
|
|
# Regression test for bad-free heap corruption in psync_pagecache_free_request.
|
|
# A large read forces multiple psync_request_range_t allocations — one per
|
|
# non-contiguous page range — which are then freed via free_request_range().
|
|
# The old code called bare free() on pmem_malloc-allocated nodes; this build
|
|
# uses AddressSanitizer to catch any such mismatched free.
|
|
#
|
|
# Usage:
|
|
# PCLOUD_USER=you@example.com bash tests/smoke-tests/smoke-test-large-read.sh
|
|
#
|
|
# Requirements:
|
|
# - PCLOUD_USER env var set (credentials prompted at daemon start)
|
|
# - A file >= 50 MB present in the pCloud root (REMOTE_FILE below)
|
|
# - FUSE available on the host
|
|
|
|
set -euo pipefail
|
|
|
|
MOUNT="${HOME}/pCloudDrive"
|
|
ASAN_LOG="/tmp/pcloudcc_asan_large_read_$$.log"
|
|
REMOTE_FILE="${SMOKE_REMOTE_FILE:-}" # override via env if needed
|
|
MIN_SIZE_MB=50
|
|
|
|
# ---- helpers ---------------------------------------------------------------
|
|
|
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
|
|
|
cleanup() {
|
|
echo "--- stopping daemon ---"
|
|
echo "finalize" | ./pcloudcc -k 2>/dev/null || true
|
|
sleep 1
|
|
# Kill any stray daemon
|
|
pkill -f "pcloudcc -d" 2>/dev/null || true
|
|
echo "--- ASAN log ($ASAN_LOG) ---"
|
|
cat "$ASAN_LOG" 2>/dev/null || echo "(empty)"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# ---- sanity checks ---------------------------------------------------------
|
|
|
|
[[ -n "${PCLOUD_USER:-}" ]] || die "PCLOUD_USER not set"
|
|
[[ -x ./pcloudcc ]] || die "pcloudcc binary not found — run make first"
|
|
|
|
# Verify the binary was built with ASAN
|
|
if ! readelf -d ./pcloudcc 2>/dev/null | grep -q "libasan\|asan"; then
|
|
echo "WARNING: pcloudcc does not appear to be an ASAN build."
|
|
echo " For a meaningful test, rebuild with:"
|
|
echo " make clean && CFLAGS='-fsanitize=address -g -O1' \\"
|
|
echo " CXXFLAGS='-fsanitize=address -g -O1' \\"
|
|
echo " LDFLAGS='-fsanitize=address' make -j\$(nproc)"
|
|
echo " Continuing anyway — crash-level corruption may still surface."
|
|
fi
|
|
|
|
# ---- build env -------------------------------------------------------------
|
|
|
|
export ASAN_OPTIONS="log_path=${ASAN_LOG}:abort_on_error=0:detect_leaks=0"
|
|
|
|
# ---- start daemon ----------------------------------------------------------
|
|
|
|
echo "--- starting pcloudcc daemon ---"
|
|
./pcloudcc -u "$PCLOUD_USER" -d
|
|
sleep 3 # wait for mount and initial sync
|
|
|
|
[[ -d "$MOUNT" ]] || die "mount point $MOUNT does not exist after daemon start"
|
|
|
|
# ---- find a large remote file ----------------------------------------------
|
|
|
|
if [[ -z "$REMOTE_FILE" ]]; then
|
|
echo "--- searching for a file >= ${MIN_SIZE_MB} MB in ${MOUNT} ---"
|
|
REMOTE_FILE=$(find "$MOUNT" -maxdepth 3 -type f \
|
|
-size "+${MIN_SIZE_MB}M" -print -quit 2>/dev/null || true)
|
|
fi
|
|
|
|
if [[ -z "$REMOTE_FILE" ]]; then
|
|
echo "SKIP: no file >= ${MIN_SIZE_MB} MB found in ${MOUNT}."
|
|
echo " Upload a large file first, or set SMOKE_REMOTE_FILE=/path/to/file."
|
|
exit 0
|
|
fi
|
|
|
|
echo "--- reading: $REMOTE_FILE ---"
|
|
SIZE=$(stat -c%s "$REMOTE_FILE" 2>/dev/null || echo 0)
|
|
echo " size: $((SIZE / 1024 / 1024)) MB"
|
|
|
|
# ---- read the file, exercising the page-cache request path -----------------
|
|
|
|
echo "--- streaming file to /dev/null ---"
|
|
dd if="$REMOTE_FILE" of=/dev/null bs=1M 2>&1 | tail -1
|
|
echo "--- read complete ---"
|
|
|
|
# Give ASAN a moment to flush any deferred reports
|
|
sleep 1
|
|
|
|
# ---- evaluate ASAN output --------------------------------------------------
|
|
|
|
ASAN_ERRORS=$(grep -c "ERROR: AddressSanitizer" "$ASAN_LOG" 2>/dev/null || true)
|
|
BAD_FREE_ERRORS=$(grep -c "attempting free on address" "$ASAN_LOG" 2>/dev/null || true)
|
|
|
|
echo ""
|
|
if [[ "$ASAN_ERRORS" -eq 0 ]]; then
|
|
echo "PASS: no AddressSanitizer errors detected during large file read"
|
|
exit 0
|
|
else
|
|
echo "FAIL: $ASAN_ERRORS ASAN error(s) detected ($BAD_FREE_ERRORS bad-free)"
|
|
echo " See $ASAN_LOG for details"
|
|
exit 1
|
|
fi
|