Skip to content

Conversation

@enjoy-binbin
Copy link
Member

Currently, when parsing querybuf, we are not checking for CRLF,
instead we assume the last two characters are CRLF by default,
as shown in the following example:

telnet 127.0.0.1 6379
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
*3
$3
set
$3
key
$5
value12
+OK
get key
$5
value

*3
$3
set
$3
key
$5
value12345
+OK
-ERR unknown command '345', with args beginning with:

This should actually be considered a protocol error. When a bug
occurs in the client-side implementation, we may execute incorrect
requests (writing incorrect data is the most serious of these).

Currently, when parsing querybuf, we are not checking for CRLF,
instead we assume the last two characters are CRLF by default,
as shown in the following example:
```
telnet 127.0.0.1 6379
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
*3
$3
set
$3
key
$5
value12
+OK
get key
$5
value

*3
$3
set
$3
key
$5
value12345
+OK
-ERR unknown command '345', with args beginning with:
```

This should actually be considered a protocol error. When a bug
occurs in the client-side implementation, we may execute incorrect
requests (writing incorrect data is the most serious of these).

Signed-off-by: Binbin <[email protected]>
@enjoy-binbin enjoy-binbin added the run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP) label Nov 25, 2025
Signed-off-by: Binbin <[email protected]>
}

set c 0
foreach seq [list "\x00" "*\x00" "$\x00" "*1\r\n$\x00"] {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems to be breaking the test *1\r\n$\x00. @ranshid Would you like to take a look?

Copy link
Member

@ranshid ranshid Nov 25, 2025

Choose a reason for hiding this comment

The 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 ;)
The 4th sequence \n will also include carriage return when the socket is not in binary mode.
So the server will actually get:
*1\r\r\n$\x00 which will hit your new validation
So I would suggest to just add:

fconfigure $s -translation binary -encoding binary

after creating the socket in the test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clever! I was staring at this and couldn't understand it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, thanks, a good explanation, got it!

Copy link
Member

Choose a reason for hiding this comment

The 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...
IMO this does indicate that it might be better to track the '\n' like we do for inline protocol. I understand the need to avoid making changes in this critical path, but we do have time till we release the next version....

Also question: should we backport this fix?

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

@ranshid ranshid self-requested a review November 25, 2025 14:33
Copy link
Member

@ranshid ranshid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Maybe we could simplify the logic by searching the '\n\ instead?
@uriyage maybe you remember something about why it is so important to search for \r and not \n?

Comment on lines 3493 to 3504
/* Buffer should also contain \n */
if (newline - (c->querybuf + c->qb_pos) > (ssize_t)(sdslen(c->querybuf) - c->qb_pos - 2)) return 0;

/* Check that what follows \r is a real \n */
if (newline[1] != '\n') {
return READ_FLAGS_ERROR_INVALID_CRLF;
}

Copy link
Member

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...

Copy link
Member Author

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

}

set c 0
foreach seq [list "\x00" "*\x00" "$\x00" "*1\r\n$\x00"] {
Copy link
Member

@ranshid ranshid Nov 25, 2025

Choose a reason for hiding this comment

The 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 ;)
The 4th sequence \n will also include carriage return when the socket is not in binary mode.
So the server will actually get:
*1\r\r\n$\x00 which will hit your new validation
So I would suggest to just add:

fconfigure $s -translation binary -encoding binary

after creating the socket in the test.

Signed-off-by: Binbin <[email protected]>
@codecov
Copy link

codecov bot commented Nov 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.43%. Comparing base (d16788e) to head (693619b).

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #2872      +/-   ##
============================================
- Coverage     72.45%   72.43%   -0.02%     
============================================
  Files           128      128              
  Lines         70485    70491       +6     
============================================
- Hits          51068    51063       -5     
- Misses        19417    19428      +11     
Files with missing lines Coverage Δ
src/networking.c 88.56% <100.00%> (+0.11%) ⬆️
src/server.h 100.00% <ø> (ø)

... and 9 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranshid
Copy link
Member

ranshid commented Nov 26, 2025

@enjoy-binbin any idea why the new fails?

@zuiderkwast
Copy link
Contributor

@enjoy-binbin any idea why the new fails?

The failures on fedora rawhide is this:

@ranshid
Copy link
Member

ranshid commented Nov 27, 2025

@enjoy-binbin any idea why the new fails?

The failures on fedora rawhide is this:

@enjoy-binbin Can we just merge unstable so we can have a clean run? probably will be fine, but just to play on the safe side

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants