| 1 | set -e |
| 2 | export CYCLOPS_HOME=/opt/cyclops-v2 |
| 3 | PY=/opt/cyclops-venv/bin/python |
| 4 | W=/opt/cyclops-v2/oracle/work |
| 5 | mkdir -p "$W" && cd "$W" |
| 6 | |
| 7 | echo "=== [1/5] seed knowledge graph ===" |
| 8 | $PY /opt/cyclops-v2/orchestrator/seed_graph.py |
| 9 | |
| 10 | echo "=== [2/5] fetch real target (cJSON, pinned old tag) ===" |
| 11 | if [ ! -d cJSON ]; then |
| 12 | git clone --quiet https://github.com/DaveGamble/cJSON.git |
| 13 | fi |
| 14 | cd cJSON |
| 15 | git checkout -q v1.7.10 2>/dev/null || git checkout -q v1.7.12 2>/dev/null || true |
| 16 | COMMIT=$(git rev-parse --short HEAD) |
| 17 | echo "cJSON @ $COMMIT" |
| 18 | cd "$W" |
| 19 | |
| 20 | echo "=== [3/5] BRAIN: joern dataflow on real source ===" |
| 21 | $PY /opt/cyclops-v2/brain/brain.py \ |
| 22 | "github.com/DaveGamble/cJSON" "memory-unsafe-parsers" \ |
| 23 | "$W/cJSON" "c" "$COMMIT" || true |
| 24 | |
| 25 | echo "=== [4/5] write a libFuzzer harness for cJSON_Parse ===" |
| 26 | cat > /opt/cyclops-v2/oracle/harnesses/cjson_harness.c <<'EOF' |
| 27 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
| 28 | char *buf = (char *)malloc(size + 1); |
| 29 | if (!buf) return 0; |
| 30 | memcpy(buf, data, size); |
| 31 | buf[size] = '\0'; |
| 32 | cJSON *j = cJSON_Parse(buf); |
| 33 | if (j) { |
| 34 | char *p = cJSON_Print(j); |
| 35 | if (p) free(p); |
| 36 | cJSON_Delete(j); |
| 37 | } |
| 38 | free(buf); |
| 39 | return 0; |
| 40 | } |
| 41 | EOF |
| 42 | |
| 43 | echo "=== [5/5] ORACLE: compile+fuzz+ASan+triage+gate ===" |
| 44 | $PY - <<'PYEOF' |
| 45 | import sys, os |
| 46 | sys.path.insert(0, "/opt/cyclops-v2/memory") |
| 47 | sys.path.insert(0, "/opt/cyclops-v2/oracle") |
| 48 | from memory import Memory |
| 49 | from oracle import prove_memory_corruption |
| 50 | |
| 51 | m = Memory() |
| 52 | W = "/opt/cyclops-v2/oracle/work" |
| 53 | import subprocess |
| 54 | commit = subprocess.run(["git","-C",f"{W}/cJSON","rev-parse","--short","HEAD"], |
| 55 | capture_output=True, text=True).stdout.strip() |
| 56 | import hashlib |
| 57 | tid = hashlib.sha1(f"github.com/DaveGamble/cJSON|{commit}".encode()).hexdigest()[:16] |
| 58 | |
| 59 | res = m._exec("""MATCH (t:Target {id:$t})-[:HAS_HYPOTHESIS]->(h:Hypothesis) |
| 60 | WHERE h.sink_class='memory-corruption' RETURN h.id LIMIT 1""", {"t": tid}) |
| 61 | if res.has_next(): |
| 62 | hid = res.get_next()[0] |
| 63 | print("using brain-found hypothesis", hid) |
| 64 | else: |
| 65 | hid = m.add_hypothesis(tid, "memory-corruption", "cJSON.c", 0, |
| 66 | "cJSON_Parse(input)", "internal buffer ops", "oracle-harness") |
| 67 | print("created hypothesis", hid) |
| 68 | |
| 69 | r = prove_memory_corruption( |
| 70 | target_id=tid, hypothesis_id=hid, |
| 71 | impact_family="RCE via Memory Corruption", |
| 72 | harness_c="/opt/cyclops-v2/oracle/harnesses/cjson_harness.c", |
| 73 | target_srcs=[f"{W}/cJSON/cJSON.c"], |
| 74 | extra_flags=[f"-I{W}/cJSON"], |
| 75 | seconds=int(os.environ.get("FUZZ_SECONDS","150")), |
| 76 | repo="cJSON") |
| 77 | print("ORACLE RESULT:", r) |
| 78 | print("GRAPH:", m.stats()) |
| 79 | PYEOF |
| 80 | echo "=== E2E COMPLETE ===" |