Skip to content

Commit 9480f6c

Browse files
committed
rewriter: emit ia2_type_registry_* calls and turn on type_confusion tests
`WITHOUT_SANDBOX` is added in `CMakeLists.txt`, as the tracer bug that causes tests to hang indefinitely is fixed in #488, but #488 is now moved out of this PR stack, as it needs more work.
1 parent 75bbe9e commit 9480f6c

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

tests/type_confusion/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ define_test(
1010
PKEY 1
1111
NEEDS_LD_WRAP
1212
CRITERION_TEST
13+
WITHOUT_SANDBOX # TODO remove once tracer bug (#488) is fixed
1314
)
1415

1516
# Build the wrapper lib

tests/type_confusion/main.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,28 @@ Test(type_confusion, normal) {
2525
dav1d_close(&c);
2626
}
2727

28-
Test(type_confusion, uninitialized,
29-
// .signal = SIGABRT, // TODO turn on once type confusion checking is working
30-
) {
28+
Test(type_confusion, uninitialized, .signal = SIGABRT) {
3129
dav1d_open(&c, &settings);
3230
// Try to use another `Dav1dContext` that hasn't been constructed/opened yet.
3331
dav1d_get_picture(&c2, &pic);
3432
dav1d_close(&c);
3533
}
3634

37-
Test(type_confusion, wrong_type,
38-
// .signal = SIGABRT, // TODO turn on once type confusion checking is working
39-
) {
35+
Test(type_confusion, wrong_type, .signal = SIGABRT) {
4036
dav1d_open(&c, &settings);
4137
// Try to use another type (`Dav1dPicture`) instead.
4238
dav1d_get_picture((Dav1dContext *)&pic, &pic);
4339
dav1d_close(&c);
4440
}
4541

46-
Test(type_confusion, null,
47-
// .signal = SIGABRT, // TODO turn on once type confusion checking is working
48-
) {
42+
Test(type_confusion, null, .signal = SIGABRT) {
4943
dav1d_open(&c, &settings);
5044
// Try to `NULL`.
5145
dav1d_get_picture(NULL, &pic);
5246
dav1d_close(&c);
5347
}
5448

55-
Test(type_confusion, use_after_free,
56-
// .signal = SIGABRT, // TODO turn on once type confusion checking is working
57-
) {
49+
Test(type_confusion, use_after_free, .signal = SIGABRT) {
5850
dav1d_open(&c, &settings);
5951
dav1d_close(&c);
6052
// Try to use an already destructed `Dav1dContext`.

tools/rewriter/GenCallAsm.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,60 @@ std::string emit_asm_wrapper(
11471147

11481148
emit_prologue(aw, caller_pkey, target_pkey, arch);
11491149

1150+
// Check types that have (both) {con,de}structors.
1151+
// Check types in the type registry.
1152+
// If the function is itself a constructor or destructor,
1153+
// call `ia2_type_registry_{con,de}struct`.
1154+
// Otherwise, go through all of the args,
1155+
// and if they have (both) {con,de}structors
1156+
// and are one of the 6 x86 register args,
1157+
// call `ia2_type_registry_check`.
1158+
// TODO make x86 only
1159+
std::string_view ia2_type_registry_fn_kind;
1160+
std::string ia2_type_registry_fn_name;
1161+
std::vector<size_t> arg_indices_to_check;
1162+
if (target_name) {
1163+
if (ctx.constructors.find(*target_name) != ctx.constructors.end()) {
1164+
ia2_type_registry_fn_kind = "construct";
1165+
arg_indices_to_check.emplace_back(0);
1166+
} else if (ctx.destructors.find(*target_name) != ctx.destructors.end()) {
1167+
ia2_type_registry_fn_kind = "destruct";
1168+
arg_indices_to_check.emplace_back(0);
1169+
} else {
1170+
ia2_type_registry_fn_kind = "check";
1171+
for (auto i = 0; i < sig.api.args.size(); i++) {
1172+
const auto &arg = sig.api.args[i];
1173+
const auto &type = ctx.types.get(arg.type);
1174+
if (!type.has_structors()) {
1175+
continue;
1176+
}
1177+
if (i >= x86_int_param_reg_order.size()) {
1178+
llvm::errs() << "skipping checking type " << type.canonical_name << " type ID " << type.id << " for arg #" << i << " of function " << *target_name << "\n";
1179+
continue;
1180+
}
1181+
arg_indices_to_check.emplace_back(i);
1182+
}
1183+
}
1184+
ia2_type_registry_fn_name = llvm::formatv("ia2_type_registry_{0}", ia2_type_registry_fn_kind);
1185+
}
1186+
1187+
if (!arg_indices_to_check.empty()) {
1188+
emit_save_args(aw, arch);
1189+
emit_align_stack(aw, arch);
1190+
for (const auto i : arg_indices_to_check) {
1191+
const auto &arg = sig.api.args[i];
1192+
const auto &type = ctx.types.get(arg.type);
1193+
add_comment_line(aw, llvm::formatv("{0}ing type {1}, type ID {2}, arg #{3}", ia2_type_registry_fn_kind, type.canonical_name, type.id, i));
1194+
// `ia2_type_registry_*` arg 0 is a ptr of type `T*` from arg i.
1195+
add_asm_line(aw, llvm::formatv("movq {0}(%rsp), %{1}", 8 + 8 * (x86_int_param_reg_order.size() - 1 - i), x86_int_param_reg_order[0]));
1196+
// `ia2_type_registry_*` arg 1 is the `TypeId`.
1197+
add_asm_line(aw, llvm::formatv("movq ${0}, %{1}", type.id, x86_int_param_reg_order[1]));
1198+
emit_direct_call(aw, arch, ia2_type_registry_fn_name);
1199+
}
1200+
emit_revert_align_stack(aw, arch);
1201+
emit_restore_args(aw, arch, /* pop */ true);
1202+
}
1203+
11501204
// Call the pre-condition functions for this target function.
11511205
// The calls happens in the caller's compartment.
11521206
// If there are any post-condition functions, save the args for that, too.

0 commit comments

Comments
 (0)