ln.Close()
}
+func TestUnixAbstractLongNameNulStart(t *testing.T) {
+ // Create an abstract socket name that starts with a null byte ("\x00")
+ // whose length is the maximum of RawSockaddrUnix Path len
+ paddedAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path))
+ copy(paddedAddr, "\x00abstract_test")
+
+ la, err := ResolveUnixAddr("unix", string(paddedAddr))
+ if err != nil {
+ t.Fatal(err)
+ }
+ c, err := ListenUnix("unix", la)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.Close()
+}
+
func TestUnixgramLinuxAbstractLongName(t *testing.T) {
if !testableNetwork("unixgram") {
t.Skip("abstract unix socket long name test")
"internal/syscall/windows"
"os"
"reflect"
+ "syscall"
"testing"
)
}
}
+func TestUnixAbstractLongNameNulStart(t *testing.T) {
+ if !windows.SupportUnixSocket() {
+ t.Skip("unix test")
+ }
+
+ // Create an abstract socket name that starts with a null byte ("\x00")
+ // whose length is the maximum of RawSockaddrUnix Path len
+ paddedAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path))
+ copy(paddedAddr, "\x00abstract_test")
+
+ la, err := ResolveUnixAddr("unix", string(paddedAddr))
+ if err != nil {
+ t.Fatal(err)
+ }
+ c, err := ListenUnix("unix", la)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.Close()
+}
+
func TestModeSocket(t *testing.T) {
if !windows.SupportUnixSocket() {
t.Skip("unix test")
if n > len(sa.raw.Path) {
return nil, 0, EINVAL
}
- if n == len(sa.raw.Path) && name[0] != '@' {
+ // Abstract addresses start with NUL.
+ // '@' is also a valid way to specify abstract addresses.
+ isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00')
+
+ // Non-abstract named addresses are NUL terminated.
+ // The length can't use the full capacity as we need to add NUL.
+ if n == len(sa.raw.Path) && !isAbstract {
return nil, 0, EINVAL
}
sa.raw.Family = AF_UNIX
for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i])
}
- // length is family (uint16), name, NUL.
- sl := _Socklen(2)
- if n > 0 {
- sl += _Socklen(n) + 1
- }
- if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
- // Check sl > 3 so we don't change unnamed socket behavior.
+ // Length is family + name (+ NUL if non-abstract).
+ // Family is of type uint16 (2 bytes).
+ sl := _Socklen(2 + n)
+ if isAbstract {
+ // Abstract addresses are not NUL terminated.
+ // We rewrite '@' prefix to NUL here.
sa.raw.Path[0] = 0
- // Don't count trailing NUL for abstract address.
- sl--
+ } else if n > 0 {
+ // Add NUL for non-abstract named addresses.
+ sl++
}
return unsafe.Pointer(&sa.raw), sl, nil
if n > len(sa.raw.Path) {
return nil, 0, EINVAL
}
- if n == len(sa.raw.Path) && name[0] != '@' {
+ // Abstract addresses start with NUL.
+ // '@' is also a valid way to specify abstract addresses.
+ isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00')
+
+ // Non-abstract named addresses are NUL terminated.
+ // The length can't use the full capacity as we need to add NUL.
+ if n == len(sa.raw.Path) && !isAbstract {
return nil, 0, EINVAL
}
sa.raw.Family = AF_UNIX
for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i])
}
- // length is family (uint16), name, NUL.
- sl := int32(2)
- if n > 0 {
- sl += int32(n) + 1
- }
- if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
- // Check sl > 3 so we don't change unnamed socket behavior.
+ // Length is family + name (+ NUL if non-abstract).
+ // Family is of type uint16 (2 bytes).
+ sl := int32(2 + n)
+ if isAbstract {
+ // Abstract addresses are not NUL terminated.
+ // We rewrite '@' prefix to NUL here.
sa.raw.Path[0] = 0
- // Don't count trailing NUL for abstract address.
- sl--
+ } else if n > 0 {
+ // Add NUL for non-abstract named addresses.
+ sl++
}
return unsafe.Pointer(&sa.raw), sl, nil