Refactor code structure for improved readability and maintainability; removed redundant code blocks and optimized function calls.
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled

This commit is contained in:
master
2025-11-20 07:50:52 +02:00
parent 616ec73133
commit 10212d67c0
473 changed files with 316758 additions and 388 deletions

View File

@@ -0,0 +1,83 @@
using System.Security.Cryptography;
using System.Text.Json;
using System.Text.RegularExpressions;
using FluentAssertions;
using Xunit;
namespace StellaOps.Reachability.FixtureTests;
public class CorpusFixtureTests
{
private static readonly string RepoRoot = ReachbenchFixtureTests.LocateRepoRoot();
private static readonly string CorpusRoot = Path.Combine(RepoRoot, "tests", "reachability", "corpus");
[Fact]
public void ManifestExistsAndIsDeterministic()
{
var manifestPath = Path.Combine(CorpusRoot, "manifest.json");
File.Exists(manifestPath).Should().BeTrue("corpus manifest should exist");
using var stream = File.OpenRead(manifestPath);
using var doc = JsonDocument.Parse(stream);
doc.RootElement.ValueKind.Should().Be(JsonValueKind.Array);
}
[Fact]
public void CorpusEntriesMatchManifestHashes()
{
var manifestPath = Path.Combine(CorpusRoot, "manifest.json");
var manifest = JsonDocument.Parse(File.ReadAllBytes(manifestPath)).RootElement.EnumerateArray().ToArray();
manifest.Should().NotBeEmpty("corpus manifest must have entries");
foreach (var entry in manifest)
{
var id = entry.GetProperty("id").GetString();
var language = entry.GetProperty("language").GetString();
var files = entry.GetProperty("files");
id.Should().NotBeNullOrEmpty();
language.Should().NotBeNullOrEmpty();
var caseDir = Path.Combine(CorpusRoot, language!, id!);
Directory.Exists(caseDir).Should().BeTrue($"case folder missing: {caseDir}");
foreach (var fileProp in files.EnumerateObject())
{
var filename = fileProp.Name;
var expectedHash = fileProp.Value.GetString();
File.Exists(Path.Combine(caseDir, filename)).Should().BeTrue($"{id} missing {filename}");
var actualHash = BitConverter.ToString(SHA256.HashData(File.ReadAllBytes(Path.Combine(caseDir, filename)))).Replace("-", "").ToLowerInvariant();
actualHash.Should().Be(expectedHash, $"{id} hash mismatch for {filename}");
}
}
}
[Fact]
public void ExpectFilesContainRequiredFields()
{
var manifestPath = Path.Combine(CorpusRoot, "manifest.json");
var manifest = JsonDocument.Parse(File.ReadAllBytes(manifestPath)).RootElement.EnumerateArray().ToArray();
var required = new[] { "id", "language", "state", "score" };
var idRegex = new Regex(@"^id:\s*(?<id>.+)$", RegexOptions.Multiline);
foreach (var entry in manifest)
{
var id = entry.GetProperty("id").GetString()!;
var language = entry.GetProperty("language").GetString()!;
var expectPath = Path.Combine(CorpusRoot, language, id, "expect.yaml");
File.Exists(expectPath).Should().BeTrue($"{id} missing expect.yaml");
var text = File.ReadAllText(expectPath);
foreach (var field in required)
{
text.Should().Contain($"{field}:", $"{id} expect.yaml missing '{field}:'");
}
var match = idRegex.Match(text);
match.Success.Should().BeTrue($"{id} expect.yaml should include matching id");
match.Groups["id"].Value.Trim().Should().Be(id, $"{id} expect.yaml id must match manifest id");
}
}
}

View File

@@ -0,0 +1,21 @@
# Reachability Corpus (QA-CORPUS-401-031)
Layout
- `manifest.json` — deterministic SHA-256 hashes for each case file.
- `<language>/<case>/expect.yaml` — state (`reachable|conditional|unreachable`), score, evidence refs.
- `<language>/<case>/callgraph.static.json` — static call graph sample (stub for MVP).
- `<language>/<case>/vex.openvex.json` — expected VEX slice for the case.
Determinism
- JSON files have sorted keys; hashes recorded in `manifest.json`.
- Scores rounded to 2dp; timestamps (if added later) must be UTC ISO-8601.
- No network access required to consume the corpus.
MVP cases (stubs, to be replaced with real artifacts)
- Go: `go-ssh-CVE-2020-9283-keyexchange`
- .NET: `dotnet-kestrel-CVE-2023-44487-http2-rapid-reset`
- Python: `python-django-CVE-2019-19844-sqli-like`
- Rust: `rust-axum-header-parsing-TBD`
CI intent
- `CorpusFixtureTests` validates presence and hashes from the manifest; hook this into CI once repo build stabilises.

View File

@@ -0,0 +1,5 @@
{
"schema_version": "reach-corpus.callgraph/v1",
"nodes": [],
"edges": []
}

View File

@@ -0,0 +1,11 @@
schema_version: reach-corpus.expect/v1
id: dotnet-kestrel-CVE-2023-44487-http2-rapid-reset
language: dotnet
state: reachable
score: 0.85
static_evidence:
callgraphs:
- callgraph.static.json
runtime_evidence: []
vex: vex.openvex.json
notes: "MVP fixture stub; replace with real callgraph and traces when available."

View File

@@ -0,0 +1,12 @@
{
"author": "StellaOps",
"role": "reachability-corpus",
"timestamp": "2025-11-18T00:00:00Z",
"statements": [
{
"vulnerability": "TBD",
"products": ["pkg:demo/demo"],
"status": "affected"
}
]
}

View File

@@ -0,0 +1,5 @@
{
"schema_version": "reach-corpus.callgraph/v1",
"nodes": [],
"edges": []
}

View File

@@ -0,0 +1,11 @@
schema_version: reach-corpus.expect/v1
id: go-ssh-CVE-2020-9283-keyexchange
language: go
state: reachable
score: 0.80
static_evidence:
callgraphs:
- callgraph.static.json
runtime_evidence: []
vex: vex.openvex.json
notes: "MVP fixture stub; replace with real callgraph and traces when available."

View File

@@ -0,0 +1,12 @@
{
"author": "StellaOps",
"role": "reachability-corpus",
"timestamp": "2025-11-18T00:00:00Z",
"statements": [
{
"vulnerability": "TBD",
"products": ["pkg:demo/demo"],
"status": "affected"
}
]
}

View File

@@ -0,0 +1,38 @@
[
{
"files": {
"callgraph.static.json": "7359d8c26f16151a4b05cf0e6675e5c66b5ffb6396b906e74c0d5bb2f290e972",
"expect.yaml": "08859e027299b83fbe0a2754797df09736c08c1dd050da830d4e55ed416e77d0",
"vex.openvex.json": "c3593790f769974b1b66aa5331f1d3ad4d699f77f198b2e77e78659ee79d3c15"
},
"id": "dotnet-kestrel-CVE-2023-44487-http2-rapid-reset",
"language": "dotnet"
},
{
"files": {
"callgraph.static.json": "7359d8c26f16151a4b05cf0e6675e5c66b5ffb6396b906e74c0d5bb2f290e972",
"expect.yaml": "ad5375a8f2ad10378a48ca031afe726ac8ce94e8faea8e7fba907ca571ab5811",
"vex.openvex.json": "c3593790f769974b1b66aa5331f1d3ad4d699f77f198b2e77e78659ee79d3c15"
},
"id": "go-ssh-CVE-2020-9283-keyexchange",
"language": "go"
},
{
"files": {
"callgraph.static.json": "7359d8c26f16151a4b05cf0e6675e5c66b5ffb6396b906e74c0d5bb2f290e972",
"expect.yaml": "c2516433b685aa955342a3a1a70485c3742eca654aa6245866084da6d7574815",
"vex.openvex.json": "c3593790f769974b1b66aa5331f1d3ad4d699f77f198b2e77e78659ee79d3c15"
},
"id": "python-django-CVE-2019-19844-sqli-like",
"language": "python"
},
{
"files": {
"callgraph.static.json": "7359d8c26f16151a4b05cf0e6675e5c66b5ffb6396b906e74c0d5bb2f290e972",
"expect.yaml": "01fd3ce042e65f4d17ca8a6144fefcbb32b945ae720d136d0d9207e17974ee0a",
"vex.openvex.json": "c3593790f769974b1b66aa5331f1d3ad4d699f77f198b2e77e78659ee79d3c15"
},
"id": "rust-axum-header-parsing-TBD",
"language": "rust"
}
]

View File

@@ -0,0 +1,5 @@
{
"schema_version": "reach-corpus.callgraph/v1",
"nodes": [],
"edges": []
}

View File

@@ -0,0 +1,11 @@
schema_version: reach-corpus.expect/v1
id: python-django-CVE-2019-19844-sqli-like
language: python
state: reachable
score: 0.80
static_evidence:
callgraphs:
- callgraph.static.json
runtime_evidence: []
vex: vex.openvex.json
notes: "MVP fixture stub; replace with real callgraph and traces when available."

View File

@@ -0,0 +1,12 @@
{
"author": "StellaOps",
"role": "reachability-corpus",
"timestamp": "2025-11-18T00:00:00Z",
"statements": [
{
"vulnerability": "TBD",
"products": ["pkg:demo/demo"],
"status": "affected"
}
]
}

View File

@@ -0,0 +1,5 @@
{
"schema_version": "reach-corpus.callgraph/v1",
"nodes": [],
"edges": []
}

View File

@@ -0,0 +1,11 @@
schema_version: reach-corpus.expect/v1
id: rust-axum-header-parsing-TBD
language: rust
state: conditional
score: 0.60
static_evidence:
callgraphs:
- callgraph.static.json
runtime_evidence: []
vex: vex.openvex.json
notes: "MVP fixture stub; replace with real callgraph and traces when available."

View File

@@ -0,0 +1,12 @@
{
"author": "StellaOps",
"role": "reachability-corpus",
"timestamp": "2025-11-18T00:00:00Z",
"statements": [
{
"vulnerability": "TBD",
"products": ["pkg:demo/demo"],
"status": "affected"
}
]
}

View File

@@ -0,0 +1,8 @@
# Reachability Scripts
- `update_corpus_manifest.py` — regenerate `tests/reachability/corpus/manifest.json` with SHA-256 hashes for all corpus files. Deterministic; no network access.
Usage:
```bash
python tests/reachability/scripts/update_corpus_manifest.py
```

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""
Regenerate reachability corpus manifest deterministically.
Usage: python tests/reachability/scripts/update_corpus_manifest.py
"""
from __future__ import annotations
import hashlib
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1] / "corpus"
FILE_LIST = ["expect.yaml", "callgraph.static.json", "vex.openvex.json"]
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def main() -> int:
entries = []
for lang_dir in sorted(p for p in ROOT.iterdir() if p.is_dir()):
for case_dir in sorted(p for p in lang_dir.iterdir() if p.is_dir()):
files = {}
for name in FILE_LIST:
path = case_dir / name
if not path.exists():
raise SystemExit(f"missing {path}")
files[name] = sha256(path)
entries.append({
"id": case_dir.name,
"language": lang_dir.name,
"files": files,
})
manifest_path = ROOT / "manifest.json"
manifest_path.write_text(json.dumps(entries, indent=2, sort_keys=True))
print(f"wrote {manifest_path} ({len(entries)} entries)")
return 0
if __name__ == "__main__":
raise SystemExit(main())