get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/parser_test.go (about) 1 // Copyright 2012-2024 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "bytes" 18 "testing" 19 ) 20 21 func dummyClient() *client { 22 return &client{srv: New(&defaultServerOptions), msubs: -1, mpay: -1, mcl: MAX_CONTROL_LINE_SIZE} 23 } 24 25 func dummyRouteClient() *client { 26 return &client{srv: New(&defaultServerOptions), kind: ROUTER} 27 } 28 29 func TestParsePing(t *testing.T) { 30 c := dummyClient() 31 if c.state != OP_START { 32 t.Fatalf("Expected OP_START vs %d\n", c.state) 33 } 34 ping := []byte("PING\r\n") 35 err := c.parse(ping[:1]) 36 if err != nil || c.state != OP_P { 37 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 38 } 39 err = c.parse(ping[1:2]) 40 if err != nil || c.state != OP_PI { 41 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 42 } 43 err = c.parse(ping[2:3]) 44 if err != nil || c.state != OP_PIN { 45 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 46 } 47 err = c.parse(ping[3:4]) 48 if err != nil || c.state != OP_PING { 49 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 50 } 51 err = c.parse(ping[4:5]) 52 if err != nil || c.state != OP_PING { 53 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 54 } 55 err = c.parse(ping[5:6]) 56 if err != nil || c.state != OP_START { 57 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 58 } 59 err = c.parse(ping) 60 if err != nil || c.state != OP_START { 61 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 62 } 63 // Should tolerate spaces 64 ping = []byte("PING \r") 65 err = c.parse(ping) 66 if err != nil || c.state != OP_PING { 67 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 68 } 69 c.state = OP_START 70 ping = []byte("PING \r \n") 71 err = c.parse(ping) 72 if err != nil || c.state != OP_START { 73 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 74 } 75 } 76 77 func TestParsePong(t *testing.T) { 78 c := dummyClient() 79 if c.state != OP_START { 80 t.Fatalf("Expected OP_START vs %d\n", c.state) 81 } 82 pong := []byte("PONG\r\n") 83 err := c.parse(pong[:1]) 84 if err != nil || c.state != OP_P { 85 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 86 } 87 err = c.parse(pong[1:2]) 88 if err != nil || c.state != OP_PO { 89 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 90 } 91 err = c.parse(pong[2:3]) 92 if err != nil || c.state != OP_PON { 93 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 94 } 95 err = c.parse(pong[3:4]) 96 if err != nil || c.state != OP_PONG { 97 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 98 } 99 err = c.parse(pong[4:5]) 100 if err != nil || c.state != OP_PONG { 101 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 102 } 103 err = c.parse(pong[5:6]) 104 if err != nil || c.state != OP_START { 105 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 106 } 107 if c.ping.out != 0 { 108 t.Fatalf("Unexpected ping.out value: %d vs 0\n", c.ping.out) 109 } 110 err = c.parse(pong) 111 if err != nil || c.state != OP_START { 112 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 113 } 114 if c.ping.out != 0 { 115 t.Fatalf("Unexpected ping.out value: %d vs 0\n", c.ping.out) 116 } 117 // Should tolerate spaces 118 pong = []byte("PONG \r") 119 err = c.parse(pong) 120 if err != nil || c.state != OP_PONG { 121 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 122 } 123 c.state = OP_START 124 pong = []byte("PONG \r \n") 125 err = c.parse(pong) 126 if err != nil || c.state != OP_START { 127 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 128 } 129 if c.ping.out != 0 { 130 t.Fatalf("Unexpected ping.out value: %d vs 0\n", c.ping.out) 131 } 132 133 // Should be adjusting c.pout (Pings Outstanding): reset to 0 134 c.state = OP_START 135 c.ping.out = 10 136 pong = []byte("PONG\r\n") 137 err = c.parse(pong) 138 if err != nil || c.state != OP_START { 139 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 140 } 141 if c.ping.out != 0 { 142 t.Fatalf("Unexpected ping.out: %d vs 0\n", c.ping.out) 143 } 144 } 145 146 func TestParseConnect(t *testing.T) { 147 c := dummyClient() 148 connect := []byte("CONNECT {\"verbose\":false,\"pedantic\":true,\"tls_required\":false}\r\n") 149 err := c.parse(connect) 150 if err != nil || c.state != OP_START { 151 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 152 } 153 // Check saved state 154 if c.as != 8 { 155 t.Fatalf("ArgStart state incorrect: 8 vs %d\n", c.as) 156 } 157 } 158 159 func TestParseSub(t *testing.T) { 160 c := dummyClient() 161 sub := []byte("SUB foo 1\r") 162 err := c.parse(sub) 163 if err != nil || c.state != SUB_ARG { 164 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 165 } 166 // Check saved state 167 if c.as != 4 { 168 t.Fatalf("ArgStart state incorrect: 4 vs %d\n", c.as) 169 } 170 if c.drop != 1 { 171 t.Fatalf("Drop state incorrect: 1 vs %d\n", c.as) 172 } 173 if !bytes.Equal(sub[c.as:], []byte("foo 1\r")) { 174 t.Fatalf("Arg state incorrect: %s\n", sub[c.as:]) 175 } 176 } 177 178 func TestParsePub(t *testing.T) { 179 c := dummyClient() 180 181 pub := []byte("PUB foo 5\r\nhello\r") 182 err := c.parse(pub) 183 if err != nil || c.state != MSG_END_N { 184 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 185 } 186 if !bytes.Equal(c.pa.subject, []byte("foo")) { 187 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", string(c.pa.subject)) 188 } 189 if c.pa.reply != nil { 190 t.Fatalf("Did not parse reply correctly: 'nil' vs '%s'\n", string(c.pa.reply)) 191 } 192 if c.pa.size != 5 { 193 t.Fatalf("Did not parse msg size correctly: 5 vs %d\n", c.pa.size) 194 } 195 196 // Clear snapshots 197 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 198 199 pub = []byte("PUB foo.bar INBOX.22 11\r\nhello world\r") 200 err = c.parse(pub) 201 if err != nil || c.state != MSG_END_N { 202 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 203 } 204 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 205 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", string(c.pa.subject)) 206 } 207 if !bytes.Equal(c.pa.reply, []byte("INBOX.22")) { 208 t.Fatalf("Did not parse reply correctly: 'INBOX.22' vs '%s'\n", string(c.pa.reply)) 209 } 210 if c.pa.size != 11 { 211 t.Fatalf("Did not parse msg size correctly: 11 vs %d\n", c.pa.size) 212 } 213 214 // Clear snapshots 215 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 216 217 // This is the case when data has more bytes than expected by size. 218 pub = []byte("PUB foo.bar 11\r\nhello world hello world\r") 219 err = c.parse(pub) 220 if err == nil { 221 t.Fatalf("Expected an error parsing longer than expected message body") 222 } 223 if c.msgBuf != nil { 224 t.Fatalf("Did not expect a c.msgBuf to be non-nil") 225 } 226 } 227 228 // https://www.twistlock.com/labs-blog/finding-dos-vulnerability-nats-go-fuzz-cve-2019-13126/ 229 func TestParsePubSizeOverflow(t *testing.T) { 230 c := dummyClient() 231 232 pub := []byte("PUB foo 3333333333333333333333333333333333333333333333333333333333333333\r\n") 233 if err := c.parse(pub); err == nil { 234 t.Fatalf("Expected an error") 235 } 236 } 237 238 func TestParsePubArg(t *testing.T) { 239 c := dummyClient() 240 241 for _, test := range []struct { 242 arg string 243 subject string 244 reply string 245 size int 246 szb string 247 }{ 248 {arg: "a 2", subject: "a", reply: "", size: 2, szb: "2"}, 249 {arg: "a 222", subject: "a", reply: "", size: 222, szb: "222"}, 250 {arg: "foo 22", subject: "foo", reply: "", size: 22, szb: "22"}, 251 {arg: " foo 22", subject: "foo", reply: "", size: 22, szb: "22"}, 252 {arg: "foo 22 ", subject: "foo", reply: "", size: 22, szb: "22"}, 253 {arg: "foo 22", subject: "foo", reply: "", size: 22, szb: "22"}, 254 {arg: " foo 22 ", subject: "foo", reply: "", size: 22, szb: "22"}, 255 {arg: " foo 22 ", subject: "foo", reply: "", size: 22, szb: "22"}, 256 {arg: "foo bar 22", subject: "foo", reply: "bar", size: 22, szb: "22"}, 257 {arg: " foo bar 22", subject: "foo", reply: "bar", size: 22, szb: "22"}, 258 {arg: "foo bar 22 ", subject: "foo", reply: "bar", size: 22, szb: "22"}, 259 {arg: "foo bar 22", subject: "foo", reply: "bar", size: 22, szb: "22"}, 260 {arg: " foo bar 22 ", subject: "foo", reply: "bar", size: 22, szb: "22"}, 261 {arg: " foo bar 22 ", subject: "foo", reply: "bar", size: 22, szb: "22"}, 262 {arg: " foo bar 2222 ", subject: "foo", reply: "bar", size: 2222, szb: "2222"}, 263 {arg: " foo 2222 ", subject: "foo", reply: "", size: 2222, szb: "2222"}, 264 {arg: "a\t2", subject: "a", reply: "", size: 2, szb: "2"}, 265 {arg: "a\t222", subject: "a", reply: "", size: 222, szb: "222"}, 266 {arg: "foo\t22", subject: "foo", reply: "", size: 22, szb: "22"}, 267 {arg: "\tfoo\t22", subject: "foo", reply: "", size: 22, szb: "22"}, 268 {arg: "foo\t22\t", subject: "foo", reply: "", size: 22, szb: "22"}, 269 {arg: "foo\t\t\t22", subject: "foo", reply: "", size: 22, szb: "22"}, 270 {arg: "\tfoo\t22\t", subject: "foo", reply: "", size: 22, szb: "22"}, 271 {arg: "\tfoo\t\t\t22\t", subject: "foo", reply: "", size: 22, szb: "22"}, 272 {arg: "foo\tbar\t22", subject: "foo", reply: "bar", size: 22, szb: "22"}, 273 {arg: "\tfoo\tbar\t22", subject: "foo", reply: "bar", size: 22, szb: "22"}, 274 {arg: "foo\tbar\t22\t", subject: "foo", reply: "bar", size: 22, szb: "22"}, 275 {arg: "foo\t\tbar\t\t22", subject: "foo", reply: "bar", size: 22, szb: "22"}, 276 {arg: "\tfoo\tbar\t22\t", subject: "foo", reply: "bar", size: 22, szb: "22"}, 277 {arg: "\t \tfoo\t \t \tbar\t \t22\t \t", subject: "foo", reply: "bar", size: 22, szb: "22"}, 278 {arg: "\t\tfoo\t\t\tbar\t\t2222\t\t", subject: "foo", reply: "bar", size: 2222, szb: "2222"}, 279 {arg: "\t \tfoo\t \t \t\t\t2222\t \t", subject: "foo", reply: "", size: 2222, szb: "2222"}, 280 } { 281 t.Run(test.arg, func(t *testing.T) { 282 if err := c.processPub([]byte(test.arg)); err != nil { 283 t.Fatalf("Unexpected parse error: %v\n", err) 284 } 285 if !bytes.Equal(c.pa.subject, []byte(test.subject)) { 286 t.Fatalf("Mismatched subject: '%s'\n", c.pa.subject) 287 } 288 if !bytes.Equal(c.pa.reply, []byte(test.reply)) { 289 t.Fatalf("Mismatched reply subject: '%s'\n", c.pa.reply) 290 } 291 if !bytes.Equal(c.pa.szb, []byte(test.szb)) { 292 t.Fatalf("Bad size buf: '%s'\n", c.pa.szb) 293 } 294 if c.pa.size != test.size { 295 t.Fatalf("Bad size: %d\n", c.pa.size) 296 } 297 }) 298 } 299 } 300 301 func TestParsePubBadSize(t *testing.T) { 302 c := dummyClient() 303 // Setup localized max payload 304 c.mpay = 32768 305 if err := c.processPub([]byte("foo 2222222222222222")); err == nil { 306 t.Fatalf("Expected parse error for size too large") 307 } 308 } 309 310 func TestParseHeaderPub(t *testing.T) { 311 c := dummyClient() 312 c.headers = true 313 314 hpub := []byte("HPUB foo 12 17\r\nname:derek\r\nHELLO\r") 315 if err := c.parse(hpub); err != nil || c.state != MSG_END_N { 316 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 317 } 318 if !bytes.Equal(c.pa.subject, []byte("foo")) { 319 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'", c.pa.subject) 320 } 321 if c.pa.reply != nil { 322 t.Fatalf("Did not parse reply correctly: 'nil' vs '%s'", c.pa.reply) 323 } 324 if c.pa.hdr != 12 { 325 t.Fatalf("Did not parse msg header size correctly: 12 vs %d", c.pa.hdr) 326 } 327 if !bytes.Equal(c.pa.hdb, []byte("12")) { 328 t.Fatalf("Did not parse or capture the header size as bytes correctly: %q", c.pa.hdb) 329 } 330 if c.pa.size != 17 { 331 t.Fatalf("Did not parse msg size correctly: 17 vs %d", c.pa.size) 332 } 333 334 // Clear snapshots 335 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 336 337 hpub = []byte("HPUB foo INBOX.22 12 17\r\nname:derek\r\nHELLO\r") 338 if err := c.parse(hpub); err != nil || c.state != MSG_END_N { 339 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 340 } 341 if !bytes.Equal(c.pa.subject, []byte("foo")) { 342 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'", c.pa.subject) 343 } 344 if !bytes.Equal(c.pa.reply, []byte("INBOX.22")) { 345 t.Fatalf("Did not parse reply correctly: 'INBOX.22' vs '%s'", c.pa.reply) 346 } 347 if c.pa.hdr != 12 { 348 t.Fatalf("Did not parse msg header size correctly: 12 vs %d", c.pa.hdr) 349 } 350 if !bytes.Equal(c.pa.hdb, []byte("12")) { 351 t.Fatalf("Did not parse or capture the header size as bytes correctly: %q", c.pa.hdb) 352 } 353 if c.pa.size != 17 { 354 t.Fatalf("Did not parse msg size correctly: 17 vs %d", c.pa.size) 355 } 356 357 // Clear snapshots 358 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 359 360 hpub = []byte("HPUB foo INBOX.22 0 5\r\nHELLO\r") 361 if err := c.parse(hpub); err != nil || c.state != MSG_END_N { 362 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 363 } 364 if !bytes.Equal(c.pa.subject, []byte("foo")) { 365 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 366 } 367 if !bytes.Equal(c.pa.reply, []byte("INBOX.22")) { 368 t.Fatalf("Did not parse reply correctly: 'INBOX.22' vs '%s'\n", c.pa.reply) 369 } 370 if c.pa.hdr != 0 { 371 t.Fatalf("Did not parse msg header size correctly: 0 vs %d\n", c.pa.hdr) 372 } 373 if !bytes.Equal(c.pa.hdb, []byte("0")) { 374 t.Fatalf("Did not parse or capture the header size as bytes correctly: %q", c.pa.hdb) 375 } 376 if c.pa.size != 5 { 377 t.Fatalf("Did not parse msg size correctly: 5 vs %d\n", c.pa.size) 378 } 379 } 380 381 func TestParseHeaderPubArg(t *testing.T) { 382 c := dummyClient() 383 c.headers = true 384 385 for _, test := range []struct { 386 arg string 387 subject string 388 reply string 389 hdr int 390 size int 391 szb string 392 }{ 393 {arg: "a 2 4", subject: "a", reply: "", hdr: 2, size: 4, szb: "4"}, 394 {arg: "a 22 222", subject: "a", reply: "", hdr: 22, size: 222, szb: "222"}, 395 {arg: "foo 3 22", subject: "foo", reply: "", hdr: 3, size: 22, szb: "22"}, 396 {arg: " foo 1 22", subject: "foo", reply: "", hdr: 1, size: 22, szb: "22"}, 397 {arg: "foo 0 22 ", subject: "foo", reply: "", hdr: 0, size: 22, szb: "22"}, 398 {arg: "foo 0 22", subject: "foo", reply: "", hdr: 0, size: 22, szb: "22"}, 399 {arg: " foo 1 22 ", subject: "foo", reply: "", hdr: 1, size: 22, szb: "22"}, 400 {arg: " foo 3 22 ", subject: "foo", reply: "", hdr: 3, size: 22, szb: "22"}, 401 {arg: "foo bar 1 22", subject: "foo", reply: "bar", hdr: 1, size: 22, szb: "22"}, 402 {arg: " foo bar 11 22", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 403 {arg: "foo bar 11 22 ", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 404 {arg: "foo bar 11 22", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 405 {arg: " foo bar 11 22 ", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 406 {arg: " foo bar 11 22 ", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 407 {arg: " foo bar 22 2222 ", subject: "foo", reply: "bar", hdr: 22, size: 2222, szb: "2222"}, 408 {arg: " foo 1 2222 ", subject: "foo", reply: "", hdr: 1, size: 2222, szb: "2222"}, 409 {arg: "a\t2\t22", subject: "a", reply: "", hdr: 2, size: 22, szb: "22"}, 410 {arg: "a\t2\t\t222", subject: "a", reply: "", hdr: 2, size: 222, szb: "222"}, 411 {arg: "foo\t2 22", subject: "foo", reply: "", hdr: 2, size: 22, szb: "22"}, 412 {arg: "\tfoo\t11\t 22", subject: "foo", reply: "", hdr: 11, size: 22, szb: "22"}, 413 {arg: "foo\t11\t22\t", subject: "foo", reply: "", hdr: 11, size: 22, szb: "22"}, 414 {arg: "foo\t\t\t11 22", subject: "foo", reply: "", hdr: 11, size: 22, szb: "22"}, 415 {arg: "\tfoo\t11\t \t 22\t", subject: "foo", reply: "", hdr: 11, size: 22, szb: "22"}, 416 {arg: "\tfoo\t\t\t11 22\t", subject: "foo", reply: "", hdr: 11, size: 22, szb: "22"}, 417 {arg: "foo\tbar\t2 22", subject: "foo", reply: "bar", hdr: 2, size: 22, szb: "22"}, 418 {arg: "\tfoo\tbar\t11\t22", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 419 {arg: "foo\tbar\t11\t\t22\t ", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 420 {arg: "foo\t\tbar\t\t11\t\t\t22", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 421 {arg: "\tfoo\tbar\t11\t22\t", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 422 {arg: "\t \tfoo\t \t \tbar\t \t11\t 22\t \t", subject: "foo", reply: "bar", hdr: 11, size: 22, szb: "22"}, 423 {arg: "\t\tfoo\t\t\tbar\t\t22\t\t\t2222\t\t", subject: "foo", reply: "bar", hdr: 22, size: 2222, szb: "2222"}, 424 {arg: "\t \tfoo\t \t \t\t\t11\t\t 2222\t \t", subject: "foo", reply: "", hdr: 11, size: 2222, szb: "2222"}, 425 } { 426 t.Run(test.arg, func(t *testing.T) { 427 if err := c.processHeaderPub([]byte(test.arg), nil); err != nil { 428 t.Fatalf("Unexpected parse error: %v\n", err) 429 } 430 if !bytes.Equal(c.pa.subject, []byte(test.subject)) { 431 t.Fatalf("Mismatched subject: '%s'\n", c.pa.subject) 432 } 433 if !bytes.Equal(c.pa.reply, []byte(test.reply)) { 434 t.Fatalf("Mismatched reply subject: '%s'\n", c.pa.reply) 435 } 436 if !bytes.Equal(c.pa.szb, []byte(test.szb)) { 437 t.Fatalf("Bad size buf: '%s'\n", c.pa.szb) 438 } 439 if c.pa.hdr != test.hdr { 440 t.Fatalf("Bad header size: %d\n", c.pa.hdr) 441 } 442 if c.pa.size != test.size { 443 t.Fatalf("Bad size: %d\n", c.pa.size) 444 } 445 }) 446 } 447 } 448 449 func TestParseRoutedHeaderMsg(t *testing.T) { 450 c := dummyRouteClient() 451 c.route = &route{} 452 453 pub := []byte("HMSG $foo foo 10 8\r\nXXXhello\r") 454 if err := c.parse(pub); err == nil { 455 t.Fatalf("Expected an error") 456 } 457 458 // Clear snapshots 459 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 460 461 pub = []byte("HMSG $foo foo 3 8\r\nXXXhello\r") 462 err := c.parse(pub) 463 if err != nil || c.state != MSG_END_N { 464 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 465 } 466 if !bytes.Equal(c.pa.account, []byte("$foo")) { 467 t.Fatalf("Did not parse account correctly: '$foo' vs '%s'\n", c.pa.account) 468 } 469 if !bytes.Equal(c.pa.subject, []byte("foo")) { 470 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 471 } 472 if c.pa.reply != nil { 473 t.Fatalf("Did not parse reply correctly: 'nil' vs '%s'\n", c.pa.reply) 474 } 475 if c.pa.hdr != 3 { 476 t.Fatalf("Did not parse header size correctly: 3 vs %d\n", c.pa.hdr) 477 } 478 if c.pa.size != 8 { 479 t.Fatalf("Did not parse msg size correctly: 8 vs %d\n", c.pa.size) 480 } 481 482 // Clear snapshots 483 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 484 485 pub = []byte("HMSG $G foo.bar INBOX.22 3 14\r\nOK:hello world\r") 486 err = c.parse(pub) 487 if err != nil || c.state != MSG_END_N { 488 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 489 } 490 if !bytes.Equal(c.pa.account, []byte("$G")) { 491 t.Fatalf("Did not parse account correctly: '$G' vs '%s'\n", c.pa.account) 492 } 493 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 494 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 495 } 496 if !bytes.Equal(c.pa.reply, []byte("INBOX.22")) { 497 t.Fatalf("Did not parse reply correctly: 'INBOX.22' vs '%s'\n", c.pa.reply) 498 } 499 if c.pa.hdr != 3 { 500 t.Fatalf("Did not parse header size correctly: 3 vs %d\n", c.pa.hdr) 501 } 502 if c.pa.size != 14 { 503 t.Fatalf("Did not parse msg size correctly: 14 vs %d\n", c.pa.size) 504 } 505 506 // Clear snapshots 507 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 508 509 pub = []byte("HMSG $G foo.bar + reply baz 3 14\r\nOK:hello world\r") 510 err = c.parse(pub) 511 if err != nil || c.state != MSG_END_N { 512 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 513 } 514 if !bytes.Equal(c.pa.account, []byte("$G")) { 515 t.Fatalf("Did not parse account correctly: '$G' vs '%s'\n", c.pa.account) 516 } 517 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 518 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 519 } 520 if !bytes.Equal(c.pa.reply, []byte("reply")) { 521 t.Fatalf("Did not parse reply correctly: 'reply' vs '%s'\n", c.pa.reply) 522 } 523 if len(c.pa.queues) != 1 { 524 t.Fatalf("Expected 1 queue, got %d", len(c.pa.queues)) 525 } 526 if !bytes.Equal(c.pa.queues[0], []byte("baz")) { 527 t.Fatalf("Did not parse queues correctly: 'baz' vs '%q'\n", c.pa.queues[0]) 528 } 529 if c.pa.hdr != 3 { 530 t.Fatalf("Did not parse header size correctly: 3 vs %d\n", c.pa.hdr) 531 } 532 if c.pa.size != 14 { 533 t.Fatalf("Did not parse msg size correctly: 14 vs %d\n", c.pa.size) 534 } 535 536 // Clear snapshots 537 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 538 539 pub = []byte("HMSG $G foo.bar | baz 3 14\r\nOK:hello world\r") 540 err = c.parse(pub) 541 if err != nil || c.state != MSG_END_N { 542 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 543 } 544 if !bytes.Equal(c.pa.account, []byte("$G")) { 545 t.Fatalf("Did not parse account correctly: '$G' vs '%s'\n", c.pa.account) 546 } 547 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 548 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 549 } 550 if !bytes.Equal(c.pa.reply, []byte("")) { 551 t.Fatalf("Did not parse reply correctly: '' vs '%s'\n", c.pa.reply) 552 } 553 if len(c.pa.queues) != 1 { 554 t.Fatalf("Expected 1 queue, got %d", len(c.pa.queues)) 555 } 556 if !bytes.Equal(c.pa.queues[0], []byte("baz")) { 557 t.Fatalf("Did not parse queues correctly: 'baz' vs '%q'\n", c.pa.queues[0]) 558 } 559 if c.pa.hdr != 3 { 560 t.Fatalf("Did not parse header size correctly: 3 vs %d\n", c.pa.hdr) 561 } 562 if c.pa.size != 14 { 563 t.Fatalf("Did not parse msg size correctly: 14 vs %d\n", c.pa.size) 564 } 565 } 566 567 func TestParseRouteMsg(t *testing.T) { 568 c := dummyRouteClient() 569 c.route = &route{} 570 571 pub := []byte("MSG $foo foo 5\r\nhello\r") 572 err := c.parse(pub) 573 if err == nil { 574 t.Fatalf("Expected an error, got none") 575 } 576 pub = []byte("RMSG $foo foo 5\r\nhello\r") 577 err = c.parse(pub) 578 if err != nil || c.state != MSG_END_N { 579 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 580 } 581 if !bytes.Equal(c.pa.account, []byte("$foo")) { 582 t.Fatalf("Did not parse account correctly: '$foo' vs '%s'\n", c.pa.account) 583 } 584 if !bytes.Equal(c.pa.subject, []byte("foo")) { 585 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 586 } 587 if c.pa.reply != nil { 588 t.Fatalf("Did not parse reply correctly: 'nil' vs '%s'\n", c.pa.reply) 589 } 590 if c.pa.size != 5 { 591 t.Fatalf("Did not parse msg size correctly: 5 vs %d\n", c.pa.size) 592 } 593 594 // Clear snapshots 595 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 596 597 pub = []byte("RMSG $G foo.bar INBOX.22 11\r\nhello world\r") 598 err = c.parse(pub) 599 if err != nil || c.state != MSG_END_N { 600 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 601 } 602 if !bytes.Equal(c.pa.account, []byte("$G")) { 603 t.Fatalf("Did not parse account correctly: '$G' vs '%s'\n", c.pa.account) 604 } 605 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 606 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 607 } 608 if !bytes.Equal(c.pa.reply, []byte("INBOX.22")) { 609 t.Fatalf("Did not parse reply correctly: 'INBOX.22' vs '%s'\n", c.pa.reply) 610 } 611 if c.pa.size != 11 { 612 t.Fatalf("Did not parse msg size correctly: 11 vs %d\n", c.pa.size) 613 } 614 615 // Clear snapshots 616 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 617 618 pub = []byte("RMSG $G foo.bar + reply baz 11\r\nhello world\r") 619 err = c.parse(pub) 620 if err != nil || c.state != MSG_END_N { 621 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 622 } 623 if !bytes.Equal(c.pa.account, []byte("$G")) { 624 t.Fatalf("Did not parse account correctly: '$G' vs '%s'\n", c.pa.account) 625 } 626 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 627 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 628 } 629 if !bytes.Equal(c.pa.reply, []byte("reply")) { 630 t.Fatalf("Did not parse reply correctly: 'reply' vs '%s'\n", c.pa.reply) 631 } 632 if len(c.pa.queues) != 1 { 633 t.Fatalf("Expected 1 queue, got %d", len(c.pa.queues)) 634 } 635 if !bytes.Equal(c.pa.queues[0], []byte("baz")) { 636 t.Fatalf("Did not parse queues correctly: 'baz' vs '%q'\n", c.pa.queues[0]) 637 } 638 639 // Clear snapshots 640 c.argBuf, c.msgBuf, c.state = nil, nil, OP_START 641 642 pub = []byte("RMSG $G foo.bar | baz 11\r\nhello world\r") 643 err = c.parse(pub) 644 if err != nil || c.state != MSG_END_N { 645 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 646 } 647 if !bytes.Equal(c.pa.account, []byte("$G")) { 648 t.Fatalf("Did not parse account correctly: '$G' vs '%s'\n", c.pa.account) 649 } 650 if !bytes.Equal(c.pa.subject, []byte("foo.bar")) { 651 t.Fatalf("Did not parse subject correctly: 'foo' vs '%s'\n", c.pa.subject) 652 } 653 if !bytes.Equal(c.pa.reply, []byte("")) { 654 t.Fatalf("Did not parse reply correctly: '' vs '%s'\n", c.pa.reply) 655 } 656 if len(c.pa.queues) != 1 { 657 t.Fatalf("Expected 1 queue, got %d", len(c.pa.queues)) 658 } 659 if !bytes.Equal(c.pa.queues[0], []byte("baz")) { 660 t.Fatalf("Did not parse queues correctly: 'baz' vs '%q'\n", c.pa.queues[0]) 661 } 662 } 663 664 func TestParseMsgSpace(t *testing.T) { 665 c := dummyRouteClient() 666 667 // Ivan bug he found 668 if err := c.parse([]byte("MSG \r\n")); err == nil { 669 t.Fatalf("Expected parse error for MSG <SPC>") 670 } 671 672 c = dummyClient() 673 674 // Anything with an M from a client should parse error 675 if err := c.parse([]byte("M")); err == nil { 676 t.Fatalf("Expected parse error for M* from a client") 677 } 678 } 679 680 func TestShouldFail(t *testing.T) { 681 wrongProtos := []string{ 682 "xxx", 683 "Px", "PIx", "PINx", " PING", 684 "POx", "PONx", 685 "+x", "+Ox", 686 "-x", "-Ex", "-ERx", "-ERRx", 687 "Cx", "COx", "CONx", "CONNx", "CONNEx", "CONNECx", "CONNECx", "CONNECT \r\n", 688 "PUx", "PUB foo\r\n", "PUB \r\n", "PUB foo bar \r\n", 689 "PUB foo 2\r\nok \r\n", "PUB foo 2\r\nok\r \n", 690 "Sx", "SUx", "SUB\r\n", "SUB \r\n", "SUB foo\r\n", 691 "SUB foo bar baz 22\r\n", 692 "Ux", "UNx", "UNSx", "UNSUx", "UNSUBx", "UNSUBUNSUB 1\r\n", "UNSUB_2\r\n", 693 "UNSUB_UNSUB_UNSUB 2\r\n", "UNSUB_\t2\r\n", "UNSUB\r\n", "UNSUB \r\n", 694 "UNSUB \t \r\n", 695 "Ix", "INx", "INFx", "INFO \r\n", 696 } 697 for _, proto := range wrongProtos { 698 c := dummyClient() 699 if err := c.parse([]byte(proto)); err == nil { 700 t.Fatalf("Should have received a parse error for: %v", proto) 701 } 702 } 703 704 // Special case for MSG, type needs to not be client. 705 wrongProtos = []string{"Mx", "MSx", "MSGx", "MSG \r\n"} 706 for _, proto := range wrongProtos { 707 c := dummyClient() 708 c.kind = ROUTER 709 if err := c.parse([]byte(proto)); err == nil { 710 t.Fatalf("Should have received a parse error for: %v", proto) 711 } 712 } 713 } 714 715 func TestProtoSnippet(t *testing.T) { 716 sample := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 717 718 tests := []struct { 719 input int 720 expected string 721 }{ 722 {0, `"abcdefghijklmnopqrstuvwxyzABCDEF"`}, 723 {1, `"bcdefghijklmnopqrstuvwxyzABCDEFG"`}, 724 {2, `"cdefghijklmnopqrstuvwxyzABCDEFGH"`}, 725 {3, `"defghijklmnopqrstuvwxyzABCDEFGHI"`}, 726 {4, `"efghijklmnopqrstuvwxyzABCDEFGHIJ"`}, 727 {5, `"fghijklmnopqrstuvwxyzABCDEFGHIJK"`}, 728 {6, `"ghijklmnopqrstuvwxyzABCDEFGHIJKL"`}, 729 {7, `"hijklmnopqrstuvwxyzABCDEFGHIJKLM"`}, 730 {8, `"ijklmnopqrstuvwxyzABCDEFGHIJKLMN"`}, 731 {9, `"jklmnopqrstuvwxyzABCDEFGHIJKLMNO"`}, 732 {10, `"klmnopqrstuvwxyzABCDEFGHIJKLMNOP"`}, 733 {11, `"lmnopqrstuvwxyzABCDEFGHIJKLMNOPQ"`}, 734 {12, `"mnopqrstuvwxyzABCDEFGHIJKLMNOPQR"`}, 735 {13, `"nopqrstuvwxyzABCDEFGHIJKLMNOPQRS"`}, 736 {14, `"opqrstuvwxyzABCDEFGHIJKLMNOPQRST"`}, 737 {15, `"pqrstuvwxyzABCDEFGHIJKLMNOPQRSTU"`}, 738 {16, `"qrstuvwxyzABCDEFGHIJKLMNOPQRSTUV"`}, 739 {17, `"rstuvwxyzABCDEFGHIJKLMNOPQRSTUVW"`}, 740 {18, `"stuvwxyzABCDEFGHIJKLMNOPQRSTUVWX"`}, 741 {19, `"tuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY"`}, 742 {20, `"uvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"`}, 743 {21, `"vwxyzABCDEFGHIJKLMNOPQRSTUVWXY"`}, 744 {22, `"wxyzABCDEFGHIJKLMNOPQRSTUVWXY"`}, 745 {23, `"xyzABCDEFGHIJKLMNOPQRSTUVWXY"`}, 746 {24, `"yzABCDEFGHIJKLMNOPQRSTUVWXY"`}, 747 {25, `"zABCDEFGHIJKLMNOPQRSTUVWXY"`}, 748 {26, `"ABCDEFGHIJKLMNOPQRSTUVWXY"`}, 749 {27, `"BCDEFGHIJKLMNOPQRSTUVWXY"`}, 750 {28, `"CDEFGHIJKLMNOPQRSTUVWXY"`}, 751 {29, `"DEFGHIJKLMNOPQRSTUVWXY"`}, 752 {30, `"EFGHIJKLMNOPQRSTUVWXY"`}, 753 {31, `"FGHIJKLMNOPQRSTUVWXY"`}, 754 {32, `"GHIJKLMNOPQRSTUVWXY"`}, 755 {33, `"HIJKLMNOPQRSTUVWXY"`}, 756 {34, `"IJKLMNOPQRSTUVWXY"`}, 757 {35, `"JKLMNOPQRSTUVWXY"`}, 758 {36, `"KLMNOPQRSTUVWXY"`}, 759 {37, `"LMNOPQRSTUVWXY"`}, 760 {38, `"MNOPQRSTUVWXY"`}, 761 {39, `"NOPQRSTUVWXY"`}, 762 {40, `"OPQRSTUVWXY"`}, 763 {41, `"PQRSTUVWXY"`}, 764 {42, `"QRSTUVWXY"`}, 765 {43, `"RSTUVWXY"`}, 766 {44, `"STUVWXY"`}, 767 {45, `"TUVWXY"`}, 768 {46, `"UVWXY"`}, 769 {47, `"VWXY"`}, 770 {48, `"WXY"`}, 771 {49, `"XY"`}, 772 {50, `"Y"`}, 773 {51, `""`}, 774 {52, `""`}, 775 {53, `""`}, 776 {54, `""`}, 777 } 778 779 for _, tt := range tests { 780 got := protoSnippet(tt.input, PROTO_SNIPPET_SIZE, sample) 781 if tt.expected != got { 782 t.Errorf("Expected protocol snippet to be %s when start=%d but got %s\n", tt.expected, tt.input, got) 783 } 784 } 785 } 786 787 func TestParseOK(t *testing.T) { 788 c := dummyClient() 789 if c.state != OP_START { 790 t.Fatalf("Expected OP_START vs %d\n", c.state) 791 } 792 okProto := []byte("+OK\r\n") 793 err := c.parse(okProto[:1]) 794 if err != nil || c.state != OP_PLUS { 795 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 796 } 797 err = c.parse(okProto[1:2]) 798 if err != nil || c.state != OP_PLUS_O { 799 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 800 } 801 err = c.parse(okProto[2:3]) 802 if err != nil || c.state != OP_PLUS_OK { 803 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 804 } 805 err = c.parse(okProto[3:4]) 806 if err != nil || c.state != OP_PLUS_OK { 807 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 808 } 809 err = c.parse(okProto[4:5]) 810 if err != nil || c.state != OP_START { 811 t.Fatalf("Unexpected: %d : %v\n", c.state, err) 812 } 813 } 814 815 func TestMaxControlLine(t *testing.T) { 816 for _, test := range []struct { 817 name string 818 kind int 819 shouldFail bool 820 }{ 821 {"client", CLIENT, true}, 822 {"leaf", LEAF, false}, 823 {"route", ROUTER, false}, 824 {"gateway", GATEWAY, false}, 825 } { 826 t.Run(test.name, func(t *testing.T) { 827 pub := []byte("PUB foo.bar.baz 2\r\nok\r\n") 828 829 setupClient := func() *client { 830 c := dummyClient() 831 c.setNoReconnect() 832 c.flags.set(connectReceived) 833 c.kind = test.kind 834 switch test.kind { 835 case ROUTER: 836 c.route = &route{} 837 case GATEWAY: 838 c.gw = &gateway{outbound: false, connected: true, insim: make(map[string]*insie)} 839 } 840 c.mcl = 8 841 return c 842 } 843 844 c := setupClient() 845 // First try with a partial: 846 // PUB foo.bar.baz 2\r\nok\r\n 847 // .............^ 848 err := c.parse(pub[:14]) 849 switch test.shouldFail { 850 case true: 851 if !ErrorIs(err, ErrMaxControlLine) { 852 t.Fatalf("Expected an error parsing longer than expected control line") 853 } 854 case false: 855 if err != nil { 856 t.Fatalf("Should not have failed, got %v", err) 857 } 858 } 859 860 // Now with full protocol (no split) and we should still enforce. 861 c = setupClient() 862 err = c.parse(pub) 863 switch test.shouldFail { 864 case true: 865 if !ErrorIs(err, ErrMaxControlLine) { 866 t.Fatalf("Expected an error parsing longer than expected control line") 867 } 868 case false: 869 if err != nil { 870 t.Fatalf("Should not have failed, got %v", err) 871 } 872 } 873 }) 874 } 875 }