CALL(3, 1, "mach_vm_deallocate"),
CALL(2, 0, "mig_deallocate"),
CALL(2, 1, "mach_port_deallocate"),
+ CALL(1, 0, "device_deallocate"),
+ CALL(1, 0, "iokit_remove_connect_reference"),
+ CALL(1, 0, "iokit_remove_reference"),
+ CALL(1, 0, "iokit_release_port"),
+ CALL(1, 0, "ipc_port_release"),
+ CALL(1, 0, "ipc_port_release_sonce"),
+ CALL(1, 0, "ipc_voucher_attr_control_release"),
+ CALL(1, 0, "ipc_voucher_release"),
+ CALL(1, 0, "lock_set_dereference"),
+ CALL(1, 0, "memory_object_control_deallocate"),
+ CALL(1, 0, "pset_deallocate"),
+ CALL(1, 0, "semaphore_dereference"),
+ CALL(1, 0, "space_deallocate"),
+ CALL(1, 0, "space_inspect_deallocate"),
+ CALL(1, 0, "task_deallocate"),
+ CALL(1, 0, "task_inspect_deallocate"),
+ CALL(1, 0, "task_name_deallocate"),
+ CALL(1, 0, "thread_deallocate"),
+ CALL(1, 0, "thread_inspect_deallocate"),
+ CALL(1, 0, "upl_deallocate"),
+ CALL(1, 0, "vm_map_deallocate"),
// E.g., if the checker sees a method 'releaseAsyncReference64()' that is
// defined on class 'IOUserClient' that takes exactly 1 argument, it knows
// that the argument is going to be consumed in the sense of the MIG
// consume-on-success convention.
CALL(1, 0, "IOUserClient", "releaseAsyncReference64"),
+ CALL(1, 0, "IOUserClient", "releaseNotificationPort"),
#undef CALL
};
typedef unsigned vm_size_t;
typedef void *ipc_space_t;
typedef unsigned long io_user_reference_t;
+typedef struct ipc_port *ipc_port_t;
+typedef unsigned mach_port_t;
+typedef uint32_t UInt32;
kern_return_t vm_deallocate(mach_port_name_t, vm_address_t, vm_size_t);
kern_return_t mach_vm_deallocate(mach_port_name_t, vm_address_t, vm_size_t);
void mig_deallocate(vm_address_t, vm_size_t);
kern_return_t mach_port_deallocate(ipc_space_t, mach_port_name_t);
+void ipc_port_release(ipc_port_t);
#define MIG_SERVER_ROUTINE __attribute__((mig_server_routine))
class IOUserClient {
public:
static IOReturn releaseAsyncReference64(OSAsyncReference64);
+ static IOReturn releaseNotificationPort(mach_port_t port);
MIG_SERVER_ROUTINE
- virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments *arguments,
- IOExternalMethodDispatch *dispatch = 0, OSObject *target = 0, void *reference = 0);
-};
+ virtual IOReturn externalMethod(
+ uint32_t selector, IOExternalMethodArguments *arguments,
+ IOExternalMethodDispatch *dispatch = 0, OSObject *target = 0,
+ void *reference = 0);
+ MIG_SERVER_ROUTINE
+ virtual IOReturn registerNotificationPort(mach_port_t, UInt32, UInt32);
+};
// Tests.
// expected-note@-1{{MIG callback fails with error after deallocating argument value}}
}
+MIG_SERVER_ROUTINE
+kern_return_t test_ipc_port_release(ipc_port_t port) {
+ ipc_port_release(port); // expected-note{{Value passed through parameter 'port' is deallocated}}
+ return KERN_ERROR; // expected-warning{{MIG callback fails with error after deallocating argument value}}
+ // expected-note@-1{{MIG callback fails with error after deallocating argument value}}
+}
+
// Let's try the C++11 attribute spelling syntax as well.
[[clang::mig_server_routine]]
IOReturn test_releaseAsyncReference64(IOExternalMethodArguments *arguments) {
return kIOReturnError; // expected-warning{{MIG callback fails with error after deallocating argument value}}
// expected-note@-1{{MIG callback fails with error after deallocating argument value}}
}
+
+ IOReturn registerNotificationPort(mach_port_t port, UInt32 x, UInt32 y) {
+ releaseNotificationPort(port); // expected-note{{Value passed through parameter 'port' is deallocated}}
+ return kIOReturnError; // expected-warning{{MIG callback fails with error after deallocating argument value}}
+ // expected-note@-1{{MIG callback fails with error after deallocating argument value}}
+ }
};