3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-08-02 20:23:27 +00:00

Fix polymorphic application arity validation (#10179)

## Summary

Validate a polymorphic declaration's arity before matching argument
sorts. This prevents
`Z3_mk_app` from reading past the declaration domain and makes both
too-few and too-many
arguments return `Z3_INVALID_ARG`.

Adds C API regression coverage for valid, too-few, and too-many
applications.

Fixes #10177.

## Testing

- `./build-release/test-z3 api`
- `./build-release/test-z3 /a` (92 passed)
- Standalone #10177 reproducer against the patched shared library
This commit is contained in:
1sgtpepper 2026-07-22 10:11:38 +08:00 committed by GitHub
parent 0105b220fd
commit 479ff3476e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 107 additions and 8 deletions

View file

@ -40,6 +40,80 @@ void test_apps() {
Z3_del_context(ctx);
}
static void test_mk_app_polymorphic_arity() {
Z3_config cfg = Z3_mk_config();
Z3_context ctx = Z3_mk_context(cfg);
Z3_del_config(cfg);
Z3_set_error_handler(ctx, [](Z3_context, Z3_error_code) {});
Z3_sort type_var = Z3_mk_type_variable(ctx, Z3_mk_string_symbol(ctx, "A"));
Z3_func_decl f = Z3_mk_func_decl(ctx, Z3_mk_string_symbol(ctx, "f"), 1, &type_var, type_var);
Z3_sort int_sort = Z3_mk_int_sort(ctx);
Z3_ast args[] = {
Z3_mk_int(ctx, 1, int_sort), Z3_mk_int(ctx, 2, int_sort), Z3_mk_int(ctx, 3, int_sort)
};
ENSURE(Z3_mk_app(ctx, f, 1, args));
ENSURE(Z3_get_error_code(ctx) == Z3_OK);
ENSURE(!Z3_mk_app(ctx, f, 0, nullptr));
ENSURE(Z3_get_error_code(ctx) == Z3_INVALID_ARG);
ENSURE(!Z3_mk_app(ctx, f, 2, args));
ENSURE(Z3_get_error_code(ctx) == Z3_INVALID_ARG);
Z3_sort set_type_var = Z3_mk_set_sort(ctx, type_var);
Z3_ast poly_set = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "poly_set"), set_type_var);
Z3_ast poly_sets[] = { poly_set, poly_set };
Z3_ast set_union = Z3_mk_set_union(ctx, 2, poly_sets);
Z3_func_decl set_union_decl = Z3_get_app_decl(ctx, Z3_to_app(ctx, set_union));
ENSURE(Z3_get_arity(ctx, set_union_decl) == 2);
Z3_sort int_set_sort = Z3_mk_set_sort(ctx, int_sort);
Z3_ast int_sets[] = {
Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "int_set1"), int_set_sort),
Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "int_set2"), int_set_sort),
Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "int_set3"), int_set_sort)
};
ENSURE(Z3_mk_app(ctx, set_union_decl, 1, int_sets));
ENSURE(Z3_get_error_code(ctx) == Z3_OK);
Z3_ast set_union3 = Z3_mk_app(ctx, set_union_decl, 3, int_sets);
ENSURE(set_union3);
ENSURE(Z3_get_error_code(ctx) == Z3_OK);
Z3_app set_union3_app = Z3_to_app(ctx, set_union3);
Z3_func_decl set_union3_decl = Z3_get_app_decl(ctx, set_union3_app);
ENSURE(Z3_get_arity(ctx, set_union3_decl) == 2);
ENSURE(Z3_get_app_num_args(ctx, set_union3_app) == 2);
ENSURE(Z3_get_app_arg(ctx, set_union3_app, 0) == int_sets[0]);
Z3_app set_union3_tail = Z3_to_app(ctx, Z3_get_app_arg(ctx, set_union3_app, 1));
ENSURE(Z3_get_app_num_args(ctx, set_union3_tail) == 2);
ENSURE(Z3_get_app_arg(ctx, set_union3_tail, 0) == int_sets[1]);
ENSURE(Z3_get_app_arg(ctx, set_union3_tail, 1) == int_sets[2]);
Z3_sort bool_set_sort = Z3_mk_set_sort(ctx, Z3_mk_bool_sort(ctx));
Z3_ast bool_set = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "bool_set"), bool_set_sort);
Z3_ast incompatible_sets[] = { int_sets[0], int_sets[1], bool_set };
ENSURE(!Z3_mk_app(ctx, set_union_decl, 3, incompatible_sets));
ENSURE(Z3_get_error_code(ctx) == Z3_INVALID_ARG);
Z3_ast poly_value = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "poly_value"), type_var);
Z3_ast poly_eq = Z3_mk_eq(ctx, poly_value, poly_value);
Z3_func_decl eq_decl = Z3_get_app_decl(ctx, Z3_to_app(ctx, poly_eq));
ENSURE(Z3_mk_app(ctx, eq_decl, 3, args));
ENSURE(Z3_get_error_code(ctx) == Z3_OK);
Z3_sort re_type_var = Z3_mk_re_sort(ctx, Z3_mk_seq_sort(ctx, type_var));
Z3_ast empty_re_type_var = Z3_mk_re_empty(ctx, re_type_var);
Z3_ast poly_res[] = { empty_re_type_var, empty_re_type_var };
Z3_ast re_union = Z3_mk_re_union(ctx, 2, poly_res);
Z3_func_decl re_union_decl = Z3_get_app_decl(ctx, Z3_to_app(ctx, re_union));
Z3_sort re_int = Z3_mk_re_sort(ctx, Z3_mk_seq_sort(ctx, int_sort));
Z3_ast empty_re_int = Z3_mk_re_empty(ctx, re_int);
Z3_ast int_res[] = { empty_re_int, empty_re_int, empty_re_int };
ENSURE(Z3_mk_app(ctx, re_union_decl, 3, int_res));
ENSURE(Z3_get_error_code(ctx) == Z3_OK);
Z3_del_context(ctx);
}
void test_bvneg() {
Z3_config cfg = Z3_mk_config();
Z3_set_param_value(cfg,"MODEL","true");
@ -305,6 +379,7 @@ void test_max_reg() {
void tst_api() {
test_apps();
test_mk_app_polymorphic_arity();
test_bvneg();
test_mk_distinct();
test_optimize_translate();