#!/bin/bash
# =============================================================================
# verify_fix.sh — verifies bundle/coding/proposed_fix.diff for CVE-2026-41042
# (Apache Gravitino unauthenticated H2 JDBC URL injection -> RCE via H2 INIT).
#
# It is idempotent and self-contained. It:
#   1. Locates the Gravitino v1.2.0 source checkout + the official 1.2.0 server
#      libs from the project cache.
#   2. Resets the checkout to a clean v1.2.0 tree and confirms the patch applies
#      cleanly (`git apply --check`), then applies it.
#   3. Compiles the REAL patched DataSourceUtils (+JdbcConfig) against the 1.2.0
#      server jars and runs H2BlockTest -> asserts the H2 guard blocks every H2
#      payload (CVE + lakehouse-paimon variant, URL-encoded, double-encoded,
#      case-insensitive, org.h2.* driver) and does NOT block legit mysql/pg/mariadb.
#   4. Compiles the REAL patched Paimon CatalogUtils against the paimon+hadoop+
#      gravitino jars and runs PaimonH2BlockTest (invokes checkPaimonConfig via
#      reflection) -> asserts the Paimon JDBC-metastore path is also protected.
# Exit 0 only if every step passes.
# =============================================================================
set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUNDLE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
PATCH="$SCRIPT_DIR/proposed_fix.diff"
H2TEST="$SCRIPT_DIR/H2BlockTest.java"
PAIMONTEST="$SCRIPT_DIR/PaimonH2BlockTest.java"

fail() { echo "VERIFY FAIL: $*" >&2; exit 1; }
ok()   { echo "VERIFY OK:   $*"; }

# --- locate repo + 1.2.0 server libs from the project cache context ------------
CTX="$BUNDLE_DIR/project_cache_context.json"
[ -f "$CTX" ] || fail "missing $CTX"
CACHE_DIR="$(python3 -c "import json;print(json.load(open('$CTX')).get('project_cache_dir',''))" 2>/dev/null || true)"
[ -n "$CACHE_DIR" ] || fail "project_cache_dir not found in $CTX"
REPO="$CACHE_DIR/repo"
VULN="$CACHE_DIR/vuln"
[ -d "$REPO/.git" ]        || fail "Gravitino source checkout not found at $REPO"
[ -d "$VULN/libs" ]        || fail "Gravitino 1.2.0 server libs not found at $VULN/libs"
[ -f "$PATCH" ]            || fail "missing patch $PATCH"
[ -f "$H2TEST" ]           || fail "missing $H2TEST"
[ -f "$PAIMONTEST" ]       || fail "missing $PAIMONTEST"
PAIMONLIBS="$VULN/catalogs/lakehouse-paimon/libs"
[ -d "$PAIMONLIBS" ]       || fail "paimon catalog libs not found at $PAIMONLIBS"

VLIBS="$VULN/libs"
DSU="$REPO/catalogs/catalog-jdbc-common/src/main/java/org/apache/gravitino/catalog/jdbc/utils/DataSourceUtils.java"
JCFG="$REPO/catalogs/catalog-jdbc-common/src/main/java/org/apache/gravitino/catalog/jdbc/config/JdbcConfig.java"
CAT="$REPO/catalogs/catalog-lakehouse-paimon/src/main/java/org/apache/gravitino/catalog/lakehouse/paimon/utils/CatalogUtils.java"

# --- 1. reset to clean v1.2.0 and verify clean apply ---------------------------
echo "::group::1) reset checkout & verify patch applies cleanly"
git -C "$REPO" checkout -- . >/dev/null 2>&1 || true
git -C "$REPO" clean -fdq >/dev/null 2>&1 || true
HEAD_TAG="$(git -C "$REPO" describe --tags 2>/dev/null || git -C "$REPO" rev-parse --short HEAD)"
ok "checkout at $HEAD_TAG, working tree clean"
git -C "$REPO" apply --check "$PATCH" || fail "patch does not apply cleanly to $REPO"
ok "git apply --check passed"
git -C "$REPO" apply "$PATCH" || fail "git apply failed"
ok "patch applied"
git -C "$REPO" diff --stat | sed 's/^/    /'
echo "::endgroup::"

# --- 2. DataSourceUtils guard (primary CVE fix) --------------------------------
echo "::group::2) compile & run DataSourceUtils H2 guard (H2BlockTest)"
OUT1="$(mktemp -d)"
javac -cp "$VLIBS/*" -d "$OUT1" "$DSU" "$JCFG" "$H2TEST" \
  || { echo "javac failed for DataSourceUtils path"; rm -rf "$OUT1"; fail "compile error"; }
ok "compiled patched DataSourceUtils + JdbcConfig + H2BlockTest"
java -cp "$OUT1:$VLIBS/*" H2BlockTest || { rm -rf "$OUT1"; fail "H2BlockTest assertions failed"; }
rm -rf "$OUT1"
echo "::endgroup::"

# --- 3. Paimon CatalogUtils guard (variant bypass fix) -------------------------
echo "::group::3) compile & run Paimon CatalogUtils H2 guard (PaimonH2BlockTest)"
# Extract the paimon gravitino jar but drop the OLD CatalogUtils.class so our
# patched source compiles cleanly against the real paimon/hadoop/gravitino deps.
TMP="$(mktemp -d)"
( cd "$TMP" && unzip -q "$PAIMONLIBS/gravitino-catalog-lakehouse-paimon-1.2.0.jar" \
    && rm -f org/apache/gravitino/catalog/lakehouse/paimon/utils/CatalogUtils.class ) \
  || { rm -rf "$TMP"; fail "could not prepare paimon gravitino classes"; }
CP3="$TMP:$PAIMONLIBS/*:$VLIBS/*"
OUT2="$(mktemp -d)"
javac -cp "$CP3" -d "$OUT2" "$CAT" "$PAIMONTEST" \
  || { echo "javac failed for Paimon CatalogUtils path"; rm -rf "$TMP" "$OUT2"; fail "compile error"; }
ok "compiled patched Paimon CatalogUtils + PaimonH2BlockTest"
java -cp "$OUT2:$CP3" PaimonH2BlockTest \
  || { rm -rf "$TMP" "$OUT2"; fail "PaimonH2BlockTest assertions failed"; }
rm -rf "$TMP" "$OUT2"
echo "::endgroup::"

# --- 4. reset checkout back to clean (idempotency) -----------------------------
git -C "$REPO" checkout -- . >/dev/null 2>&1 || true
git -C "$REPO" clean -fdq >/dev/null 2>&1 || true
ok "checkout reset to clean v1.2.0 (idempotent)"

echo
ok "ALL VERIFICATION STEPS PASSED"
echo "  - patch applies cleanly to Gravitino v1.2.0 source"
echo "  - DataSourceUtils.createDataSource blocks H2 URLs/drivers (CVE-2026-41042)"
echo "  - CatalogUtils.checkPaimonConfig blocks H2 on the lakehouse-paimon JDBC path"
echo "  - legitimate mysql/postgresql/mariadb/filesystem configs are not blocked"
exit 0
