///|
pub(all) struct NativeStubFallbackLockdownRule {
file : String
required_includes : Array[String]
required_tokens : Array[String]
forbidden_tokens : Array[String]
expected_ffi_export_count : Int
expected_set_error_call_count : Int
expected_helper_call_count : Int
} derive(Eq, Debug)
///|
pub(all) struct NativeStubFallbackLockdownFact {
file : String
includes : Array[String]
present_tokens : Array[String]
present_forbidden_tokens : Array[String]
ffi_export_count : Int
set_error_call_count : Int
helper_call_count : Int
} derive(Eq, Debug)
///|
pub(all) struct NativeStubFallbackLockdownPolicyReport {
rule_count : Int
actual_file_count : Int
missing_file_count : Int
extra_file_count : Int
required_include_count : Int
include_exact_set_mismatch_count : Int
required_token_count : Int
missing_required_token_count : Int
forbidden_token_count : Int
present_forbidden_token_count : Int
ffi_export_count_mismatch_count : Int
set_error_call_count_mismatch_count : Int
helper_call_count_mismatch_count : Int
duplicate_file_fact_count : Int
replaces_file_reading : Bool
replaces_token_extraction : Bool
live_io_evidence : Bool
} derive(Eq, Debug)
///|
pub fn NativeStubFallbackLockdownPolicyReport::passes(
self : NativeStubFallbackLockdownPolicyReport,
) -> Bool {
self.rule_count > 0 &&
self.actual_file_count == self.rule_count &&
self.missing_file_count == 0 &&
self.extra_file_count == 0 &&
self.required_include_count > 0 &&
self.include_exact_set_mismatch_count == 0 &&
self.required_token_count > 0 &&
self.missing_required_token_count == 0 &&
self.forbidden_token_count > 0 &&
self.present_forbidden_token_count == 0 &&
self.ffi_export_count_mismatch_count == 0 &&
self.set_error_call_count_mismatch_count == 0 &&
self.helper_call_count_mismatch_count == 0 &&
self.duplicate_file_fact_count == 0 &&
!self.replaces_file_reading &&
!self.replaces_token_extraction &&
!self.live_io_evidence
}
///|
pub fn native_stub_fallback_lockdown_rules() -> Array[
NativeStubFallbackLockdownRule,
] {
[
fallback_lockdown_rule(
"stub_npcap_unsupported.c",
["stub_common.h"],
["#if !defined(_WIN32)", "MOONBIT_FFI_EXPORT"],
[
"stub_npcap_windows.h", "stub_npcap_windows_[A-Za-z0-9_]+.c", "#include ",
"PCAP_OPENFLAG_PROMISCUOUS", "lockwire_native_npcap_ensure", "lockwire_native_npcap_findalldevs",
"lockwire_native_npcap_freealldevs", "lockwire_native_npcap_live_ensure",
"lockwire_native_npcap_open_live_handle", "lockwire_native_npcap_close_handle",
"lockwire_native_npcap_sendpacket_handle", "lockwire_native_npcap_next_ex_handle",
"lockwire_native_npcap_geterr_handle", "lockwire_native_npcap_compile_filter_handle",
"lockwire_native_npcap_setfilter_handle", "lockwire_native_npcap_freecode_handle",
"lockwire_native_npcap_live_handle_get", "lockwire_native_npcap_live_handle_alloc",
"lockwire_native_npcap_live_handle_release", "lockwire_native_npcap_copy_moonbit_bytes_to_c_string",
],
9,
9,
0,
),
fallback_lockdown_rule(
"stub_raw_socket_unsupported.c",
["stub_common.h"],
[
"#define LOCKWIRE_RAW_SOCKET_UNSUPPORTED_ERROR (-90)", "static void raw_socket_unsupported_error(void)",
],
[
"stub_raw_socket_linux.h", "stub_raw_socket_linux_[A-Za-z0-9_]+.c", "#include ", "#include ", "#include ",
"#include ", "#include ", "AF_PACKET", "SOCK_RAW", "ETH_P_",
"sockaddr_ll", "if_nametoindex(", "socket(", "bind(", "setsockopt(", "send(",
"recv(", "poll(", "close(",
],
6,
1,
6,
),
fallback_lockdown_rule(
"stub_udp_unsupported.c",
["stub_common.h"],
[
"#define LOCKWIRE_UDP_UNSUPPORTED_ERROR (-20)", "static void udp_unsupported_error(void)",
"#if !defined(_WIN32)", "!defined(__linux__)", "!defined(__APPLE__)", "!defined(__FreeBSD__)",
],
[
"stub_udp_windows.h", "stub_udp_posix.h", "stub_udp_[A-Za-z0-9_]+.c", "#include ",
"#include ", "#include ", "#include ",
"AF_INET", "SOCK_DGRAM", "sockaddr_in", "WSAStartup", "LoadLibraryA(", "GetProcAddress(",
"socket(", "bind(", "setsockopt(", "sendto(", "recvfrom(", "getsockname(",
"close(", "closesocket(",
],
5,
1,
5,
),
]
}
///|
pub fn native_stub_expected_fallback_lockdown_facts() -> Array[
NativeStubFallbackLockdownFact,
] {
let facts : Array[NativeStubFallbackLockdownFact] = []
for rule in native_stub_fallback_lockdown_rules() {
facts.push({
file: rule.file,
includes: rule.required_includes,
present_tokens: rule.required_tokens,
present_forbidden_tokens: [],
ffi_export_count: rule.expected_ffi_export_count,
set_error_call_count: rule.expected_set_error_call_count,
helper_call_count: rule.expected_helper_call_count,
})
}
facts
}
///|
pub fn native_stub_fallback_lockdown_policy_report(
actual : Array[NativeStubFallbackLockdownFact],
) -> NativeStubFallbackLockdownPolicyReport {
native_stub_fallback_lockdown_policy_report_from_rules(
native_stub_fallback_lockdown_rules(),
actual,
)
}
///|
pub fn native_stub_fallback_lockdown_policy_report_from_rules(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> NativeStubFallbackLockdownPolicyReport {
{
rule_count: rules.length(),
actual_file_count: count_actual_fallback_lockdown_files(actual),
missing_file_count: count_missing_fallback_lockdown_files(rules, actual),
extra_file_count: count_extra_fallback_lockdown_files(rules, actual),
required_include_count: count_required_fallback_lockdown_includes(rules),
include_exact_set_mismatch_count: count_fallback_lockdown_include_mismatches(
rules, actual,
),
required_token_count: count_required_fallback_lockdown_tokens(rules),
missing_required_token_count: count_missing_fallback_lockdown_tokens(
rules, actual,
),
forbidden_token_count: count_forbidden_fallback_lockdown_tokens(rules),
present_forbidden_token_count: count_present_forbidden_fallback_lockdown_tokens(
rules, actual,
),
ffi_export_count_mismatch_count: count_fallback_lockdown_export_mismatches(
rules, actual,
),
set_error_call_count_mismatch_count: count_fallback_lockdown_set_error_mismatches(
rules, actual,
),
helper_call_count_mismatch_count: count_fallback_lockdown_helper_mismatches(
rules, actual,
),
duplicate_file_fact_count: count_duplicate_fallback_lockdown_file_facts(
actual,
),
replaces_file_reading: false,
replaces_token_extraction: false,
live_io_evidence: false,
}
}
///|
fn fallback_lockdown_rule(
file : String,
required_includes : Array[String],
required_tokens : Array[String],
forbidden_tokens : Array[String],
expected_ffi_export_count : Int,
expected_set_error_call_count : Int,
expected_helper_call_count : Int,
) -> NativeStubFallbackLockdownRule {
{
file,
required_includes,
required_tokens,
forbidden_tokens,
expected_ffi_export_count,
expected_set_error_call_count,
expected_helper_call_count,
}
}
///|
fn count_actual_fallback_lockdown_files(
facts : Array[NativeStubFallbackLockdownFact],
) -> Int {
let files : Array[String] = []
for fact in facts {
if !fallback_lockdown_contains_string(files, fact.file) {
files.push(fact.file)
}
}
files.length()
}
///|
fn count_missing_fallback_lockdown_files(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
if !fallback_lockdown_contains_file(actual, rule.file) {
count += 1
}
}
count
}
///|
fn count_extra_fallback_lockdown_files(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let seen : Array[String] = []
let mut count = 0
for fact in actual {
if !fallback_lockdown_contains_string(seen, fact.file) {
seen.push(fact.file)
if !fallback_lockdown_contains_rule_file(rules, fact.file) {
count += 1
}
}
}
count
}
///|
fn count_required_fallback_lockdown_includes(
rules : Array[NativeStubFallbackLockdownRule],
) -> Int {
let mut count = 0
for rule in rules {
count += rule.required_includes.length()
}
count
}
///|
fn count_fallback_lockdown_include_mismatches(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
for fact in actual {
if fact.file == rule.file &&
!fallback_lockdown_same_set(rule.required_includes, fact.includes) {
count += 1
}
}
}
count
}
///|
fn count_required_fallback_lockdown_tokens(
rules : Array[NativeStubFallbackLockdownRule],
) -> Int {
let mut count = 0
for rule in rules {
count += rule.required_tokens.length()
}
count
}
///|
fn count_missing_fallback_lockdown_tokens(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
for token in rule.required_tokens {
if !fallback_lockdown_contains_present_token(actual, rule.file, token) {
count += 1
}
}
}
count
}
///|
fn count_forbidden_fallback_lockdown_tokens(
rules : Array[NativeStubFallbackLockdownRule],
) -> Int {
let mut count = 0
for rule in rules {
count += rule.forbidden_tokens.length()
}
count
}
///|
fn count_present_forbidden_fallback_lockdown_tokens(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
for fact in actual {
if fact.file == rule.file {
for token in fact.present_forbidden_tokens {
if fallback_lockdown_contains_string(rule.forbidden_tokens, token) {
count += 1
}
}
}
}
}
count
}
///|
fn count_fallback_lockdown_export_mismatches(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
for fact in actual {
if fact.file == rule.file &&
fact.ffi_export_count != rule.expected_ffi_export_count {
count += 1
}
}
}
count
}
///|
fn count_fallback_lockdown_set_error_mismatches(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
for fact in actual {
if fact.file == rule.file &&
fact.set_error_call_count != rule.expected_set_error_call_count {
count += 1
}
}
}
count
}
///|
fn count_fallback_lockdown_helper_mismatches(
rules : Array[NativeStubFallbackLockdownRule],
actual : Array[NativeStubFallbackLockdownFact],
) -> Int {
let mut count = 0
for rule in rules {
for fact in actual {
if fact.file == rule.file &&
fact.helper_call_count != rule.expected_helper_call_count {
count += 1
}
}
}
count
}
///|
fn count_duplicate_fallback_lockdown_file_facts(
facts : Array[NativeStubFallbackLockdownFact],
) -> Int {
let seen : Array[String] = []
let mut count = 0
for fact in facts {
if fallback_lockdown_contains_string(seen, fact.file) {
count += 1
} else {
seen.push(fact.file)
}
}
count
}
///|
fn fallback_lockdown_contains_rule_file(
rules : Array[NativeStubFallbackLockdownRule],
file : String,
) -> Bool {
for rule in rules {
if rule.file == file {
return true
}
}
false
}
///|
fn fallback_lockdown_contains_file(
facts : Array[NativeStubFallbackLockdownFact],
file : String,
) -> Bool {
for fact in facts {
if fact.file == file {
return true
}
}
false
}
///|
fn fallback_lockdown_contains_present_token(
facts : Array[NativeStubFallbackLockdownFact],
file : String,
token : String,
) -> Bool {
for fact in facts {
if fact.file == file &&
fallback_lockdown_contains_string(fact.present_tokens, token) {
return true
}
}
false
}
///|
fn fallback_lockdown_same_set(
expected : Array[String],
actual : Array[String],
) -> Bool {
if expected.length() != actual.length() {
return false
}
for item in expected {
if !fallback_lockdown_contains_string(actual, item) {
return false
}
}
true
}
///|
fn fallback_lockdown_contains_string(
items : Array[String],
item : String,
) -> Bool {
for got in items {
if got == item {
return true
}
}
false
}