Repository: redis/redis

Problem statement:
[BUG] wrong content returned by redis-server
**Describe the bug**

**To reproduce**
```
127.0.0.1:6379> set a 2
OK
127.0.0.1:6379> get a
"2"
```
The result seems right, however the content returned by server is wrong. When using strace
<img width="485" alt="image" src="https://github.com/user-attachments/assets/65ac2899-c113-4dfc-b1ea-76790c64e898" />
it's clear that the result is wrong. It should be
```
$1\r\n2\r\n
```
After reviewed code, I found the bug is introduced in git sha(a106198878f85b91de651dde74587768e81d4506)

the fix code is
```
diff --git a/src/networking.c b/src/networking.c
index e3d0d25e4..589b3ed24 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1080,8 +1080,8 @@ void addReplyBulk(client *c, robj *obj) {
          * to the output buffer. */
         char buf[34];
         size_t len = ll2string(buf,sizeof(buf),(long)obj->ptr);
-        buf[len+1] = '\r';
-        buf[len+2] = '\n';
+        buf[len] = '\r';
+        buf[len+1] = '\n';
         _addReplyLongLongBulk(c, len);
         _addReplyToBufferOrList(c,buf,len+2);
```

If I'm right, please let me to do a code fix pr.

It's just in unstable branch now.

**Expected behavior**

A description of what you expected to happen.

**Additional information**

Any additional information that is relevant to the problem.



Hints:
Another question is why redis-cli is able to parse the wrong content correctly. I found this bug when I was debugging twemproxy.
@raffertyyu good catch, feel free to make a PR to fix it.

Patch:
diff --git a/src/networking.c b/src/networking.c
index e3d0d25e4bf..589b3ed248b 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1080,8 +1080,8 @@ void addReplyBulk(client *c, robj *obj) {
          * to the output buffer. */
         char buf[34];
         size_t len = ll2string(buf,sizeof(buf),(long)obj->ptr);
-        buf[len+1] = '\r';
-        buf[len+2] = '\n';
+        buf[len] = '\r';
+        buf[len+1] = '\n';
         _addReplyLongLongBulk(c, len);
         _addReplyToBufferOrList(c,buf,len+2);
     } else {


Test patch:
diff --git a/tests/unit/protocol.tcl b/tests/unit/protocol.tcl
index e3b4115a8a7..a98b124b74e 100644
--- a/tests/unit/protocol.tcl
+++ b/tests/unit/protocol.tcl
@@ -135,6 +135,68 @@ start_server {tags {"protocol network"}} {
         assert_equal [r read] {a}
     }
 
+    test "bulk reply protocol" {
+        # value=2 (int encoding)
+        r set crlf 2
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 7] "\$1\r\n2\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 9] "\$3\r\nint\r\n"
+
+        # value=2147483647 (int encoding)
+        r set crlf 2147483647
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 17] "\$10\r\n2147483647\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 9] "\$3\r\nint\r\n"
+
+        # value=-2147483648 (int encoding)
+        r set crlf -2147483648
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 18] "\$11\r\n-2147483648\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 9] "\$3\r\nint\r\n"
+
+        # value=-9223372036854775809 (embstr encoding)
+        r set crlf -9223372036854775809
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 27] "\$20\r\n-9223372036854775809\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 12] "\$6\r\nembstr\r\n"
+
+        # value=9223372036854775808 (embstr encoding)
+        r set crlf 9223372036854775808
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 26] "\$19\r\n9223372036854775808\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 12] "\$6\r\nembstr\r\n"
+
+        # normal sds (embstr encoding)
+        r set crlf aaaaaaaaaaaaaaaa
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 23] "\$16\r\naaaaaaaaaaaaaaaa\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 12] "\$6\r\nembstr\r\n"
+
+        # normal sds (raw string encoding) with 45 'a'
+        set rawstr [string repeat "a" 45]
+        r set crlf $rawstr
+        assert_equal [r rawread 5] "+OK\r\n"
+        r get crlf
+        assert_equal [r rawread 52] "\$45\r\n$rawstr\r\n"
+        r object encoding crlf
+        assert_equal [r rawread 9] "\$3\r\nraw\r\n"
+
+        r del crlf
+        assert_equal [r rawread 4] ":1\r\n"
+    }
+
     # restore connection settings
     r readraw 0
     r deferred 0