diff --git a/MEMORY.md b/MEMORY.md new file mode 100644 index 0000000..19a5400 --- /dev/null +++ b/MEMORY.md @@ -0,0 +1,27 @@ +# Memory Model + +This document provides an overview of the memory model of libCwtch. Callers should consult this document to ensure +that they are properly handling pointers passed to-and-from libCwtch. + +## Pointer Parameters + +All pointers **passed** into functions in this library, except `c_FreePointer`, are assumed to be owned by the caller. + +libCwtch **will not** modifying the underlying memory, nor attempt to free or otherwise modify these pointers. + +This is realized by copying the underlying memory using `C.GoStringN`. libCwtch guarantees that it will not depend +on the underlying memory of these pointers being available after returning from this function. + +Callers are responsible for freeing these pointers after the call has been completed. + +## Returned Pointers + +All pointers **returned** by functions in libCwtch should be assumed to owned by libCwtch + +Callers **must not** modifying the underlying memory of these pointers, nor attempt to free or otherwise modify these pointers +through any method other than the one provided below. + +Calling functions **must** copy the contents of the memory into their own memory space and then call `c_FreePointer` providing +the returned pointer as a parameter. + +libCwtch guarantees that it will not modify or free the underlying memory of these pointers prior to a call to `c_FreePointer`. \ No newline at end of file diff --git a/lib.go b/lib.go index 699269b..b4ce058 100644 --- a/lib.go +++ b/lib.go @@ -2,7 +2,10 @@ package main +// //Needed to invoke C.free +// #include import "C" + import ( "crypto/rand" "cwtch.im/cwtch/app" @@ -21,6 +24,7 @@ import ( "runtime" "strconv" "strings" + "unsafe" "encoding/base64" "git.openprivacy.ca/openprivacy/connectivity/tor" @@ -381,6 +385,7 @@ func SendProfileEvent(onion string, eventJson string) { } //export c_GetAppBusEvent +// the pointer returned from this function **must** be freed using c_Free func c_GetAppBusEvent() *C.char { return C.CString(GetAppBusEvent()) } @@ -427,20 +432,6 @@ func LoadProfiles(pass string) { application.LoadProfiles(pass) } -//export c_ContactEvents -func c_ContactEvents() *C.char { - return C.CString(ContactEvents()) -} - -func ContactEvents() string { - select { - case myevent := <-contactEventsQueue.OutChan(): - return fmt.Sprintf("%v", myevent) - default: - return "" - } -} - //export c_AcceptContact func c_AcceptContact(profilePtr *C.char, profileLen C.int, handlePtr *C.char, handleLen C.int) { AcceptContact(C.GoStringN(profilePtr, profileLen), C.GoStringN(handlePtr, handleLen)) @@ -520,6 +511,7 @@ func UpdateMessageFlags(profileOnion, handle string, mIdx int, flags int64) { } //export c_GetMessage +// the pointer returned from this function **must** be Freed by c_Free func c_GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char { profile := C.GoStringN(profile_ptr, profile_len) handle := C.GoStringN(handle_ptr, handle_len) @@ -585,6 +577,7 @@ func GetMessage(profileOnion, handle string, message_index int) string { } //export c_GetMessagesByContentHash +// the pointer returned from this function **must** be freed by calling c_Free func c_GetMessagesByContentHash(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, contenthash_ptr *C.char, contenthash_len C.int) *C.char { profile := C.GoStringN(profile_ptr, profile_len) handle := C.GoStringN(handle_ptr, handle_len) @@ -592,6 +585,12 @@ func c_GetMessagesByContentHash(profile_ptr *C.char, profile_len C.int, handle_p return C.CString(GetMessagesByContentHash(profile, handle, contentHash)) } +//export c_FreePointer +// Dangerous function. Should only be used as documented in `MEMORY.md` +func c_FreePointer(ptr *C.char) { + C.free(unsafe.Pointer(ptr)) +} + func GetMessagesByContentHash(profileOnion, handle string, contentHash string) string { var indexedMessages []model.LocallyIndexedMessage if application != nil {