Skip to content

panic: index out of range in getBytesAndSize on empty event payload (StreamReplaced) crashes process #194

Description

@rbinar

Summary

getBytesAndSize panics with index out of range [0] with length 0 and crashes the whole process (SIGABRT) when an event's marshaled payload is empty. Reproducibly triggered by a StreamReplaced event.

Version

neonize 0.3.18.post0 (latest), Linux x86_64, Python 3.12.

Traceback (from production)

INFO  Successfully authenticated
INFO  Got replaced stream error, sending StreamReplaced event
panic: runtime error: index out of range [0] with length 0

goroutine 18 [running, locked to thread]:
main.getBytesAndSize(...)
	/home/runner/work/neonize/neonize/goneonize/main.go:341
main.CallbackFunction({...}, ...)
	/home/runner/work/neonize/neonize/goneonize/main.go:2444 +0x1eb
main.Neonize(...)
	/home/runner/work/neonize/neonize/goneonize/main.go:1092 +0xad5

Root cause

getBytesAndSize (goneonize/main.go:340-344) dereferences &data[0]:

func getBytesAndSize(data []byte) (*C.char, C.size_t) {
	messageSourceCDATA := (*C.char)(unsafe.Pointer(&data[0]))  // panics when len(data)==0
	messageSourceCSize := C.size_t(len(data))
	return messageSourceCDATA, messageSourceCSize
}

CallbackFunction (main.go:2444) calls it with proto.Marshal(message.message). For some events (observed: StreamReplaced) the marshaled message is empty (0 bytes), so &data[0] panics and aborts the runtime — taking down the entire host process.

Impact

Any session that receives a StreamReplaced event (e.g. the same account's stream is taken over by another client) crashes the process. Under supervisor/systemd this becomes a crash-restart loop (reconnect → StreamReplaced → panic → restart → …), making the service unusable and blocking new QR pairings.

Proposed fix

Guard getBytesAndSize against empty input:

func getBytesAndSize(data []byte) (*C.char, C.size_t) {
	if len(data) == 0 {
		return nil, 0
	}
	messageSourceCDATA := (*C.char)(unsafe.Pointer(&data[0]))
	messageSourceCSize := C.size_t(len(data))
	return messageSourceCDATA, messageSourceCSize
}

(The C side already receives an explicit size, so a nil/0 pair for empty payloads is safe.)

Activity

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions