telegabber/e2ee/omemo/libsignal/address.go
Bohdan Horbeshko 3751113015 e2ee tests
2026-07-28 18:49:48 -04:00

55 lines
1.7 KiB
Go

package libsignal
/*
#include <stdlib.h>
#include <signal_protocol.h>
*/
import "C"
import "unsafe"
// Address identifies a Signal Protocol session peer: a logical recipient
// name (for OMEMO, a bare JID) plus a numeric device ID.
type Address struct {
Name string
DeviceID uint32
}
// cAddress is a C-heap-allocated signal_protocol_address (struct and name
// string both), for the specific cases - session_builder_create and
// session_cipher_create - where the C library stores the *pointer* we pass
// it and keeps dereferencing it for the object's entire lifetime (a
// shallow assignment, e.g. `result_cipher->remote_address = remote_address;`
// in session_cipher.c, confirmed by reading the source - not a defensive
// copy). A transient, freed-after-the-call address (as a short-lived cgo
// helper would naturally produce) becomes a use-after-free the moment the
// constructor returns; this type's lifetime must instead match its owning
// SessionBuilder/SessionCipher, freed only in their Close methods.
type cAddress struct {
ptr *C.signal_protocol_address
}
func newCAddress(addr Address) *cAddress {
namePtr := C.CString(addr.Name)
c := (*C.signal_protocol_address)(C.malloc(C.size_t(unsafe.Sizeof(C.signal_protocol_address{}))))
c.name = namePtr
c.name_len = C.size_t(len(addr.Name))
c.device_id = C.int32_t(addr.DeviceID)
return &cAddress{ptr: c}
}
func (a *cAddress) free() {
if a.ptr != nil {
C.free(unsafe.Pointer(a.ptr.name))
C.free(unsafe.Pointer(a.ptr))
a.ptr = nil
}
}
// addressFromC copies a C signal_protocol_address into a Go Address.
func addressFromC(addr *C.signal_protocol_address) Address {
return Address{
Name: C.GoStringN(addr.name, C.int(addr.name_len)),
DeviceID: uint32(addr.device_id),
}
}