commit 2440fa356713a6a5e24841131db5ecafa143a0ed from: Isaac Meerleo date: Sat Jul 18 15:47:23 2026 UTC Prove exact Artifact result boundaries commit - ade20e173499fe07ed4a9826662db533fc795456 commit + 2440fa356713a6a5e24841131db5ecafa143a0ed blob - 284b995e0acc3f061f32013d5d482c128af327ce blob + 1090a5bf0d5dc1f8c9e76e79baba43a936f5db9a --- regress/artifact_result/artifact_result_test.c +++ regress/artifact_result/artifact_result_test.c @@ -224,6 +224,83 @@ test_boundary_selection(void) } static void +test_exact_inline_boundaries(void) +{ + static const struct { + const char *name; + u_char byte; + const char *encoding; + size_t encoded_step; + } shapes[] = { + { "printable", 'x', "utf-8", 1 }, + { "escape-heavy", '\1', "utf-8", 6 }, + { "NUL", '\0', "utf-8", 6 }, + { "invalid UTF-8/base64", 0xff, "base64", 4 } + }; + struct artifact_result in; + struct json j; + struct buf out; + char *encoding; + u_char *raw; + size_t elen, hi, i, lo, mid; + int root; + + raw = malloc(ARTIFACT_RESULT_MAX + 1); + CHECK(raw != NULL); + if (raw == NULL) + return; + buf_init(&out); + for (i = 0; i < sizeof(shapes) / sizeof(shapes[0]); i++) { + memset(raw, shapes[i].byte, ARTIFACT_RESULT_MAX + 1); + lo = 0; + hi = ARTIFACT_RESULT_MAX + 1; + while (lo + 1 < hi) { + mid = lo + (hi - lo) / 2; + if (artifact_result_inline_fits(raw, mid)) + lo = mid; + else + hi = mid; + } + CHECK(lo != 0 && artifact_result_inline_fits(raw, lo)); + CHECK(!artifact_result_inline_fits(raw, lo + 1)); + + memset(&in, 0, sizeof(in)); + in.raw = raw; + in.raw_len = lo; + in.observed_bytes = lo; + in.retained_bytes = lo; + in.termination = ARTIFACT_TERM_EXIT; + CHECK(artifact_result_build(&out, &in) == 0 && + out.len <= ARTIFACT_RESULT_MAX && + ARTIFACT_RESULT_MAX - out.len < shapes[i].encoded_step); + CHECK(json_parse(&j, out.data, out.len, 0) == 0); + root = json_root(&j); + CHECK(json_get_bool(&j, json_obj_get(&j, root, + "preview_abbreviated")) == 0); + encoding = string_field(&j, root, "preview_encoding", &elen); + CHECK(encoding != NULL && elen == strlen(shapes[i].encoding) && + memcmp(encoding, shapes[i].encoding, elen) == 0); + free(encoding); + json_done(&j); + + in.raw_len = lo + 1; + in.observed_bytes = lo + 1; + in.retained_bytes = lo + 1; + in.id = good_id; + CHECK(artifact_result_build(&out, &in) == 0 && + out.len <= ARTIFACT_RESULT_MAX); + CHECK(json_parse(&j, out.data, out.len, 0) == 0); + root = json_root(&j); + CHECK(json_get_bool(&j, json_obj_get(&j, root, + "preview_abbreviated")) == 1); + json_done(&j); + (void)shapes[i].name; + } + buf_free(&out); + free(raw); +} + +static void test_error_metadata_is_not_spoofable(void) { static const char detail[] = "spawn failed before capture"; @@ -462,6 +539,7 @@ main(void) test_encoded_budgets_and_id(); test_binary_base64(); test_boundary_selection(); + test_exact_inline_boundaries(); test_error_metadata_is_not_spoofable(); test_json_integer_range(); test_empty_streaming_capture_is_inline();