Skip to content

Instantly share code, notes, and snippets.

@chobie
Created May 4, 2012 02:21
Show Gist options
  • Save chobie/2591440 to your computer and use it in GitHub Desktop.
Save chobie/2591440 to your computer and use it in GitHub Desktop.
php-redis-5.4-patch
diff --git a/config.m4 b/config.m4
index 51a1cad..f1af506 100755
--- a/config.m4
+++ b/config.m4
@@ -55,5 +55,5 @@ if test "$PHP_REDIS" != "no"; then
dnl
dnl PHP_SUBST(REDIS_SHARED_LIBADD)
- PHP_NEW_EXTENSION(redis, redis.c library.c redis_session.c redis_array.c redis_array_impl.c igbinary/igbinary.c igbinary/hash_si.c igbinary/hash_function.c, $ext_shared)
+ PHP_NEW_EXTENSION(redis, redis.c g_fmt.c library.c redis_session.c redis_array.c redis_array_impl.c igbinary/igbinary.c igbinary/hash_si.c igbinary/hash_function.c, $ext_shared)
fi
diff --git a/g_fmt.c b/g_fmt.c
new file mode 100644
index 0000000..9fab62b
--- /dev/null
+++ b/g_fmt.c
@@ -0,0 +1,105 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 1996 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
+ * it suffices to declare buf
+ * char buf[32];
+ */
+
+/* Modified for use with php in the memcached client extension.
+ *
+ * // Teddy Grenman <[email protected]>, 2010-05-18.
+ */
+
+/* Modified for use with php in the redis client extension.
+ *
+ * // Shuhei Tanuma <[email protected]>, 2012-05-04.
+ */
+
+
+#include <zend_operators.h>
+
+char *php_redis_g_fmt(register char *b, double x) {
+ register int i, k;
+ register char *s;
+ int decpt, j, sign;
+ char *b0, *s0, *se;
+
+ b0 = b;
+#ifdef IGNORE_ZERO_SIGN
+ if (!x) {
+ *b++ = '0';
+ *b = 0;
+ goto done;
+ }
+#endif
+
+ s = s0 = zend_dtoa(x, 0, 0, &decpt, &sign, &se);
+ if (sign)
+ *b++ = '-';
+ if (decpt == 9999) /* Infinity or Nan */ {
+ while(*b++ = *s++);
+ goto done0;
+ }
+ if (decpt <= -4 || decpt > se - s + 5) {
+ *b++ = *s++;
+ if (*s) {
+ *b++ = '.';
+ while(*b = *s++)
+ b++;
+ }
+ *b++ = 'e';
+ /* sprintf(b, "%+.2d", decpt - 1); */
+ if (--decpt < 0) {
+ *b++ = '-';
+ decpt = -decpt;
+ }
+ else
+ *b++ = '+';
+ for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
+ for(;;) {
+ i = decpt / k;
+ *b++ = i + '0';
+ if (--j <= 0)
+ break;
+ decpt -= i*k;
+ decpt *= 10;
+ }
+ *b = 0;
+ } else if (decpt <= 0) {
+ *b++ = '.';
+ for(; decpt < 0; decpt++)
+ *b++ = '0';
+ while(*b++ = *s++);
+ } else {
+ while(*b = *s++) {
+ b++;
+ if (--decpt == 0 && *s)
+ *b++ = '.';
+ }
+ for(; decpt > 0; decpt--)
+ *b++ = '0';
+ *b = 0;
+ }
+
+ done0:
+ zend_freedtoa(s0);
+ done:
+ return b0;
+}
diff --git a/g_fmt.h b/g_fmt.h
new file mode 100644
index 0000000..a7ee1b6
--- /dev/null
+++ b/g_fmt.h
@@ -0,0 +1,38 @@
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 1996 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
+ * it suffices to declare buf
+ * char buf[32];
+ */
+
+/* Modified for use with php in the memcached client
+ * extension by Teddy Grenman, 2010.
+ */
+
+/* Modified for use with php in the redis client
+ * extension by Shuhei Tanuma, 2012-05-04.
+ */
+
+#ifndef REDIS_G_FMT_H
+#define REDIS_G_FMT_H
+
+char *php_redis_g_fmt(register char *b, double x);
+
+#endif
diff --git a/library.c b/library.c
index faef623..5bd2506 100644
--- a/library.c
+++ b/library.c
@@ -12,6 +12,7 @@
#include <zend_exceptions.h>
#include "php_redis.h"
#include "library.h"
+#include "g_fmt.h"
#include <ext/standard/php_math.h>
#define UNSERIALIZE_ONLY_VALUES 0
@@ -259,12 +260,12 @@ redis_cmd_format_static(char **ret, char *keyword, char *format, ...) {
case 'f':
case 'F': {
double d = va_arg(ap, double);
- dbl_str = _php_math_number_format(d, 8, '.', '\x00');
+ char dbl_str[32] = {0};
+ php_redis_g_fmt(dbl_str, d);
dbl_len = strlen(dbl_str);
smart_str_append_long(&buf, dbl_len);
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
smart_str_appendl(&buf, dbl_str, dbl_len);
- efree(dbl_str);
}
break;
@@ -318,12 +319,12 @@ redis_cmd_format(char **ret, char *format, ...) {
case 'F':
case 'f': {
double d = va_arg(ap, double);
- dbl_str = _php_math_number_format(d, 8, '.', '\x00');
+ char dbl_str[32] = {0};
+ php_redis_g_fmt(dbl_str, d);
dbl_len = strlen(dbl_str);
smart_str_append_long(&buf, dbl_len);
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
smart_str_appendl(&buf, dbl_str, dbl_len);
- efree(dbl_str);
}
break;
diff --git a/redis.c b/redis.c
index d1f5e5d..07c0c9b 100755
--- a/redis.c
+++ b/redis.c
@@ -3488,19 +3488,19 @@ PHP_METHOD(Redis, zAdd) {
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
for(i = 1; i < argc; i +=2) {
+ char dbl_str[32] = {0};
convert_to_double(z_args[i]); // convert score to double
val_free = redis_serialize(redis_sock, z_args[i+1], &val, &val_len TSRMLS_CC); // possibly serialize value.
/* add score */
score = Z_DVAL_P(z_args[i]);
- dbl_str = _php_math_number_format(score, 8, '.', '\x00');
+ php_redis_g_fmt(dbl_str, score);
dbl_len = strlen(dbl_str);
smart_str_appendc(&buf, '$');
smart_str_append_long(&buf, dbl_len);
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
smart_str_appendl(&buf, dbl_str, dbl_len);
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- efree(dbl_str);
/* add value */
smart_str_appendc(&buf, '$');
@ulrichsg
Copy link

ulrichsg commented May 4, 2012

I have re-installed my phpredis extension with this patch applied, but now it gives me the following error message:
php: symbol lookup error: /usr/lib/php5/20100525+lfs/redis.so: undefined symbol: php_redis_g_fmt
Do you have any idea why this might be happening?
My system is Debian wheezy with PHP 5.4.0 installed.

@chobie
Copy link
Author

chobie commented May 4, 2012

@ulrichsg did you redo phpize? I've added g_fmt.c entry to config.m4 so It need to do phpize.

how can i patch this to php-redis?

git clone https://github.com/nicolasff/phpredis.git
cd phpredis
wget https://raw.github.com/gist/2591440/d9cfdb93cd2ef8629723c0aa36c5ea4f5dd67948/php-redis-5.4-patch.diff
patch -p1 < php-redis-5.4-patch.diff 
phipze
./configure
make
sudo make install

test.php

<?php
$redis = new Redis();
$redis->connect('127.0.0.1','6379');
$return = array();
$return[]=$redis->zAdd('login_time',microtime(true),'Niro');
$return[]=$redis->zAdd('login_time',microtime(true),'Another');
$return[]=$redis->zRange('login_time',0,-1,true);
echo "<pre>";
var_dump($return);
echo "</pre><br>";
$ php test.php
<pre>array(3) {
  [0]=>
  int(0)
  [1]=>
  int(0)
  [2]=>
  array(2) {
    ["Niro"]=>
    string(18) "1336138521.9390869"
    ["Another"]=>
    string(18) "1336138521.9393129"
  }
}
</pre><br>

Can you try to re-install php-redis with above instruction?

@leafpeak
Copy link

leafpeak commented May 4, 2012

Patch works! Thanks.

@ulrichsg
Copy link

ulrichsg commented May 4, 2012

@chobie I had indeed neglected to phpize again after patching. Now it works. Thanks!

@kporembinski
Copy link

[08:49:29] [root@proofhq-dev phpredis]# patch -p1 < php-redis-5.4-patch.diff
patching file config.m4
Hunk #1 FAILED at 55.
1 out of 1 hunk FAILED -- saving rejects to file config.m4.rej
patching file g_fmt.c
patching file g_fmt.h
patching file library.c
Hunk #1 succeeded at 16 (offset 4 lines).
Hunk #2 FAILED at 260.
Hunk #3 FAILED at 319.
2 out of 3 hunks FAILED -- saving rejects to file library.c.rej
patching file redis.c
Hunk #1 FAILED at 3488.
1 out of 1 hunk FAILED -- saving rejects to file redis.c.rej

I can't add patch and still have Segmentation Fault. PHP 5.4.15, 2.6.32-358.6.1.el6.x86_64.

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