Fix TGK mem multi-encoding handling

This commit is contained in:
Carl Niklas Rydberg 2025-12-21 19:46:56 +01:00
parent 05baf8e847
commit d7b456654b
3 changed files with 141 additions and 28 deletions

View file

@ -153,7 +153,7 @@ amduat_add_lib(tgk_store_mem SRCS ${AMDUAT_TGK_STORE_MEM_SRCS})
amduat_link(tgk_store_mem amduat_tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
amduat_add_lib(tgk_store_fs SRCS ${AMDUAT_TGK_STORE_FS_SRCS})
amduat_link(tgk_store_fs amduat_tgk amduat_asl_store_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
amduat_link(tgk_store_fs amduat_tgk_store_mem amduat_tgk amduat_asl_store_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
add_executable(amduat_asl_cli src/tools/amduat_asl_cli.c)
target_include_directories(amduat_asl_cli
@ -256,6 +256,9 @@ target_include_directories(amduat_test_tgk_store_fs
PRIVATE ${AMDUAT_INTERNAL_DIR}
PRIVATE ${AMDUAT_INCLUDE_DIR}
)
target_compile_definitions(amduat_test_tgk_store_fs
PRIVATE _POSIX_C_SOURCE=200809L
)
target_link_libraries(amduat_test_tgk_store_fs
PRIVATE amduat_tgk_store_fs
)

View file

@ -53,20 +53,26 @@ static bool amduat_tgk_store_mem_edge_type_supported(
return false;
}
static bool amduat_tgk_store_mem_encoding_supported(
const amduat_tgk_store_mem_t *mem,
static bool amduat_tgk_store_mem_encoding_impl_supported(
amduat_asl_encoding_profile_id_t profile_id) {
size_t i;
if (mem == NULL) {
return false;
}
for (i = 0; i < mem->config.tgk_profiles.encodings_len; ++i) {
if (mem->config.tgk_profiles.encodings[i] == profile_id) {
switch (profile_id) {
case TGK1_EDGE_ENC_V1:
return true;
}
default:
return false;
}
}
static bool amduat_tgk_store_mem_decode_profile(
amduat_asl_encoding_profile_id_t profile_id,
amduat_octets_t bytes,
amduat_tgk_edge_body_t *out_body) {
switch (profile_id) {
case TGK1_EDGE_ENC_V1:
return amduat_enc_tgk1_edge_decode_v1(bytes, out_body);
default:
return false;
}
return false;
}
static bool amduat_tgk_store_mem_type_filter_match(
@ -272,6 +278,11 @@ static amduat_tgk_graph_error_t amduat_tgk_store_mem_decode_edge(
const amduat_tgk_store_mem_t *mem,
const amduat_tgk_store_mem_artifact_t *entry,
amduat_tgk_edge_body_t *out_body) {
size_t i;
bool saw_supported = false;
bool have_body = false;
amduat_tgk_edge_body_t resolved;
if (out_body != NULL) {
memset(out_body, 0, sizeof(*out_body));
}
@ -283,24 +294,61 @@ static amduat_tgk_graph_error_t amduat_tgk_store_mem_decode_edge(
mem, entry->artifact.type_tag.tag_id)) {
return GS_ERR_NOT_EDGE;
}
if (!amduat_tgk_store_mem_encoding_supported(mem, TGK1_EDGE_ENC_V1)) {
return GS_ERR_UNSUPPORTED;
}
if (entry->artifact.bytes.len != 0 &&
entry->artifact.bytes.data == NULL) {
return GS_ERR_INTEGRITY;
}
if (!amduat_enc_tgk1_edge_decode_v1(entry->artifact.bytes, out_body)) {
return GS_ERR_INTEGRITY;
}
if (!amduat_tgk_edge_body_has_endpoints(out_body)) {
amduat_tgk_edge_body_free(out_body);
return GS_ERR_INTEGRITY;
}
if (!amduat_tgk_store_mem_edge_type_supported(mem, out_body->type)) {
amduat_tgk_edge_body_free(out_body);
return GS_ERR_NOT_EDGE;
}
if (mem->config.tgk_profiles.encodings_len != 0 &&
mem->config.tgk_profiles.encodings == NULL) {
return GS_ERR_UNSUPPORTED;
}
memset(&resolved, 0, sizeof(resolved));
for (i = 0; i < mem->config.tgk_profiles.encodings_len; ++i) {
amduat_asl_encoding_profile_id_t profile_id =
mem->config.tgk_profiles.encodings[i];
amduat_tgk_edge_body_t candidate;
if (!amduat_tgk_store_mem_encoding_impl_supported(profile_id)) {
continue;
}
saw_supported = true;
if (!amduat_tgk_store_mem_decode_profile(profile_id,
entry->artifact.bytes,
&candidate)) {
continue;
}
if (!amduat_tgk_edge_body_has_endpoints(&candidate)) {
amduat_tgk_edge_body_free(&candidate);
if (have_body) {
amduat_tgk_edge_body_free(&resolved);
}
return GS_ERR_INTEGRITY;
}
if (!amduat_tgk_store_mem_edge_type_supported(mem, candidate.type)) {
amduat_tgk_edge_body_free(&candidate);
continue;
}
if (!have_body) {
resolved = candidate;
have_body = true;
continue;
}
if (!amduat_tgk_edge_body_eq(&resolved, &candidate)) {
amduat_tgk_edge_body_free(&candidate);
amduat_tgk_edge_body_free(&resolved);
return GS_ERR_INTEGRITY;
}
amduat_tgk_edge_body_free(&candidate);
}
if (!saw_supported) {
return GS_ERR_UNSUPPORTED;
}
if (!have_body) {
return GS_ERR_NOT_EDGE;
}
*out_body = resolved;
return 0;
}
@ -609,6 +657,17 @@ bool amduat_tgk_store_mem_init(amduat_tgk_store_mem_t *mem,
mem->edges = NULL;
mem->edges_len = 0;
if (config.tgk_profiles.encodings_len != 0 &&
config.tgk_profiles.encodings == NULL) {
return false;
}
for (i = 0; i < config.tgk_profiles.encodings_len; ++i) {
if (!amduat_tgk_store_mem_encoding_impl_supported(
config.tgk_profiles.encodings[i])) {
return false;
}
}
if (artifacts_len == 0) {
return true;
}

View file

@ -14,13 +14,14 @@ static const uint8_t k_non_edge_bytes[] = {0xde, 0xad, 0xbe, 0xef};
typedef struct {
amduat_tgk_store_t store;
amduat_tgk_store_mem_t mem;
amduat_tgk_store_mem_artifact_t artifacts[5];
amduat_tgk_store_mem_artifact_t artifacts[6];
amduat_octets_t edge_bytes[4];
amduat_reference_t ref_edge1;
amduat_reference_t ref_edge2;
amduat_reference_t ref_edge3;
amduat_reference_t ref_edge_bad;
amduat_reference_t ref_non_edge;
amduat_reference_t ref_invalid_tagged;
amduat_reference_t ref_missing;
amduat_reference_t node_a;
amduat_reference_t node_b;
@ -34,6 +35,7 @@ typedef struct {
uint8_t digest_edge3[32];
uint8_t digest_edge_bad[32];
uint8_t digest_non_edge[32];
uint8_t digest_invalid_tagged[32];
uint8_t digest_missing[32];
uint8_t digest_node_a[32];
uint8_t digest_node_b[32];
@ -59,6 +61,15 @@ static amduat_reference_t make_ref(uint8_t value, uint8_t *storage) {
amduat_octets(storage, 32));
}
static void free_ref(amduat_reference_t *ref) {
if (ref == NULL) {
return;
}
free((void *)ref->digest.data);
ref->digest.data = NULL;
ref->digest.len = 0;
}
static void free_edge_bytes(test_env_t *env) {
size_t i;
@ -107,6 +118,7 @@ static bool init_env(test_env_t *env) {
env->ref_edge3 = make_ref(0x30, env->digest_edge3);
env->ref_edge_bad = make_ref(0x40, env->digest_edge_bad);
env->ref_non_edge = make_ref(0x50, env->digest_non_edge);
env->ref_invalid_tagged = make_ref(0x55, env->digest_invalid_tagged);
env->ref_missing = make_ref(0x60, env->digest_missing);
env->node_a = make_ref(0xa1, env->digest_node_a);
@ -185,8 +197,13 @@ static bool init_env(test_env_t *env) {
env->artifacts[4].ref = env->ref_non_edge;
env->artifacts[4].artifact =
amduat_artifact(amduat_octets(k_non_edge_bytes, sizeof(k_non_edge_bytes)));
env->artifacts[5].ref = env->ref_invalid_tagged;
env->artifacts[5].artifact =
amduat_artifact_with_type(amduat_octets(k_non_edge_bytes,
sizeof(k_non_edge_bytes)),
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1));
if (!amduat_tgk_store_mem_init(&env->mem, env->config, env->artifacts, 5)) {
if (!amduat_tgk_store_mem_init(&env->mem, env->config, env->artifacts, 6)) {
free_edge_bytes(env);
return false;
}
@ -239,6 +256,19 @@ static int test_resolve_edge_not_edge(const test_env_t *env) {
return 0;
}
static int test_resolve_edge_invalid_bytes(const test_env_t *env) {
amduat_tgk_edge_body_t body;
amduat_tgk_graph_error_t err;
err = amduat_tgk_store_resolve_edge((amduat_tgk_store_t *)&env->store,
env->ref_invalid_tagged, &body);
if (err != GS_ERR_NOT_EDGE) {
fprintf(stderr, "resolve_edge invalid bytes mismatch: %d\n", err);
return 1;
}
return 0;
}
static int test_resolve_edge_missing(const test_env_t *env) {
amduat_tgk_edge_body_t body;
amduat_tgk_graph_error_t err;
@ -274,6 +304,25 @@ static bool make_ref_for_hash(amduat_hash_id_t hash_id,
return true;
}
static int test_init_rejects_unsupported_encoding(void) {
amduat_tgk_store_mem_t mem;
amduat_tgk_store_config_t config;
amduat_asl_encoding_profile_id_t encodings[1];
memset(&mem, 0, sizeof(mem));
memset(&config, 0, sizeof(config));
encodings[0] = 0x9999u;
config.tgk_profiles.encodings = encodings;
config.tgk_profiles.encodings_len = 1;
if (amduat_tgk_store_mem_init(&mem, config, NULL, 0)) {
fprintf(stderr, "init accepted unsupported encoding\n");
amduat_tgk_store_mem_free(&mem);
return 1;
}
return 0;
}
static int test_resolve_edge_unsupported(const test_env_t *env) {
amduat_reference_t ref;
amduat_tgk_edge_body_t body;
@ -481,8 +530,10 @@ int main(void) {
if (test_resolve_edge_ok(&env) != 0 ||
test_resolve_edge_not_edge(&env) != 0 ||
test_resolve_edge_invalid_bytes(&env) != 0 ||
test_resolve_edge_missing(&env) != 0 ||
test_resolve_edge_unsupported(&env) != 0 ||
test_init_rejects_unsupported_encoding() != 0 ||
test_type_filter(&env) != 0 ||
test_ordering(&env) != 0 ||
test_adjacency(&env) != 0 ||