--- /dev/null
+--TEST--
+Bug #70895 null ptr deref and segfault with crafted calable
+--FILE--
+<?php
+
+array_map("%n", 0);
+array_map("%n %i", 0);
+array_map("%n %i aoeu %f aoeu %p", 0);
+?>
+--EXPECTREGEX--
+Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n' not found or invalid function name in .+
+
+Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n %i' not found or invalid function name in .+
+
+Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n %i aoeu %f aoeu %p' not found or invalid function name in .+bug70895.php on line \d+
} else {
/* We already checked for plain function before. */
if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
- zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
+ size_t callable_name_len = Z_STRLEN_P(callable), sanitized_callable_name_len = Z_STRLEN_P(callable), k = 0, n = 0;
+ char *callable_name = Z_STRVAL_P(callable), *sanitized_callable_name = emalloc(sizeof(char) * callable_name_len);
+
+ while (k < callable_name_len) {
+ sanitized_callable_name[n] = callable_name[k];
+ if ('%' == callable_name[k]) {
+ n++;
+ sanitized_callable_name[n] = '%';
+ }
+ k++;
+ n++;
+
+ if (n == sanitized_callable_name_len) {
+ sanitized_callable_name_len += callable_name_len - k;
+ sanitized_callable_name = erealloc(sanitized_callable_name, sanitized_callable_name_len);
+ }
+ }
+ sanitized_callable_name[n] = '\0';
+
+ zend_spprintf(error, 0, "function '%s' not found or invalid function name", sanitized_callable_name);
+
+ efree(sanitized_callable_name);
}
return 0;
}