The new PHPRedis code fails when a value 1,000 or 1,000,000 characters
in length is set. This is due to an incorrect calculation of the
number of digits for the SET command, so that what should be
SET key 1000
<1000 character-long value>
is actually sent to Redis as
SET key 100
<1000 character-long value>
In the second case, the remaining 900 characters remain in the buffer
and are misinterpreted as a command, meaning the next command gets a -
ERR result, no matter what it was.
Here's a patch to the PHPRedis code that fixes this:
----------------------------------------
diff --git a/redis.c b/redis.c
index efdd2fd..ac3f21f 100755
--- a/redis.c
+++ b/redis.c
@@ -127,7 +127,7 @@ redis_cmd_format(char **ret, char *format, ...) {
va_list ap;
int total = 0, sz, ret_sz;
- int i;
+ int i, ci;
unsigned int u;
@@ -153,7 +153,12 @@ redis_cmd_format(char **ret, char *format, ...) {
case 'd':
i = va_arg(ap, int);
/* compute display size of integer value */
- sz = 1+log(abs(i))/log(10);
+ sz = 0;
+ ci = abs(i);
+ while (ci>0) {
+ ci = (ci/10);
+ sz += 1;
+ }
if(i == 0) { /* log 0 doesn't make sense. */
sz = 1;
} else if(i < 0) { /* allow for neg sign as
well. */
-------------------------------
and here's a test case that fails with the old code, and works with
the new:
-------------------------------
#!/usr/bin/php
<?php
$valuelength = 1000;
$testvalue = str_pad('', $valuelength, '0');
$redis = new Redis();
$redis->connect("127.0.0.1", 6379);
$redis->set('key', $testvalue);
$currentvalue = $redis->get('key');
if ($currentvalue!==$testvalue)
die("The returned value was not '$testvalue' but '$currentvalue'\n");
print "Run completed successfully\n";
?>
-------------------------------