typedef __typeof__(sizeof(int)) size_t;
typedef int zx_status_t;
typedef __typeof__(sizeof(int)) zx_handle_t;
typedef unsigned int uint32_t;
#define NULL ((void *)0)
#define ZX_HANDLE_INVALID 0
#if defined(__clang__)
#define ZX_HANDLE_ACQUIRE __attribute__((acquire_handle("Fuchsia")))
#define ZX_HANDLE_RELEASE __attribute__((release_handle("Fuchsia")))
#define ZX_HANDLE_USE __attribute__((use_handle("Fuchsia")))
#define ZX_HANDLE_ACQUIRE_UNOWNED __attribute__((acquire_handle("FuchsiaUnowned")))
#else
#define ZX_HANDLE_ACQUIRE
#define ZX_HANDLE_RELEASE
#define ZX_HANDLE_USE
#define ZX_HANDLE_ACQUIRE_UNOWNED
#endif
zx_status_t zx_channel_create(
uint32_t options,
zx_handle_t *out0 ZX_HANDLE_ACQUIRE,
zx_handle_t *out1 ZX_HANDLE_ACQUIRE);
zx_status_t zx_handle_close(
zx_handle_t handle ZX_HANDLE_RELEASE);
ZX_HANDLE_ACQUIRE_UNOWNED
zx_handle_t zx_process_self();
void zx_process_self_param(zx_handle_t *out ZX_HANDLE_ACQUIRE_UNOWNED);
ZX_HANDLE_ACQUIRE
zx_handle_t return_handle();
void escape1(zx_handle_t *in);
void escape2(zx_handle_t in);
void (*escape3)(zx_handle_t) = escape2;
void use1(const zx_handle_t *in ZX_HANDLE_USE);
void use2(zx_handle_t in ZX_HANDLE_USE);
void moreArgs(zx_handle_t, int, ...);
void lessArgs(zx_handle_t, int a = 5);
struct MyType {
ZX_HANDLE_ACQUIRE
zx_handle_t operator+(zx_handle_t ZX_HANDLE_RELEASE replace);
};
void checkUnownedHandle01() {
zx_handle_t h0;
h0 = zx_process_self(); zx_handle_close(h0); }
void checkUnownedHandle02() {
zx_handle_t h0;
zx_process_self_param(&h0); zx_handle_close(h0); }
void checkInvalidHandle01() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
if (sa == ZX_HANDLE_INVALID)
;
use2(sa); zx_handle_close(sb);
zx_handle_close(sa);
}
void checkInvalidHandle2() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
if (sb != ZX_HANDLE_INVALID)
zx_handle_close(sb);
if (sa != ZX_HANDLE_INVALID)
zx_handle_close(sa);
}
void handleDieBeforeErrorSymbol01() {
zx_handle_t sa, sb;
zx_status_t status = zx_channel_create(0, &sa, &sb);
if (status < 0)
return;
__builtin_trap();
}
void handleDieBeforeErrorSymbol02() {
zx_handle_t sa, sb;
zx_status_t status = zx_channel_create(0, &sa, &sb);
if (status == 0) { return; }
__builtin_trap();
}
void checkNoCrash01() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
moreArgs(sa, 1, 2, 3, 4, 5);
lessArgs(sa);
zx_handle_close(sa);
zx_handle_close(sb);
}
void checkNoLeak01() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
zx_handle_close(sa);
zx_handle_close(sb);
}
void checkNoLeak02() {
zx_handle_t ay[2];
zx_channel_create(0, &ay[0], &ay[1]);
zx_handle_close(ay[0]);
zx_handle_close(ay[1]);
}
void checkNoLeak03() {
zx_handle_t ay[2];
zx_channel_create(0, &ay[0], &ay[1]);
for (int i = 0; i < 2; i++)
zx_handle_close(ay[i]);
}
zx_handle_t checkNoLeak04() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
zx_handle_close(sa);
return sb; }
zx_handle_t checkNoLeak05(zx_handle_t *out1) {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
*out1 = sa;
return sb; }
void checkNoLeak06() {
zx_handle_t sa, sb;
if (zx_channel_create(0, &sa, &sb))
return;
zx_handle_close(sa);
zx_handle_close(sb);
}
void checkLeak01(int tag) {
zx_handle_t sa, sb;
if (zx_channel_create(0, &sa, &sb)) return; use1(&sa);
if (tag) zx_handle_close(sa);
use2(sb); zx_handle_close(sb);
}
void checkLeakFromReturn01(int tag) {
zx_handle_t sa = return_handle(); (void)sa;
}
void checkReportLeakOnOnePath(int tag) {
zx_handle_t sa, sb;
if (zx_channel_create(0, &sa, &sb)) return; zx_handle_close(sb);
switch (tag) { case 0:
use2(sa);
return;
case 1:
use2(sa);
return;
case 2:
use2(sa);
return;
case 3:
use2(sa);
return;
case 4:
use2(sa);
return;
default:
use2(sa);
return; }
}
void checkDoubleRelease01(int tag) {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
if (tag) zx_handle_close(sa); zx_handle_close(sa); zx_handle_close(sb);
}
void checkUseAfterFree01(int tag) {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
if (tag) {
zx_handle_close(sa); use1(&sa); }
zx_handle_close(sb); use2(sb); }
void checkMemberOperatorIndices() {
zx_handle_t sa, sb, sc;
zx_channel_create(0, &sa, &sb);
zx_handle_close(sb);
MyType t;
sc = t + sa;
zx_handle_close(sc);
}
struct HandleStruct {
zx_handle_t h;
};
void close_handle_struct(HandleStruct hs ZX_HANDLE_RELEASE);
void use_handle_struct(HandleStruct hs ZX_HANDLE_USE);
void checkHandleInStructureUseAfterFree() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb); HandleStruct hs;
hs.h = sb;
use_handle_struct(hs);
close_handle_struct(hs); zx_handle_close(sa);
use2(sb); }
void checkHandleInStructureUseAfterFree2() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb); HandleStruct hs;
hs.h = sb;
use_handle_struct(hs);
zx_handle_close(sb); zx_handle_close(sa);
use_handle_struct(hs); }
void checkHandleInStructureLeak() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb); HandleStruct hs;
hs.h = sb;
zx_handle_close(sa); }
struct HandlePtrStruct {
zx_handle_t *h;
};
void close_handle_struct(HandlePtrStruct hs ZX_HANDLE_RELEASE);
void use_handle_struct(HandlePtrStruct hs ZX_HANDLE_USE);
void checkHandlePtrInStructureUseAfterFree() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
HandlePtrStruct hs;
hs.h = &sb;
use_handle_struct(hs);
close_handle_struct(hs); zx_handle_close(sa);
use2(sb); }
void checkHandlePtrInStructureUseAfterFree2() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb);
HandlePtrStruct hs;
hs.h = &sb;
use_handle_struct(hs);
zx_handle_close(sb); zx_handle_close(sa);
use_handle_struct(hs); }
void checkHandlePtrInStructureLeak() {
zx_handle_t sa, sb;
zx_channel_create(0, &sa, &sb); HandlePtrStruct hs;
hs.h = &sb;
zx_handle_close(sa); }
zx_status_t test_release_handle(zx_handle_t handle ZX_HANDLE_RELEASE) {
return zx_handle_close(handle);
}
void checkReleaseImplementedFunc() {
zx_handle_t a, b;
zx_channel_create(0, &a, &b);
zx_handle_close(a);
test_release_handle(b);
}
void use_handle(zx_handle_t handle) {
}
void test_call_by_value() {
zx_handle_t a, b;
zx_channel_create(0, &a, &b);
zx_handle_close(a);
use_handle(b);
zx_handle_close(b);
}
void test_call_by_value_leak() {
zx_handle_t a, b;
zx_channel_create(0, &a, &b); zx_handle_close(a);
use_handle(b);
}
template <typename T>
struct HandleWrapper {
~HandleWrapper() { close(); }
void close() {
if (handle != ZX_HANDLE_INVALID)
zx_handle_close(handle);
}
T *get_handle_address() { return &handle; }
private:
T handle;
};
void doNotWarnOnRAII() {
HandleWrapper<zx_handle_t> w1;
zx_handle_t sb;
if (zx_channel_create(0, w1.get_handle_address(), &sb))
return;
zx_handle_close(sb);
}
template <typename T>
struct HandleWrapperUnkonwDtor {
~HandleWrapperUnkonwDtor();
void close() {
if (handle != ZX_HANDLE_INVALID)
zx_handle_close(handle);
}
T *get_handle_address() { return &handle; }
private:
T handle;
};
void doNotWarnOnUnknownDtor() {
HandleWrapperUnkonwDtor<zx_handle_t> w1;
zx_handle_t sb;
if (zx_channel_create(0, w1.get_handle_address(), &sb))
return;
zx_handle_close(sb);
}
zx_handle_t *get_handle_address();
void escape_store_to_escaped_region01() {
zx_handle_t sb;
if (zx_channel_create(0, get_handle_address(), &sb))
return;
zx_handle_close(sb);
}
struct object {
zx_handle_t *get_handle_address();
};
void escape_store_to_escaped_region02(object &o) {
zx_handle_t sb;
if (zx_channel_create(0, o.get_handle_address(), &sb))
return;
zx_handle_close(sb);
}
void escape_store_to_escaped_region03(object o) {
zx_handle_t sb;
if (zx_channel_create(0, o.get_handle_address(), &sb))
return;
zx_handle_close(sb);
}
void escape_through_call(int tag) {
zx_handle_t sa, sb;
if (zx_channel_create(0, &sa, &sb))
return;
escape1(&sa);
if (tag)
escape2(sb);
else
escape3(sb);
}
struct have_handle {
zx_handle_t h;
zx_handle_t *hp;
};
void escape_through_store01(have_handle *handle) {
zx_handle_t sa;
if (zx_channel_create(0, &sa, handle->hp))
return;
handle->h = sa;
}
have_handle global;
void escape_through_store02() {
zx_handle_t sa;
if (zx_channel_create(0, &sa, global.hp))
return;
global.h = sa;
}
have_handle escape_through_store03() {
zx_handle_t sa, sb;
if (zx_channel_create(0, &sa, &sb))
return {0, nullptr};
zx_handle_close(sb);
return {sa, nullptr};
}
void escape_structs(have_handle *);
void escape_transitively01() {
zx_handle_t sa, sb;
if (zx_channel_create(0, &sa, &sb))
return;
have_handle hs[2];
hs[1] = {sa, &sb};
escape_structs(hs);
}
void escape_top_level_pointees(zx_handle_t *h) {
zx_handle_t h2;
if (zx_channel_create(0, h, &h2))
return;
zx_handle_close(h2);
}