Skip to content

Possible memory leak: model path C.CString is never freed in NewOnnx #1444

Description

@OvOhao

Possible memory leak: model path C.CString is never freed in NewOnnx

NewOnnx passes the model path to CreateSession as an inline C.CString. The
allocation is not bound to a variable, so there is no name available to free it
afterwards.

go/onnx/onnx_runtime.go:21

	if err := C.CreateSession(ort.api, C.CString(modelPath), &ort.session, &ort.memory); err != nil {
		return nil, fmt.Errorf("create session: %v", C.GoString(C.GetErrorMessage(err)))
	}

go/onnx/onnx_runtime.h:15

OrtStatus *CreateSession(const OrtApi *ort, const char *model, OrtSession **session, OrtMemoryInfo **memory_info) {
	...
	RETURN_ON_ERROR(ort->CreateSession(env, model, options, session));

model is taken as const char * and handed to OrtApi::CreateSession, which
copies the path. Nothing takes ownership of the buffer, and CreateSession does
not free it, so the string leaks on every call, on both the success and the
error path.

Fix:

	cPath := C.CString(modelPath)
	defer C.free(unsafe.Pointer(cPath))
	if err := C.CreateSession(ort.api, cPath, &ort.session, &ort.memory); err != nil {

with #include <stdlib.h> in the preamble.

Separately, RETURN_ON_ERROR in CreateSession returns before releasing env
and options, and the OrtStatus returned to Go is never passed to
ReleaseStatus.

If you could credit me as a reporter for my contributions to security advisory I will be thankful.

Activity

  1. ryux1 commented on Sep 7, 2026

    @ryux1

    I verified the C.CString(modelPath) allocation is still passed inline on current main, so it has no corresponding C.free on either return path. I’ll send a focused PR that binds and frees only that Go-owned C string; the separate ONNX environment/options/status cleanup should remain separate work.

  2. OvOhao commented on Sep 11, 2026

    @OvOhao
    Author

    Thanks for picking this up. #1446 matches what I reported: it binds the
    conversion and defers the free, so both the error return and the success return
    release it.

    	cModelPath := C.CString(modelPath)
    	defer C.free(unsafe.Pointer(cModelPath))

    Agreed on keeping the ONNX environment, session options and OrtStatus cleanup
    separate, they are a different ownership question.

    The PR is still open at the time of writing, so leaving this issue open until it
    lands seems right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions