From cc1be6b9e0bc7011bb2eb8eaaf91089f6fe2a5ed Mon Sep 17 00:00:00 2001 From: Christian Svensson Date: Mon, 17 Aug 2020 15:34:28 +0000 Subject: [PATCH] unix: allow non-padded SockaddrIUCV This was the intention from the start, but due to a logic error in the handling of slices the implementation only handled minimum 8 character strings. This commit also improves the tests. Change-Id: I6b0ed00bbd8a2faf90ca4a3ebe6218d3c5d6e8bf GitHub-Last-Rev: 5b6dbc068212695d787788f1e8f71852a7cd407b GitHub-Pull-Request: golang/sys#77 Reviewed-on: https://go-review.googlesource.com/c/sys/+/248778 Reviewed-by: Matt Layher Run-TryBot: Matt Layher TryBot-Result: Gobot Gobot --- unix/syscall_internal_linux_test.go | 70 +++++++++++++++++++++++++++++ unix/syscall_linux.go | 7 ++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/unix/syscall_internal_linux_test.go b/unix/syscall_internal_linux_test.go index a690b991..7156c3dc 100644 --- a/unix/syscall_internal_linux_test.go +++ b/unix/syscall_internal_linux_test.go @@ -474,6 +474,76 @@ func TestSockaddrUnix_sockaddr(t *testing.T) { } } +func TestSockaddrIUCV_sockaddr(t *testing.T) { + tests := []struct { + name string + sa *SockaddrIUCV + raw *RawSockaddrIUCV + err error + }{ + { + name: "no fields set", + sa: &SockaddrIUCV{}, + raw: &RawSockaddrIUCV{ + Family: AF_IUCV, + Nodeid: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, + User_id: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, + Name: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, + }, + }, + { + name: "both fields set", + sa: &SockaddrIUCV{ + UserID: "USERID", + Name: "NAME", + }, + raw: &RawSockaddrIUCV{ + Family: AF_IUCV, + Nodeid: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, + User_id: [8]int8{'U', 'S', 'E', 'R', 'I', 'D', ' ', ' '}, + Name: [8]int8{'N', 'A', 'M', 'E', ' ', ' ', ' ', ' '}, + }, + }, + { + name: "too long userid", + sa: &SockaddrIUCV{ + UserID: "123456789", + }, + err: EINVAL, + }, + { + name: "too long name", + sa: &SockaddrIUCV{ + Name: "123456789", + }, + err: EINVAL, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + out, l, err := tt.sa.sockaddr() + if err != tt.err { + t.Fatalf("unexpected error: %v, want: %v", err, tt.err) + } + + // Must be 0 on error or a fixed size otherwise. + if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrIUCV) { + t.Fatalf("unexpected Socklen: %d", l) + } + if out == nil { + // No pointer to cast, return early. + return + } + + raw := (*RawSockaddrIUCV)(out) + if !reflect.DeepEqual(raw, tt.raw) { + t.Fatalf("unexpected RawSockaddrIUCV:\n got: %#v\nwant: %#v", raw, tt.raw) + } + }) + } +} + // These helpers explicitly copy the contents of in into out to produce // the correct sockaddr structure, without relying on unsafe casting to // a type of a larger size. diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go index e12f9bab..c48f5dda 100644 --- a/unix/syscall_linux.go +++ b/unix/syscall_linux.go @@ -902,10 +902,13 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.User_id[i] = ' ' sa.raw.Name[i] = ' ' } - for i, b := range []byte(sa.UserID[:8]) { + if len(sa.UserID) > 8 || len(sa.Name) > 8 { + return nil, 0, EINVAL + } + for i, b := range []byte(sa.UserID[:]) { sa.raw.User_id[i] = int8(b) } - for i, b := range []byte(sa.Name[:8]) { + for i, b := range []byte(sa.Name[:]) { sa.raw.Name[i] = int8(b) } return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil