Skip to content

bitsets are misaligned on 32-bit architectures #527

@slingamn

Description

@slingamn

Testing on my trusty x86-32 machine:

panic: runtime error: invalid memory address or nil pointer dereference                                                       
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x804a9eb] 
                                                                                                                             
goroutine 21 [running]:                                          
runtime/internal/atomic.Load64(0x980c394, 0x2800, 0x84e4060)              
        /usr/local/go/src/runtime/internal/atomic/asm_386.s:194 +0xb                                 
github.com/oragono/oragono/irc/utils.BitsetGet(0x980c394, 0x1, 0x1, 0xc, 0x980c2d0)               
        /home/shivaram/go/src/github.com/oragono/oragono/irc/utils/bitset.go:16 +0x37
github.com/oragono/oragono/irc/caps.(*Set).Has(...)                 
        /home/shivaram/go/src/github.com/oragono/oragono/irc/caps/set.go:63
github.com/oragono/oragono/irc.(*Session).SetMaxlenRest(0x980c2d0)                             
        /home/shivaram/go/src/github.com/oragono/oragono/irc/client.go:137 +0x46  
github.com/oragono/oragono/irc.(*Server).RunClient(0x98b6000, 0x85de3a0, 0x99b0200, 0x9860000)
        /home/shivaram/go/src/github.com/oragono/oragono/irc/client.go:223 +0x4cf                                             
created by github.com/oragono/oragono/irc.(*Server).createListener.func1                        
        /home/shivaram/go/src/github.com/oragono/oragono/irc/server.go:316 +0x10a                                            

sync.atomic guarantees that "the first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned." I misunderstood what "allocated" means; it does not include a [1]uint64 that is a struct field. This article was helpful: https://go101.org/article/memory-layout.html

We got lucky with 1.0.0: the three bitsets we use (client caps, client modes, and channel modes) happened to be 64-bit aligned.

Anyway, this should be an easy fix, we just have to use []uint32 in place of []uint64 for the bitsets. I'll do a round of benchmarking to see if there's any impact on performance on amd64.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions