-
Notifications
You must be signed in to change notification settings - Fork 954
Strictly check CRLF when parsing querybuf #2872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: unstable
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,6 +99,62 @@ start_server {tags {"protocol network"}} { | |
| assert_error "*unbalanced*" {r read} | ||
| } | ||
|
|
||
| test "Check CRLF when parsing the querybuf" { | ||
| # Command) SET key value | ||
| # RESP) *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n | ||
| # We need to strictly check these \r\n characters. | ||
| set proto "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| reconnect; r write $proto; r flush; assert_equal "OK" [r read] | ||
|
|
||
| # Check if multibulklen `*3\r\n` is followed by `\r\n` | ||
| set proto1 "*3x\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| set proto2 "*3\rx\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| set proto3 "*3xx\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| r write $proto1; r flush; assert_error "*invalid multibulk length*" {r read}; reconnect | ||
| r write $proto2; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto3; r flush; assert_error "*invalid multibulk length*" {r read}; reconnect | ||
|
|
||
| # Check if bulklen `$3\r\n` is followed by `\r\n` | ||
| set proto1 "*3\r\n\$3x\nSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| set proto2 "*3\r\n\$3\rxSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| set proto3 "*3\r\n\$3xxSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| r write $proto1; r flush; assert_error "*invalid bulk length*" {r read}; reconnect | ||
| r write $proto2; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto3; r flush; assert_error "*invalid bulk length*" {r read}; reconnect | ||
|
|
||
| # Check if `SET\r\n` is followed by `\r\n` | ||
| set proto1 "*3\r\n\$3\r\nSET\rx\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| set proto2 "*3\r\n\$3\r\nSETx\n\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| set proto3 "*3\r\n\$3\r\nSETxx\$3\r\nkey\r\n\$5\r\nvalue\r\n" | ||
| r write $proto1; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto2; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto3; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
|
|
||
| # Check if `key\r\n` is followed by `\r\n` | ||
| set proto1 "*3\r\n\$3\r\nSET\r\n\$3\r\nkeyx\n\$5\r\nvalue\r\n" | ||
| set proto2 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\rx\$5\r\nvalue\r\n" | ||
| set proto3 "*3\r\n\$3\r\nSET\r\n\$3\r\nkeyxx\$5\r\nvalue\r\n" | ||
| r write $proto1; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto2; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto3; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
|
|
||
| # Check if bulklen `$5\r\n` is followed by `\r\n` | ||
| set proto1 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5x\nvalue\r\n" | ||
| set proto2 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\rxvalue\r\n" | ||
| set proto3 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5xxvalue\r\n" | ||
| r write $proto1; r flush; assert_error "*invalid bulk length*" {r read}; reconnect | ||
| r write $proto2; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto3; r flush; assert_error "*invalid bulk length*" {r read}; reconnect | ||
|
|
||
| # Check if `value\r\n` is followed by `\r\n` | ||
| set proto1 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvaluex\n" | ||
| set proto2 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvalue\rx" | ||
| set proto3 "*3\r\n\$3\r\nSET\r\n\$3\r\nkey\r\n\$5\r\nvaluexx" | ||
| r write $proto1; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto2; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| r write $proto3; r flush; assert_error "*invalid CRLF in request*" {r read}; reconnect | ||
| } | ||
|
|
||
| set c 0 | ||
| foreach seq [list "\x00" "*\x00" "$\x00" "*1\r\n$\x00"] { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change seems to be breaking the test
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. The problem is that we allow people like me contribute to this respectable project ;) after creating the socket in the test.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very clever! I was staring at this and couldn't understand it.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wow, thanks, a good explanation, got it!
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder of this case should be considered as a missing CRLF error? the bulk does include CRLF... Also question: should we backport this fix?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Backport? If you want, but it's not urgent. It's not a security issue. It's only about how we handle incorrect clients. |
||
| incr c | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the first check is for a case when we read up to \r but the \n is not yet read into the buffer right? Maybe we should have made a similar check like we do for inline protocol and just search for the \n and not \r?
not sure if that would simplify things but it seems like it would make the check in line 3490 more accurate...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, maybe, there were some history i don't know about, this code is quite critical and i want to change it as little as possible to avoid any unexpected issues, that would be great if have some protocol fuzzer.
5af3020
bf9fd5f