summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--ext/standard/uniqid.c29
2 files changed, 19 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index 7ef1302edc..a1a9b4e334 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ PHP NEWS
- SPL:
. Fixed bug #74669 (Unserialize ArrayIterator broken). (Andrew Nester)
+- Standard:
+ . Fixed bug #74851 (uniqid() without more_entropy performs badly).
+ (Emmanuel Dreyfus)
+
20 Jul 2017, PHP 7.2.0beta1
- Core:
diff --git a/ext/standard/uniqid.c b/ext/standard/uniqid.c
index 22173ae01d..e8f2f19520 100644
--- a/ext/standard/uniqid.c
+++ b/ext/standard/uniqid.c
@@ -38,17 +38,15 @@
#include "php_lcg.h"
#include "uniqid.h"
+#ifdef HAVE_GETTIMEOFDAY
+ZEND_TLS struct timeval prev_tv = { 0, 0 };
+
/* {{{ proto string uniqid([string prefix [, bool more_entropy]])
Generates a unique ID */
-#ifdef HAVE_GETTIMEOFDAY
PHP_FUNCTION(uniqid)
{
char *prefix = "";
-#if defined(__CYGWIN__)
- zend_bool more_entropy = 1;
-#else
zend_bool more_entropy = 0;
-#endif
zend_string *uniqid;
int sec, usec;
size_t prefix_len = 0;
@@ -60,17 +58,20 @@ PHP_FUNCTION(uniqid)
Z_PARAM_BOOL(more_entropy)
ZEND_PARSE_PARAMETERS_END();
-#if HAVE_USLEEP && !defined(PHP_WIN32)
if (!more_entropy) {
-#if defined(__CYGWIN__)
- php_error_docref(NULL, E_WARNING, "You must use 'more entropy' under CYGWIN");
- RETURN_FALSE;
-#else
- usleep(1);
-#endif
+ /* This implementation needs current microsecond to change,
+ * hence we poll time until it does. This is much faster than
+ * calling usleep(1) which may cause the kernel to schedule
+ * another process, causing a pause of around 10ms.
+ */
+ do {
+ (void)gettimeofday((struct timeval *) &tv, (struct timezone *) NULL);
+ } while (tv.tv_sec == prev_tv.tv_sec && tv.tv_usec == prev_tv.tv_usec);
+
+ prev_tv.tv_sec = tv.tv_sec;
+ prev_tv.tv_usec = tv.tv_usec;
}
-#endif
- gettimeofday((struct timeval *) &tv, (struct timezone *) NULL);
+
sec = (int) tv.tv_sec;
usec = (int) (tv.tv_usec % 0x100000);