objectbox-go icon indicating copy to clipboard operation
objectbox-go copied to clipboard

Fix bug in dataVisitorDispatch

Open chzhongsending opened this issue 2 years ago • 0 comments

The obx_data_visitor in ObjectBox Core (C library) is:

/// The callback for reading data one-by-one
/// @param data is the read data buffer
/// @param size specifies the length of the read data
/// @param user_data is a pass-through argument passed to the called API
/// @return true to keep going, false to cancel.
typedef bool obx_data_visitor(const void* data, size_t size, void* user_data);

// ...

/// Walk over matching objects using the given data visitor
OBX_C_API obx_err obx_query_visit(OBX_query* query, obx_data_visitor* visitor, void* user_data);

The first two parameter should be data and size according to the C header file, the third parameter is the user data. But objectbox-go defined dataVisitorDispatch function in Go has a wrong parameter order:

// datavisitor.go
var dataVisitor = (*C.obx_data_visitor)(unsafe.Pointer(C.dataVisitorDispatch))

// datavisitorc.go
//export dataVisitorDispatch
// This function finds the data visitor (based on the pointer to the visitorId) and calls it with the given data
// NOTE: don't change ptr contents, it's `const void*` in C but go doesn't support const pointers
func dataVisitorDispatch(visitorIdPtr unsafe.Pointer, data unsafe.Pointer, size C.size_t) C.bool {
// ...
}

visitorIdPtr was passed as user data here:

// Find returns all objects matching the query
func (query *Query) Find() (objects interface{}, err error) {
	defer runtime.KeepAlive(query)

	if err := query.check(); err != nil {
		return nil, err
	}

	const existingOnly = true
	if supportsResultArray {
		var cFn = func() *C.OBX_bytes_array {
			return C.obx_query_find(query.cQuery)
		}
		return query.box.readManyObjects(existingOnly, cFn)
	}

	var cFn = func(visitorArg unsafe.Pointer) C.obx_err {
                // visitorArg is passed as user data here
		return C.obx_query_visit(query.cQuery, dataVisitor, visitorArg)
	}
	return query.box.readUsingVisitor(existingOnly, cFn)
}

This might lead to a crash when you use a ObjectBox Core C version without OBXFeature_ResultArray (e.g. Mobile version like iOS). Simply re-order the parameter will fix this issue:

func dataVisitorDispatch(data unsafe.Pointer, size C.size_t, visitorIdPtr unsafe.Pointer) C.bool

chzhongsending avatar Aug 17 '23 04:08 chzhongsending