Skip to content

Commit 66c29ca

Browse files
authored
internal/sdk: Fix SDK's UUID utility to handle partial read (#536)
Fixes the SDK's UUID utility to correctly handle partial reads from its crypto rand source. This error was sometimes causing the SDK's InvocationID value to fail to be obtained, due to a partial read from crypto.Rand. Fix #534
1 parent 1b3b54b commit 66c29ca

File tree

3 files changed

+78
-15
lines changed

3 files changed

+78
-15
lines changed

CHANGELOG_PENDING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ SDK Enhancements
3636

3737
SDK Bugs
3838
---
39+
* `internal/sdk`: Fix SDK's UUID utility to handle partial read ([#536](https://github.com/aws/aws-sdk-go-v2/pull/536))
40+
* Fixes the SDK's UUID utility to correctly handle partial reads from its crypto rand source. This error was sometimes causing the SDK's InvocationID value to fail to be obtained, due to a partial read from crypto.Rand.
41+
* Fix [#534](https://github.com/aws/aws-sdk-go-v2/issues/534)

internal/sdk/uuid.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ import (
99
// UUIDVersion4 returns a Version 4 random UUID from the byte slice provided
1010
func UUIDVersion4() (string, error) {
1111
b := make([]byte, 16)
12-
if n, err := rand.Reader.Read(b); err != nil {
13-
return "", fmt.Errorf("unable to get random bytes for UUID, %w", err)
14-
} else if n != len(b) {
15-
return "", fmt.Errorf("unable to get 16 bytes for UUID, got %d", n)
12+
13+
var offset int
14+
for offset < len(b) {
15+
n, err := rand.Reader.Read(b[offset:])
16+
if err != nil {
17+
return "", fmt.Errorf("unable to get random bytes for UUID, %w", err)
18+
}
19+
offset += n
1620
}
1721

1822
return uuidVersion4(b), nil

internal/sdk/uuid_test.go

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,75 @@
11
package sdk
22

3-
import "testing"
3+
import (
4+
"io"
5+
"strings"
6+
"testing"
7+
"testing/iotest"
48

5-
func TestUUIDVersion4(t *testing.T) {
6-
uuid := uuidVersion4(make([]byte, 16))
7-
if e, a := `00000000-0000-4000-8000-000000000000`, uuid; e != a {
8-
t.Errorf("expect %v uuid, got %v", e, a)
9+
"github.com/aws/aws-sdk-go-v2/internal/rand"
10+
)
11+
12+
type byteReader byte
13+
14+
func (b byteReader) Read(p []byte) (n int, err error) {
15+
for i := 0; i < len(p); i++ {
16+
p[i] = byte(b)
917
}
18+
return len(p), nil
19+
}
20+
21+
type errorReader struct{ err error }
22+
23+
func (e errorReader) Read(p []byte) (n int, err error) {
24+
return 0, e.err
25+
}
26+
27+
func TestUUIDVersion4(t *testing.T) {
28+
origReader := rand.Reader
29+
defer func() { rand.Reader = origReader }()
1030

11-
b := make([]byte, 16)
12-
for i := 0; i < len(b); i++ {
13-
b[i] = 1
31+
cases := map[string]struct {
32+
Expect string
33+
Reader io.Reader
34+
Err string
35+
}{
36+
"0x00": {
37+
Expect: `00000000-0000-4000-8000-000000000000`,
38+
Reader: byteReader(0),
39+
},
40+
"0x01": {
41+
Expect: `01010101-0101-4101-8101-010101010101`,
42+
Reader: byteReader(1),
43+
},
44+
"partial": {
45+
Expect: `01010101-0101-4101-8101-010101010101`,
46+
Reader: iotest.HalfReader(byteReader(1)),
47+
},
48+
"error": {
49+
Reader: errorReader{err: io.ErrUnexpectedEOF},
50+
Err: io.ErrUnexpectedEOF.Error(),
51+
},
1452
}
15-
uuid = uuidVersion4(b)
16-
if e, a := `01010101-0101-4101-8101-010101010101`, uuid; e != a {
17-
t.Errorf("expect %v uuid, got %v", e, a)
53+
54+
for name, c := range cases {
55+
t.Run(name, func(t *testing.T) {
56+
rand.Reader = c.Reader
57+
58+
uuid, err := UUIDVersion4()
59+
if len(c.Err) != 0 {
60+
if err == nil {
61+
t.Fatalf("expect error, got none")
62+
}
63+
if e, a := c.Err, err.Error(); !strings.Contains(a, e) {
64+
t.Fatalf("expect %q in error, %q", e, a)
65+
}
66+
} else if err != nil {
67+
t.Fatalf("expect no error, got %v", err)
68+
}
69+
70+
if e, a := c.Expect, uuid; e != a {
71+
t.Errorf("expect %v uuid, got %v", e, a)
72+
}
73+
})
1874
}
1975
}

0 commit comments

Comments
 (0)