Blame


1 c74282f8 2016-11-16 noreply package p9p
2 c74282f8 2016-11-16 noreply
3 c74282f8 2016-11-16 noreply import (
4 c74282f8 2016-11-16 noreply "bytes"
5 c74282f8 2016-11-16 noreply "context"
6 c74282f8 2016-11-16 noreply "encoding/binary"
7 c74282f8 2016-11-16 noreply "net"
8 c74282f8 2016-11-16 noreply "testing"
9 c74282f8 2016-11-16 noreply "time"
10 c74282f8 2016-11-16 noreply )
11 c74282f8 2016-11-16 noreply
12 c74282f8 2016-11-16 noreply // TestTwriteOverflow ensures that a Twrite message will have the data field
13 c74282f8 2016-11-16 noreply // truncated if the msize would be exceeded.
14 c74282f8 2016-11-16 noreply func TestTwriteOverflow(t *testing.T) {
15 c74282f8 2016-11-16 noreply const (
16 c74282f8 2016-11-16 noreply msize = 512
17 c74282f8 2016-11-16 noreply
18 c74282f8 2016-11-16 noreply // size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] | count = 0
19 c74282f8 2016-11-16 noreply overhead = 4 + 1 + 2 + 4 + 8 + 4
20 c74282f8 2016-11-16 noreply )
21 c74282f8 2016-11-16 noreply
22 c74282f8 2016-11-16 noreply var (
23 c74282f8 2016-11-16 noreply ctx = context.Background()
24 c74282f8 2016-11-16 noreply conn = &mockConn{}
25 c74282f8 2016-11-16 noreply ch = NewChannel(conn, msize)
26 c74282f8 2016-11-16 noreply )
27 c74282f8 2016-11-16 noreply
28 c74282f8 2016-11-16 noreply for _, testcase := range []struct {
29 c74282f8 2016-11-16 noreply name string
30 c74282f8 2016-11-16 noreply overflow int // amount to overflow the message by.
31 c74282f8 2016-11-16 noreply }{
32 c74282f8 2016-11-16 noreply {
33 c74282f8 2016-11-16 noreply name: "BoundedOverflow",
34 c74282f8 2016-11-16 noreply overflow: msize / 2,
35 c74282f8 2016-11-16 noreply },
36 c74282f8 2016-11-16 noreply {
37 c74282f8 2016-11-16 noreply name: "LargeOverflow",
38 c74282f8 2016-11-16 noreply overflow: msize * 3,
39 c74282f8 2016-11-16 noreply },
40 c74282f8 2016-11-16 noreply {
41 c74282f8 2016-11-16 noreply name: "HeaderOverflow",
42 c74282f8 2016-11-16 noreply overflow: overhead,
43 c74282f8 2016-11-16 noreply },
44 c74282f8 2016-11-16 noreply {
45 c74282f8 2016-11-16 noreply name: "HeaderOffsetOverflow",
46 c74282f8 2016-11-16 noreply overflow: overhead - 1,
47 c74282f8 2016-11-16 noreply },
48 c74282f8 2016-11-16 noreply {
49 c74282f8 2016-11-16 noreply name: "OverflowByOne",
50 c74282f8 2016-11-16 noreply overflow: 1,
51 c74282f8 2016-11-16 noreply },
52 c74282f8 2016-11-16 noreply } {
53 c74282f8 2016-11-16 noreply
54 c74282f8 2016-11-16 noreply t.Run(testcase.name, func(t *testing.T) {
55 c74282f8 2016-11-16 noreply var (
56 c74282f8 2016-11-16 noreply fcall = overflowMessage(ch.(*channel).codec, msize, testcase.overflow)
57 c74282f8 2016-11-16 noreply data = fcall.Message.(MessageTwrite).Data
58 c74282f8 2016-11-16 noreply size uint32
59 c74282f8 2016-11-16 noreply )
60 c74282f8 2016-11-16 noreply
61 c74282f8 2016-11-16 noreply t.Logf("overflow: %v, len(data): %v, expected overflow: %v", testcase.overflow, len(data), overhead+len(data)-msize)
62 c74282f8 2016-11-16 noreply conn.buf.Reset()
63 c74282f8 2016-11-16 noreply if err := ch.WriteFcall(ctx, fcall); err != nil {
64 c74282f8 2016-11-16 noreply t.Fatal(err)
65 c74282f8 2016-11-16 noreply }
66 c74282f8 2016-11-16 noreply
67 c74282f8 2016-11-16 noreply if err := binary.Read(bytes.NewReader(conn.buf.Bytes()), binary.LittleEndian, &size); err != nil {
68 c74282f8 2016-11-16 noreply t.Fatal(err)
69 c74282f8 2016-11-16 noreply }
70 c74282f8 2016-11-16 noreply
71 c74282f8 2016-11-16 noreply if size != msize {
72 c74282f8 2016-11-16 noreply t.Fatalf("should have truncated size header: %d != %d", size, msize)
73 c74282f8 2016-11-16 noreply }
74 c74282f8 2016-11-16 noreply
75 c74282f8 2016-11-16 noreply if conn.buf.Len() != msize {
76 c74282f8 2016-11-16 noreply t.Fatalf("should have truncated message: conn.buf.Len(%v) != msize(%v)", conn.buf.Len(), msize)
77 c74282f8 2016-11-16 noreply }
78 c74282f8 2016-11-16 noreply })
79 c74282f8 2016-11-16 noreply }
80 c74282f8 2016-11-16 noreply
81 c74282f8 2016-11-16 noreply }
82 c74282f8 2016-11-16 noreply
83 c74282f8 2016-11-16 noreply // TestWriteOverflowError ensures that we return an error in cases when there
84 c74282f8 2016-11-16 noreply // will certainly be an overflow and it cannot be resolved.
85 c74282f8 2016-11-16 noreply func TestWriteOverflowError(t *testing.T) {
86 c74282f8 2016-11-16 noreply const (
87 c74282f8 2016-11-16 noreply msize = 4
88 c74282f8 2016-11-16 noreply overflowMSize = msize + 1
89 c74282f8 2016-11-16 noreply )
90 c74282f8 2016-11-16 noreply
91 c74282f8 2016-11-16 noreply var (
92 c74282f8 2016-11-16 noreply ctx = context.Background()
93 c74282f8 2016-11-16 noreply conn = &mockConn{}
94 c74282f8 2016-11-16 noreply ch = NewChannel(conn, msize)
95 c74282f8 2016-11-16 noreply data = bytes.Repeat([]byte{'A'}, 4)
96 c74282f8 2016-11-16 noreply fcall = newFcall(1, MessageTwrite{
97 c74282f8 2016-11-16 noreply Data: data,
98 c74282f8 2016-11-16 noreply })
99 c74282f8 2016-11-16 noreply messageSize = 4 + ch.(*channel).codec.Size(fcall)
100 c74282f8 2016-11-16 noreply )
101 c74282f8 2016-11-16 noreply
102 c74282f8 2016-11-16 noreply err := ch.WriteFcall(ctx, fcall)
103 c74282f8 2016-11-16 noreply if err == nil {
104 c74282f8 2016-11-16 noreply t.Fatal("error expected when overflowing message")
105 c74282f8 2016-11-16 noreply }
106 c74282f8 2016-11-16 noreply
107 c74282f8 2016-11-16 noreply if Overflow(err) != messageSize-msize {
108 c74282f8 2016-11-16 noreply t.Fatalf("overflow should reflect messageSize and msize, %d != %d", Overflow(err), messageSize-msize)
109 c74282f8 2016-11-16 noreply }
110 c74282f8 2016-11-16 noreply }
111 c74282f8 2016-11-16 noreply
112 c74282f8 2016-11-16 noreply // TestReadOverflow ensures that messages coming over a network connection do
113 c74282f8 2016-11-16 noreply // not overflow the msize. Invalid messages will cause `ReadFcall` to return an
114 c74282f8 2016-11-16 noreply // Overflow error.
115 c74282f8 2016-11-16 noreply func TestReadFcallOverflow(t *testing.T) {
116 c74282f8 2016-11-16 noreply const (
117 c74282f8 2016-11-16 noreply msize = 256
118 c74282f8 2016-11-16 noreply )
119 c74282f8 2016-11-16 noreply
120 c74282f8 2016-11-16 noreply var (
121 c74282f8 2016-11-16 noreply ctx = context.Background()
122 c74282f8 2016-11-16 noreply conn = &mockConn{}
123 c74282f8 2016-11-16 noreply ch = NewChannel(conn, msize)
124 c74282f8 2016-11-16 noreply codec = ch.(*channel).codec
125 c74282f8 2016-11-16 noreply )
126 c74282f8 2016-11-16 noreply
127 c74282f8 2016-11-16 noreply for _, testcase := range []struct {
128 c74282f8 2016-11-16 noreply name string
129 c74282f8 2016-11-16 noreply overflow int
130 c74282f8 2016-11-16 noreply }{
131 c74282f8 2016-11-16 noreply {
132 c74282f8 2016-11-16 noreply name: "OverflowByOne",
133 c74282f8 2016-11-16 noreply overflow: 1,
134 c74282f8 2016-11-16 noreply },
135 c74282f8 2016-11-16 noreply {
136 c74282f8 2016-11-16 noreply name: "HeaderOverflow",
137 c74282f8 2016-11-16 noreply overflow: overheadMessage(codec, MessageTwrite{}),
138 c74282f8 2016-11-16 noreply },
139 c74282f8 2016-11-16 noreply {
140 c74282f8 2016-11-16 noreply name: "HeaderOffsetOverflow",
141 c74282f8 2016-11-16 noreply overflow: overheadMessage(codec, MessageTwrite{}) - 1,
142 c74282f8 2016-11-16 noreply },
143 c74282f8 2016-11-16 noreply } {
144 c74282f8 2016-11-16 noreply t.Run(testcase.name, func(t *testing.T) {
145 c74282f8 2016-11-16 noreply fcall := overflowMessage(codec, msize, testcase.overflow)
146 c74282f8 2016-11-16 noreply
147 c74282f8 2016-11-16 noreply // prepare the raw message
148 c74282f8 2016-11-16 noreply p, err := ch.(*channel).codec.Marshal(fcall)
149 c74282f8 2016-11-16 noreply if err != nil {
150 c74282f8 2016-11-16 noreply t.Fatal(err)
151 c74282f8 2016-11-16 noreply }
152 c74282f8 2016-11-16 noreply
153 c74282f8 2016-11-16 noreply // "send" the message into the buffer
154 c74282f8 2016-11-16 noreply // this message is crafted to overflow the read buffer.
155 c74282f8 2016-11-16 noreply if err := sendmsg(&conn.buf, p); err != nil {
156 c74282f8 2016-11-16 noreply t.Fatal(err)
157 c74282f8 2016-11-16 noreply }
158 c74282f8 2016-11-16 noreply
159 c74282f8 2016-11-16 noreply var incoming Fcall
160 c74282f8 2016-11-16 noreply err = ch.ReadFcall(ctx, &incoming)
161 c74282f8 2016-11-16 noreply if err == nil {
162 c74282f8 2016-11-16 noreply t.Fatal("expected error on fcall")
163 c74282f8 2016-11-16 noreply }
164 c74282f8 2016-11-16 noreply
165 c74282f8 2016-11-16 noreply // sanity check to ensure our test code has the right overflow
166 c74282f8 2016-11-16 noreply if testcase.overflow != ch.(*channel).msgmsize(fcall)-msize {
167 c74282f8 2016-11-16 noreply t.Fatalf("overflow calculation incorrect: %v != %v", testcase.overflow, ch.(*channel).msgmsize(fcall)-msize)
168 c74282f8 2016-11-16 noreply }
169 c74282f8 2016-11-16 noreply
170 c74282f8 2016-11-16 noreply if Overflow(err) != testcase.overflow {
171 c74282f8 2016-11-16 noreply t.Fatalf("unexpected overflow on error: %v !=%v", Overflow(err), testcase.overflow)
172 c74282f8 2016-11-16 noreply }
173 c74282f8 2016-11-16 noreply })
174 c74282f8 2016-11-16 noreply }
175 c74282f8 2016-11-16 noreply }
176 c74282f8 2016-11-16 noreply
177 c74282f8 2016-11-16 noreply // TestTreadRewrite ensures that messages that whose response would overflow
178 c74282f8 2016-11-16 noreply // the msize will have be adjusted before sending.
179 c74282f8 2016-11-16 noreply func TestTreadRewrite(t *testing.T) {
180 c74282f8 2016-11-16 noreply const (
181 c74282f8 2016-11-16 noreply msize = 256
182 c74282f8 2016-11-16 noreply overflowMSize = msize + 1
183 c74282f8 2016-11-16 noreply )
184 c74282f8 2016-11-16 noreply
185 c74282f8 2016-11-16 noreply var (
186 c74282f8 2016-11-16 noreply ctx = context.Background()
187 c74282f8 2016-11-16 noreply conn = &mockConn{}
188 c74282f8 2016-11-16 noreply ch = NewChannel(conn, msize)
189 c74282f8 2016-11-16 noreply buf = make([]byte, overflowMSize)
190 c74282f8 2016-11-16 noreply // data = bytes.Repeat([]byte{'A'}, overflowMSize)
191 c74282f8 2016-11-16 noreply fcall = newFcall(1, MessageTread{
192 c74282f8 2016-11-16 noreply Count: overflowMSize,
193 c74282f8 2016-11-16 noreply })
194 c74282f8 2016-11-16 noreply responseMSize = ch.(*channel).msgmsize(newFcall(1, MessageRread{
195 c74282f8 2016-11-16 noreply Data: buf,
196 c74282f8 2016-11-16 noreply }))
197 c74282f8 2016-11-16 noreply )
198 c74282f8 2016-11-16 noreply
199 c74282f8 2016-11-16 noreply if err := ch.WriteFcall(ctx, fcall); err != nil {
200 c74282f8 2016-11-16 noreply t.Fatal(err)
201 c74282f8 2016-11-16 noreply }
202 c74282f8 2016-11-16 noreply
203 c74282f8 2016-11-16 noreply // just read the message off the buffer
204 c74282f8 2016-11-16 noreply n, err := readmsg(&conn.buf, buf)
205 c74282f8 2016-11-16 noreply if err != nil {
206 c74282f8 2016-11-16 noreply t.Fatal(err)
207 c74282f8 2016-11-16 noreply }
208 c74282f8 2016-11-16 noreply
209 c74282f8 2016-11-16 noreply *fcall = Fcall{}
210 c74282f8 2016-11-16 noreply if err := ch.(*channel).codec.Unmarshal(buf[:n], fcall); err != nil {
211 c74282f8 2016-11-16 noreply t.Fatal(err)
212 c74282f8 2016-11-16 noreply }
213 c74282f8 2016-11-16 noreply
214 c74282f8 2016-11-16 noreply tread, ok := fcall.Message.(MessageTread)
215 c74282f8 2016-11-16 noreply if !ok {
216 c74282f8 2016-11-16 noreply t.Fatalf("unexpected message: %v", fcall)
217 c74282f8 2016-11-16 noreply }
218 c74282f8 2016-11-16 noreply
219 c74282f8 2016-11-16 noreply if tread.Count != overflowMSize-(uint32(responseMSize)-msize) {
220 c74282f8 2016-11-16 noreply t.Fatalf("count not rewritten: %v != %v", tread.Count, overflowMSize-(uint32(responseMSize)-msize))
221 c74282f8 2016-11-16 noreply }
222 c74282f8 2016-11-16 noreply }
223 c74282f8 2016-11-16 noreply
224 c74282f8 2016-11-16 noreply type mockConn struct {
225 c74282f8 2016-11-16 noreply net.Conn
226 c74282f8 2016-11-16 noreply buf bytes.Buffer
227 c74282f8 2016-11-16 noreply }
228 c74282f8 2016-11-16 noreply
229 c74282f8 2016-11-16 noreply func (m mockConn) SetWriteDeadline(t time.Time) error { return nil }
230 c74282f8 2016-11-16 noreply func (m mockConn) SetReadDeadline(t time.Time) error { return nil }
231 c74282f8 2016-11-16 noreply
232 c74282f8 2016-11-16 noreply func (m *mockConn) Write(p []byte) (int, error) {
233 c74282f8 2016-11-16 noreply return m.buf.Write(p)
234 c74282f8 2016-11-16 noreply }
235 c74282f8 2016-11-16 noreply
236 c74282f8 2016-11-16 noreply func (m *mockConn) Read(p []byte) (int, error) {
237 c74282f8 2016-11-16 noreply return m.buf.Read(p)
238 c74282f8 2016-11-16 noreply }
239 c74282f8 2016-11-16 noreply
240 c74282f8 2016-11-16 noreply func overheadMessage(codec Codec, msg Message) int {
241 c74282f8 2016-11-16 noreply return 4 + codec.Size(newFcall(1, msg))
242 c74282f8 2016-11-16 noreply }
243 c74282f8 2016-11-16 noreply
244 c74282f8 2016-11-16 noreply // overflowMessage returns message that overflows the msize by overflow bytes,
245 c74282f8 2016-11-16 noreply // returning the message size and the fcall.
246 c74282f8 2016-11-16 noreply func overflowMessage(codec Codec, msize, overflow int) *Fcall {
247 c74282f8 2016-11-16 noreply var (
248 c74282f8 2016-11-16 noreply overhead = overheadMessage(codec, MessageTwrite{})
249 c74282f8 2016-11-16 noreply data = bytes.Repeat([]byte{'A'}, (msize-overhead)+overflow)
250 c74282f8 2016-11-16 noreply fcall = newFcall(1, MessageTwrite{
251 c74282f8 2016-11-16 noreply Data: data,
252 c74282f8 2016-11-16 noreply })
253 c74282f8 2016-11-16 noreply )
254 c74282f8 2016-11-16 noreply
255 c74282f8 2016-11-16 noreply return fcall
256 c74282f8 2016-11-16 noreply }