summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--Zend/tests/compound_assign_with_numeric_strings.phpt41
-rw-r--r--Zend/zend_operators.c21
-rw-r--r--ext/curl/interface.c1
-rw-r--r--ext/ereg/regex/regcomp.c4
-rw-r--r--ext/gettext/tests/bug66267.phpt1
-rw-r--r--ext/mysqli/mysqli_api.c28
-rw-r--r--ext/mysqli/tests/010.phpt6
-rw-r--r--ext/mysqli/tests/bug67839.phpt18
-rw-r--r--ext/mysqlnd/config9.m431
-rw-r--r--ext/mysqlnd/mysql_float_to_double.h60
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c53
-rw-r--r--ext/opcache/Optimizer/block_pass.c2
-rw-r--r--ext/opcache/zend_shared_alloc.c2
-rw-r--r--ext/pcre/php_pcre.c2
-rw-r--r--ext/pgsql/pgsql.c3
-rw-r--r--ext/standard/basic_functions.c9
-rw-r--r--ext/standard/basic_functions.h3
-rw-r--r--ext/standard/pack.c2
-rw-r--r--ext/standard/php_fopen_wrapper.c2
-rw-r--r--ext/standard/string.c36
-rw-r--r--ext/standard/tests/strings/bug68636.phpt21
-rw-r--r--ext/standard/tests/strings/crypt_des_error.phpt16
-rw-r--r--ext/standard/url_scanner_ex.c2
-rw-r--r--ext/standard/url_scanner_ex.re2
25 files changed, 242 insertions, 125 deletions
diff --git a/NEWS b/NEWS
index a89018d174..d8d94df9fa 100644
--- a/NEWS
+++ b/NEWS
@@ -65,6 +65,7 @@
. Fixed possible read after end of buffer and use after free. (Dmitry)
- Opcache:
+ . Fixed bug (try block removed while combined with xdebug). (Laruence)
. Fixed bug #68644 (strlen incorrect : mbstring + func_overload=2 +UTF-8
+ Opcache). (Laruence)
diff --git a/Zend/tests/compound_assign_with_numeric_strings.phpt b/Zend/tests/compound_assign_with_numeric_strings.phpt
new file mode 100644
index 0000000000..803650cb02
--- /dev/null
+++ b/Zend/tests/compound_assign_with_numeric_strings.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Error cases of compound shift assignment on strings
+--FILE--
+<?php
+
+$n = "65";
+$n <<= $n;
+var_dump($n);
+
+$n = "-1";
+$n <<= $n;
+var_dump($n);
+
+$n = "65";
+$n >>= $n;
+var_dump($n);
+
+$n = "-1";
+$n >>= $n;
+var_dump($n);
+
+$n = "0";
+$n %= $n;
+var_dump($n);
+
+$n = "-1";
+$n %= $n;
+var_dump($n);
+--EXPECTF--
+int(0)
+
+Warning: Bit shift by negative number in %s on line %d
+bool(false)
+int(0)
+
+Warning: Bit shift by negative number in %s on line %d
+bool(false)
+
+Warning: Division by zero in %s on line %d
+bool(false)
+int(0)
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 14a85123c1..0b1b9f2188 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1143,6 +1143,10 @@ ZEND_API int mod_function(zval *result, zval *op1, zval *op2) /* {{{ */
zend_long op1_lval, op2_lval;
convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function);
+
+ if (op1 == result) {
+ zval_dtor(result);
+ }
if (op2_lval == 0) {
zend_error(E_WARNING, "Division by zero");
@@ -1156,9 +1160,6 @@ ZEND_API int mod_function(zval *result, zval *op1, zval *op2) /* {{{ */
return SUCCESS;
}
- if (op1 == result) {
- zval_dtor(result);
- }
ZVAL_LONG(result, op1_lval % op2_lval);
return SUCCESS;
}
@@ -1451,6 +1452,10 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2) /* {{{ */
convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function);
+ if (op1 == result) {
+ zval_dtor(result);
+ }
+
/* prevent wrapping quirkiness on some processors where << 64 + x == << x */
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
if (EXPECTED(op2_lval > 0)) {
@@ -1463,9 +1468,6 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2) /* {{{ */
}
}
- if (op1 == result) {
- zval_dtor(result);
- }
ZVAL_LONG(result, op1_lval << op2_lval);
return SUCCESS;
}
@@ -1477,6 +1479,10 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2) /* {{{ */
convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function);
+ if (op1 == result) {
+ zval_dtor(result);
+ }
+
/* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
if (EXPECTED(op2_lval > 0)) {
@@ -1489,9 +1495,6 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2) /* {{{ */
}
}
- if (op1 == result) {
- zval_dtor(result);
- }
ZVAL_LONG(result, op1_lval >> op2_lval);
return SUCCESS;
}
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index f5bfb1e919..0c267e0681 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -2721,6 +2721,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{
curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share);
}
}
+ break;
#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
case CURLOPT_FNMATCH_FUNCTION:
diff --git a/ext/ereg/regex/regcomp.c b/ext/ereg/regex/regcomp.c
index 730bcf568a..f55862b922 100644
--- a/ext/ereg/regex/regcomp.c
+++ b/ext/ereg/regex/regcomp.c
@@ -1276,6 +1276,10 @@ int c;
register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
register unsigned uc = (unsigned char)c;
+ if (!g->setbits) {
+ return(0);
+ }
+
for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
if (col[uc] != 0)
return(1);
diff --git a/ext/gettext/tests/bug66267.phpt b/ext/gettext/tests/bug66267.phpt
index 26963acb7e..56396860b4 100644
--- a/ext/gettext/tests/bug66267.phpt
+++ b/ext/gettext/tests/bug66267.phpt
@@ -28,6 +28,7 @@ $loc = ["de_DE", "fr_FR", "en_US"];
foreach ($loc as $l) {
putenv("LC_ALL=$l");
+ setlocale(LC_ALL, $l);
$path = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . "66265");
bindtextdomain($domain, $path);
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 698e6bb5ba..7ea4d6a1a0 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -33,6 +33,7 @@
#include "zend_smart_str.h"
#include "php_mysqli_structs.h"
#include "mysqli_priv.h"
+#include "ext/mysqlnd/mysql_float_to_double.h"
#if !defined(MYSQLI_USE_MYSQLND)
@@ -413,9 +414,18 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc, un
col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
switch (col_type) {
- case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_FLOAT:
stmt->result.buf[ofs].type = IS_DOUBLE;
+ stmt->result.buf[ofs].buflen = sizeof(float);
+
+ stmt->result.buf[ofs].val = (char *)emalloc(sizeof(float));
+ bind[ofs].buffer_type = MYSQL_TYPE_FLOAT;
+ bind[ofs].buffer = stmt->result.buf[ofs].val;
+ bind[ofs].is_null = &stmt->result.is_null[ofs];
+ break;
+
+ case MYSQL_TYPE_DOUBLE:
+ stmt->result.buf[ofs].type = IS_DOUBLE;
stmt->result.buf[ofs].buflen = sizeof(double);
/* allocate buffer for double */
@@ -1021,8 +1031,22 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
}
break;
case IS_DOUBLE:
- ZVAL_DOUBLE(result, *(double *)stmt->result.buf[i].val);
+ {
+ double dval;
+ if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
+#ifndef NOT_FIXED_DEC
+# define NOT_FIXED_DEC 31
+#endif
+ dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
+ (stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
+ stmt->stmt->fields[i].decimals);
+ } else {
+ dval = *((double *)stmt->result.buf[i].val);
+ }
+
+ ZVAL_DOUBLE(result, dval);
break;
+ }
case IS_STRING:
if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
#if MYSQL_VERSION_ID > 50002
diff --git a/ext/mysqli/tests/010.phpt b/ext/mysqli/tests/010.phpt
index 83a43e06b6..b1712ca2a6 100644
--- a/ext/mysqli/tests/010.phpt
+++ b/ext/mysqli/tests/010.phpt
@@ -62,7 +62,7 @@ mysqli_close($link);
--EXPECT--
array(7) {
[0]=>
- float(3.141593)
+ float(3.14159)
[1]=>
float(-1.0E-6)
[2]=>
@@ -70,10 +70,10 @@ array(7) {
[3]=>
float(1.0E+12)
[4]=>
- float(0.5646425)
+ float(0.564642)
[5]=>
float(1)
[6]=>
- float(8.888889E+14)
+ float(8.88889E+14)
}
done!
diff --git a/ext/mysqli/tests/bug67839.phpt b/ext/mysqli/tests/bug67839.phpt
index ef4e6c649c..58b2d2fa82 100644
--- a/ext/mysqli/tests/bug67839.phpt
+++ b/ext/mysqli/tests/bug67839.phpt
@@ -38,19 +38,27 @@ precision=5
die();
}
- if (!mysqli_stmt_execute($stmt)) {
+ $id = null;
+ $fp4 = null;
+ $fp8 = null;
+
+ if (!mysqli_stmt_bind_result($stmt, $id, $fp4, $fp8)) {
printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
die();
}
-
- if (!($result = mysqli_stmt_get_result($stmt))) {
+ if (!mysqli_stmt_execute($stmt)) {
printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
die();
}
- $data = mysqli_fetch_assoc($result);
- print $data['id'] . ": " . $data['fp4'] . ": " . $data['fp8'] . "\n";
+
+ if (!(mysqli_stmt_fetch($stmt))) {
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ die();
+ }
+
+ print $id . ": " . $fp4 . ": " . $fp8 . "\n";
?>
--CLEAN--
<?php
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 756a325014..92cab94367 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -49,34 +49,3 @@ fi
if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes" || test "$PHP_MYSQLI" != "no"; then
PHP_ADD_BUILD_DIR([ext/mysqlnd], 1)
fi
-
-dnl
-dnl Check if the compiler supports Decimal32/64/128 types from the IEEE-754 2008 version
-dnl References: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1657.pdf
-dnl http://speleotrove.com/decimal/
-dnl
-AC_CACHE_CHECK([whether whether compiler supports Decimal32/64/128 types], ac_cv_decimal_fp_supported,[
-AC_TRY_RUN( [
-#include <stdio.h>
-#include <string.h>
-
-int main(int argc, char **argv) {
- typedef float dec32 __attribute__((mode(SD)));
- dec32 k = 99.49f;
- double d2 = (double)k;
- const char *check_str = "99.49";
- char print_str[32];
-
- snprintf(print_str, 32, "%f", d2);
- return memcmp(print_str, check_str, 5);
-}
-],[
- ac_cv_decimal_fp_supported=yes
-],[
- ac_cv_decimal_fp_supported=no
-],[
- ac_cv_decimal_fp_supported=no
-])])
-if test "$ac_cv_decimal_fp_supported" = "yes"; then
- AC_DEFINE(HAVE_DECIMAL_FP_SUPPORT, 1, [Define if the compiler supports Decimal32/64/128 types.])
-fi
diff --git a/ext/mysqlnd/mysql_float_to_double.h b/ext/mysqlnd/mysql_float_to_double.h
new file mode 100644
index 0000000000..2ccce7d14d
--- /dev/null
+++ b/ext/mysqlnd/mysql_float_to_double.h
@@ -0,0 +1,60 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Keyur Govande <kgovande@gmail.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQL_FLOAT_TO_DOUBLE_H
+#define MYSQL_FLOAT_TO_DOUBLE_H
+
+#include "main/php.h"
+#include <float.h>
+#include "main/snprintf.h"
+
+#define MAX_CHAR_BUF_LEN 255
+
+#ifndef FLT_DIG
+# define FLT_DIG 6
+#endif
+
+/*
+ * Convert from a 4-byte float to a 8-byte decimal by first converting
+ * the float to a string, and then the string to a double.
+ * The decimals argument specifies the precision of the output. If decimals
+ * is less than zero, then a gcvt(3) like logic is used with the significant
+ * digits set to FLT_DIG i.e. 6.
+ */
+static inline double mysql_float_to_double(float fp4, int decimals) {
+ char num_buf[MAX_CHAR_BUF_LEN]; /* Over allocated */
+
+ if (decimals < 0) {
+ php_gcvt(fp4, FLT_DIG, '.', 'e', num_buf);
+ } else {
+ php_sprintf(num_buf, "%.*f", decimals, fp4);
+ }
+
+ return zend_strtod(num_buf, NULL);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
+#endif /* MYSQL_FLOAT_TO_DOUBLE_H */
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index 0cd34540b0..b78e4f0c70 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -24,6 +24,7 @@
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
+#include "ext/mysqlnd/mysql_float_to_double.h"
#define MYSQLND_SILENT
@@ -181,56 +182,12 @@ ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
(*row)+= 4;
DBG_INF_FMT("value=%f", fval);
- /*
- * The following is needed to correctly support 4-byte floats.
- * Otherwise, a value of 9.99 in a FLOAT column comes out of mysqli
- * as 9.9998998641968.
- *
- * For GCC, we use the built-in decimal support to "up-convert" a
- * 4-byte float to a 8-byte double.
- * When that is not available, we fall back to converting the float
- * to a string and then converting the string to a double. This mimics
- * what MySQL does.
- */
-#ifdef HAVE_DECIMAL_FP_SUPPORT
- {
- typedef float dec32 __attribute__((mode(SD)));
- /* volatile so the compiler will not optimize away the conversion */
- volatile dec32 d32val = fval;
-
- /* The following cast is guaranteed to do the right thing */
- dval = (double) d32val;
- }
-#elif defined(PHP_WIN32)
- {
- /* float datatype on Winows is already 4 byte but has a precision of 7 digits */
- char num_buf[2048];
- (void)_gcvt_s(num_buf, 2048, fval, field->decimals >= 31 ? 7 : field->decimals);
- dval = zend_strtod(num_buf, NULL);
- }
-#else
- {
- char num_buf[2048]; /* Over allocated */
- char *s;
-
-#ifndef FLT_DIG
-# define FLT_DIG 6
-#endif
- /* Convert to string. Ignoring localization, etc.
- * Following MySQL's rules. If precision is undefined (NOT_FIXED_DEC i.e. 31)
- * or larger than 31, the value is limited to 6 (FLT_DIG).
- */
- s = php_gcvt(fval,
- field->decimals >= 31 ? FLT_DIG : field->decimals,
- '.',
- 'e',
- num_buf);
-
- /* And now convert back to double */
- dval = zend_strtod(s, NULL);
- }
+#ifndef NOT_FIXED_DEC
+# define NOT_FIXED_DEC 31
#endif
+ dval = mysql_float_to_double(fval, (field->decimals >= NOT_FIXED_DEC) ? -1 : field->decimals);
+
ZVAL_DOUBLE(zv, dval);
DBG_VOID_RETURN;
}
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 9cb95a3e47..276f802b34 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -1469,7 +1469,7 @@ next_target:
}
/* next block is only NOP's */
- if (target == target_end) {
+ if (target == target_end && ! block->follow_to->protected) {
del_source(block, block->follow_to);
block->follow_to = block->follow_to->follow_to;
ADD_SOURCE(block, block->follow_to);
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index 4036abe06f..48c16abb9c 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -344,10 +344,10 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source)
retval = ZCG(mem);
ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
memcpy(retval, source, size);
+ zend_shared_alloc_register_xlat_entry(source, retval);
if (free_source) {
efree(source);
}
- zend_shared_alloc_register_xlat_entry(source, retval);
return retval;
}
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index 5701ae1a0c..d6f3823d3f 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -376,7 +376,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
#if HAVE_SETLOCALE
if (BG(locale_string) &&
- (!BG(locale_string)->len != 1 || !BG(locale_string)->val[0] != 'C')) {
+ (BG(locale_string)->len != 1 || BG(locale_string)->val[0] != 'C')) {
tables = pcre_maketables();
}
#endif
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index e4aab66e00..0469c8b1ba 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -6445,6 +6445,9 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const c
/* schame.table should be "schame"."table" */
table_copy = estrdup(table);
token = php_strtok_r(table_copy, ".", &tmp);
+ if (token == NULL) {
+ token = table;
+ }
len = strlen(token);
if (_php_pgsql_detect_identifier_escape(token, len) == SUCCESS) {
smart_str_appendl(querystr, token, len);
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index ed5206aa69..02001f5433 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -3708,6 +3708,7 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
ZVAL_UNDEF(&BG(strtok_zval));
BG(strtok_last) = NULL;
BG(locale_string) = NULL;
+ BG(locale_changed) = 0;
BG(array_walk_fci) = empty_fcall_info;
BG(array_walk_fci_cache) = empty_fcall_info_cache;
BG(user_compare_fci) = empty_fcall_info;
@@ -3756,12 +3757,14 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
/* Check if locale was changed and change it back
* to the value in startup environment */
- if (BG(locale_string) != NULL) {
+ if (BG(locale_changed)) {
setlocale(LC_ALL, "C");
setlocale(LC_CTYPE, "");
zend_update_current_locale();
- zend_string_release(BG(locale_string));
- BG(locale_string) = NULL;
+ if (BG(locale_string)) {
+ zend_string_release(BG(locale_string));
+ BG(locale_string) = NULL;
+ }
}
/* FG(stream_wrappers) and FG(stream_filters) are destroyed
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index fe09dc5e25..8820148a63 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -168,7 +168,8 @@ typedef struct _php_basic_globals {
HashTable putenv_ht;
zval strtok_zval;
char *strtok_string;
- zend_string *locale_string;
+ zend_string *locale_string; /* current LC_CTYPE locale (or NULL for 'C') */
+ zend_bool locale_changed; /* locale was changed and has to be restored */
char *strtok_last;
char strtok_table[256];
zend_ulong strtok_len;
diff --git a/ext/standard/pack.c b/ext/standard/pack.c
index d1c7cf9e0b..5578604b66 100644
--- a/ext/standard/pack.c
+++ b/ext/standard/pack.c
@@ -736,7 +736,7 @@ PHP_FUNCTION(unpack)
case 'A': {
/* A will strip any trailing whitespace */
char padn = '\0'; char pads = ' '; char padt = '\t'; char padc = '\r'; char padl = '\n';
- size_t len = inputlen - inputpos; /* Remaining string */
+ zend_long len = inputlen - inputpos; /* Remaining string */
/* If size was given take minimum of len and size */
if ((size >= 0) && (len > size)) {
diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c
index 9239b37032..dc52ade5c8 100644
--- a/ext/standard/php_fopen_wrapper.c
+++ b/ext/standard/php_fopen_wrapper.c
@@ -146,7 +146,7 @@ php_stream_ops php_stream_input_ops = {
static void php_stream_apply_filter_list(php_stream *stream, char *filterlist, int read_chain, int write_chain) /* {{{ */
{
- char *p, *token;
+ char *p, *token = NULL;
php_stream_filter *temp_filter;
p = php_strtok_r(filterlist, "|", &token);
diff --git a/ext/standard/string.c b/ext/standard/string.c
index c57885fff1..483e8b4f1d 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -4343,27 +4343,31 @@ PHP_FUNCTION(setlocale)
if (retval) {
if (loc) {
/* Remember if locale was changed */
- size_t len;
+ size_t len = strlen(retval);
- if (BG(locale_string)) {
- zend_string_release(BG(locale_string));
- }
- len = strlen(retval);
- if (len == loc->len && !memcmp(loc->val, retval, len)) {
- BG(locale_string) = zend_string_copy(loc);
- } else {
- BG(locale_string) = zend_string_init(retval, len, 0);
+ BG(locale_changed) = 1;
+ if (cat == LC_CTYPE || cat == LC_ALL) {
+ if (BG(locale_string)) {
+ zend_string_release(BG(locale_string));
+ }
+ if (len == loc->len && !memcmp(loc->val, retval, len)) {
+ BG(locale_string) = zend_string_copy(loc);
+ RETURN_STR(BG(locale_string));
+ } else {
+ BG(locale_string) = zend_string_init(retval, len, 0);
+ zend_string_release(loc);
+ RETURN_STR(BG(locale_string));
+ }
+ } else if (len == loc->len && !memcmp(loc->val, retval, len)) {
+ RETURN_STR(loc);
}
-
zend_string_release(loc);
}
- if (BG(locale_string)) {
- RETURN_STR(zend_string_copy(BG(locale_string)));
- } else {
- RETURN_EMPTY_STRING();
- }
+ RETURN_STRING(retval);
+ }
+ if (loc) {
+ zend_string_release(loc);
}
- zend_string_release(loc);
if (Z_TYPE(args[0]) == IS_ARRAY) {
if (zend_hash_move_forward_ex(Z_ARRVAL(args[0]), &pos) == FAILURE) break;
diff --git a/ext/standard/tests/strings/bug68636.phpt b/ext/standard/tests/strings/bug68636.phpt
new file mode 100644
index 0000000000..246722c7aa
--- /dev/null
+++ b/ext/standard/tests/strings/bug68636.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #68636 (setlocale no longer returns current value per category).
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ die('skip Not valid for windows');
+}
+if (setlocale(LC_ALL, "en_US.UTF8") !== "en_US.UTF8") {
+ die('skip available locales not usable');
+}
+?>
+--FILE--
+<?php
+var_dump(setlocale(LC_TIME, 'en_US.UTF8'));
+var_dump(setlocale(LC_NUMERIC, 'C'));
+var_dump(setlocale(LC_TIME, 0));
+?>
+--EXPECT--
+string(10) "en_US.UTF8"
+string(1) "C"
+string(10) "en_US.UTF8"
diff --git a/ext/standard/tests/strings/crypt_des_error.phpt b/ext/standard/tests/strings/crypt_des_error.phpt
new file mode 100644
index 0000000000..f480efc470
--- /dev/null
+++ b/ext/standard/tests/strings/crypt_des_error.phpt
@@ -0,0 +1,16 @@
+--TEST--
+crypt(): *0 should return *1
+--SKIPIF--
+<?php
+if (!function_exists('crypt')) {
+ die("SKIP crypt() is not available");
+}
+?>
+--FILE--
+<?php
+
+var_dump(crypt('foo', '*0'));
+
+?>
+--EXPECT--
+string(2) "*1"
diff --git a/ext/standard/url_scanner_ex.c b/ext/standard/url_scanner_ex.c
index a24fb1ee8b..878af57813 100644
--- a/ext/standard/url_scanner_ex.c
+++ b/ext/standard/url_scanner_ex.c
@@ -53,8 +53,8 @@ static PHP_INI_MH(OnUpdateTags)
{
url_adapt_state_ex_t *ctx;
char *key;
- char *lasts;
char *tmp;
+ char *lasts = NULL;
ctx = &BG(url_adapt_state_ex);
diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
index e374b76195..7d4f42a7cf 100644
--- a/ext/standard/url_scanner_ex.re
+++ b/ext/standard/url_scanner_ex.re
@@ -51,8 +51,8 @@ static PHP_INI_MH(OnUpdateTags)
{
url_adapt_state_ex_t *ctx;
char *key;
- char *lasts;
char *tmp;
+ char *lasts = NULL;
ctx = &BG(url_adapt_state_ex);