Skip to content

Commit 9a655fc

Browse files
committed
Merge branch 'PHP-5.5' of https://git.php.net/repository/php-src into PHP-5.5
# By Dmitry Stogov (2) and others # Via Adam Harvey (1) and Dmitry Stogov (1) * 'PHP-5.5' of https://git.php.net/repository/php-src: Added function opcache_compile_file() to load PHP scripts into cache without execution. Fixed issue #135 (segfault in interned strings if initial memory is too low) Make message and format arguments const char * to avoid build warning about invalid cast. Copy dba_*() keys before converting to string.
2 parents 9bf997c + 69454d9 commit 9a655fc

File tree

8 files changed

+132
-19
lines changed

8 files changed

+132
-19
lines changed

NEWS

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ PHP NEWS
1313
. Fixed bug #65548 (Comparison for DateTimeImmutable doesn't work).
1414
(Boro Sitnikovski)
1515

16+
- DBA extension:
17+
. Fixed bug #65708 (dba functions cast $key param to string in-place,
18+
bypassing copy on write). (Adam)
19+
1620
- GD
1721
. Ensure that the defined interpolation method is used with the generic
1822
scaling methods. (Pierre)
@@ -22,9 +26,13 @@ PHP NEWS
2226
imap). (ryotakatsuki at gmail dot com)
2327

2428
- OPcache:
29+
. Added function opcache_compile_file() to load PHP scripts into cache
30+
without execution. (Julien)
2531
. Fixed bug #65665 (Exception not properly caught when opcache enabled).
2632
(Laruence)
2733
. Fixed bug #65510 (5.5.2 crashes in _get_zval_ptr_ptr_var). (Dmitry)
34+
. Fixed issue #135 (segfault in interned strings if initial memory is too
35+
low). (Julien)
2836

2937
- SPL:
3038
. Fix bug #64782 (SplFileObject constructor make $context optional / give it

Zend/zend_exceptions.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ ZEND_METHOD(exception, getPrevious)
560560
RETURN_ZVAL(previous, 1, 0);
561561
}
562562

563-
int zend_spprintf(char **message, int max_len, char *format, ...) /* {{{ */
563+
int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ */
564564
{
565565
va_list arg;
566566
int len;
@@ -732,7 +732,7 @@ ZEND_API zend_class_entry *zend_get_error_exception(TSRMLS_D) /* {{{ */
732732
}
733733
/* }}} */
734734

735-
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC) /* {{{ */
735+
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC) /* {{{ */
736736
{
737737
zval *ex;
738738

@@ -760,7 +760,7 @@ ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *messa
760760
}
761761
/* }}} */
762762

763-
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...) /* {{{ */
763+
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...) /* {{{ */
764764
{
765765
va_list arg;
766766
char *message;
@@ -775,7 +775,7 @@ ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long cod
775775
}
776776
/* }}} */
777777

778-
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, char *message, long code, int severity TSRMLS_DC) /* {{{ */
778+
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC) /* {{{ */
779779
{
780780
zval *ex = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
781781
zend_update_property_long(default_exception_ce, ex, "severity", sizeof("severity")-1, severity TSRMLS_CC);

Zend/zend_exceptions.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,20 @@ ZEND_API void zend_register_default_classes(TSRMLS_D);
4040

4141
/* exception_ce NULL or zend_exception_get_default() or a derived class
4242
* message NULL or the message of the exception */
43-
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC);
44-
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...);
43+
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC);
44+
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...);
4545
ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC);
4646
ZEND_API void zend_clear_exception(TSRMLS_D);
4747

48-
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, char *message, long code, int severity TSRMLS_DC);
48+
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC);
4949

5050
extern ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
5151

5252
/* show an exception using zend_error(severity,...), severity should be E_ERROR */
5353
ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC);
5454

5555
/* do not export, in php it's available thru spprintf directly */
56-
int zend_spprintf(char **message, int max_len, char *format, ...);
56+
int zend_spprintf(char **message, int max_len, const char *format, ...);
5757

5858
END_EXTERN_C()
5959

ext/dba/dba.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,17 @@ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free TSRMLS
226226
*key_free = *key_str;
227227
return len;
228228
} else {
229-
*key_free = NULL;
229+
zval tmp = *key;
230+
int len;
230231

231-
convert_to_string(key);
232-
*key_str = Z_STRVAL_P(key);
232+
zval_copy_ctor(&tmp);
233+
convert_to_string(&tmp);
233234

234-
return Z_STRLEN_P(key);
235+
*key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
236+
len = Z_STRLEN(tmp);
237+
238+
zval_dtor(&tmp);
239+
return len;
235240
}
236241
}
237242
/* }}} */
@@ -297,6 +302,14 @@ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free TSRMLS
297302
RETURN_FALSE; \
298303
}
299304

305+
/* the same check, but with a call to DBA_ID_DONE before returning */
306+
#define DBA_WRITE_CHECK_WITH_ID \
307+
if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
308+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform a modification to a database without proper access"); \
309+
DBA_ID_DONE; \
310+
RETURN_FALSE; \
311+
}
312+
300313
/* }}} */
301314

302315
/* {{{ globals */
@@ -557,7 +570,7 @@ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
557570

558571
DBA_FETCH_RESOURCE(info, &id);
559572

560-
DBA_WRITE_CHECK;
573+
DBA_WRITE_CHECK_WITH_ID;
561574

562575
if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
563576
DBA_ID_DONE;
@@ -1110,7 +1123,7 @@ PHP_FUNCTION(dba_delete)
11101123
{
11111124
DBA_ID_GET2;
11121125

1113-
DBA_WRITE_CHECK;
1126+
DBA_WRITE_CHECK_WITH_ID;
11141127

11151128
if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
11161129
{

ext/dba/tests/bug65708.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Bug #65708 (dba functions cast $key param to string in-place, bypassing copy on write)
3+
--SKIPIF--
4+
<?php
5+
require_once(dirname(__FILE__) .'/skipif.inc');
6+
?>
7+
--FILE--
8+
<?php
9+
10+
error_reporting(E_ALL);
11+
12+
require_once(dirname(__FILE__) .'/test.inc');
13+
14+
$db = dba_popen($db_filename, 'c');
15+
16+
$key = 1;
17+
$copy = $key;
18+
19+
echo gettype($key)."\n";
20+
echo gettype($copy)."\n";
21+
22+
dba_exists($key, $db);
23+
24+
echo gettype($key)."\n";
25+
echo gettype($copy)."\n";
26+
27+
dba_close($db);
28+
29+
?>
30+
--CLEAN--
31+
<?php
32+
require(dirname(__FILE__) .'/clean.inc');
33+
?>
34+
--EXPECT--
35+
integer
36+
integer
37+
integer
38+
integer

ext/opcache/ZendAccelerator.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
14461446
}
14471447

14481448
/* zend_compile() replacement */
1449-
static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
1449+
zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
14501450
{
14511451
zend_persistent_script *persistent_script = NULL;
14521452
char *key = NULL;
@@ -2407,14 +2407,14 @@ static inline int accel_find_sapi(TSRMLS_D)
24072407
return FAILURE;
24082408
}
24092409

2410-
static void zend_accel_init_shm(TSRMLS_D)
2410+
static int zend_accel_init_shm(TSRMLS_D)
24112411
{
24122412
zend_shared_alloc_lock(TSRMLS_C);
24132413

24142414
accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals));
24152415
if (!accel_shared_globals) {
24162416
zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
2417-
return;
2417+
return FAILURE;
24182418
}
24192419
ZSMMG(app_shared_globals) = accel_shared_globals;
24202420

@@ -2429,7 +2429,8 @@ static void zend_accel_init_shm(TSRMLS_D)
24292429
ZCSG(interned_strings).arBuckets = zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket *));
24302430
ZCSG(interned_strings_start) = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024));
24312431
if (!ZCSG(interned_strings).arBuckets || !ZCSG(interned_strings_start)) {
2432-
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings");
2432+
zend_accel_error(ACCEL_LOG_FATAL, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings");
2433+
return FAILURE;
24332434
}
24342435
ZCSG(interned_strings_end) = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
24352436
ZCSG(interned_strings_top) = ZCSG(interned_strings_start);
@@ -2468,6 +2469,8 @@ static void zend_accel_init_shm(TSRMLS_D)
24682469
ZCSG(restart_in_progress) = 0;
24692470

24702471
zend_shared_alloc_unlock(TSRMLS_C);
2472+
2473+
return SUCCESS;
24712474
}
24722475

24732476
static void accel_globals_ctor(zend_accel_globals *accel_globals TSRMLS_DC)
@@ -2525,7 +2528,10 @@ static int accel_startup(zend_extension *extension)
25252528
/********************************************/
25262529
switch (zend_shared_alloc_startup(ZCG(accel_directives).memory_consumption)) {
25272530
case ALLOC_SUCCESS:
2528-
zend_accel_init_shm(TSRMLS_C);
2531+
if (zend_accel_init_shm(TSRMLS_C) == FAILURE) {
2532+
accel_startup_ok = 0;
2533+
return FAILURE;
2534+
}
25292535
break;
25302536
case ALLOC_FAILURE:
25312537
accel_startup_ok = 0;

ext/opcache/ZendAccelerator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ int accelerator_shm_read_lock(TSRMLS_D);
325325
void accelerator_shm_read_unlock(TSRMLS_D);
326326

327327
char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC);
328+
zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
328329

329330
#if !defined(ZEND_DECLARE_INHERITED_CLASS_DELAYED)
330331
# define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145

ext/opcache/zend_accelerator_module.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_get_status, 0, 0, 0)
4848
ZEND_ARG_INFO(0, fetch_scripts)
4949
ZEND_END_ARG_INFO()
5050

51+
ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_compile_file, 0, 0, 1)
52+
ZEND_ARG_INFO(0, file)
53+
ZEND_END_ARG_INFO()
54+
5155
ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_invalidate, 0, 0, 1)
5256
ZEND_ARG_INFO(0, script)
5357
ZEND_ARG_INFO(0, force)
@@ -59,12 +63,14 @@ static ZEND_FUNCTION(opcache_invalidate);
5963

6064
/* Private functions */
6165
static ZEND_FUNCTION(opcache_get_status);
66+
static ZEND_FUNCTION(opcache_compile_file);
6267
static ZEND_FUNCTION(opcache_get_configuration);
6368

6469
static zend_function_entry accel_functions[] = {
6570
/* User functions */
6671
ZEND_FE(opcache_reset, arginfo_opcache_none)
6772
ZEND_FE(opcache_invalidate, arginfo_opcache_invalidate)
73+
ZEND_FE(opcache_compile_file, arginfo_opcache_compile_file)
6874
/* Private functions */
6975
ZEND_FE(opcache_get_configuration, arginfo_opcache_none)
7076
ZEND_FE(opcache_get_status, arginfo_opcache_get_status)
@@ -709,3 +715,44 @@ static ZEND_FUNCTION(opcache_invalidate)
709715
RETURN_FALSE;
710716
}
711717
}
718+
719+
static ZEND_FUNCTION(opcache_compile_file)
720+
{
721+
char *script_name;
722+
int script_name_len;
723+
zend_file_handle handle;
724+
zend_op_array *op_array = NULL;
725+
zend_execute_data *orig_execute_data = NULL;
726+
727+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &script_name, &script_name_len) == FAILURE) {
728+
return;
729+
}
730+
731+
if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) {
732+
zend_error(E_NOTICE, ACCELERATOR_PRODUCT_NAME " seems to be disabled, can't compile file");
733+
RETURN_FALSE;
734+
}
735+
736+
handle.filename = script_name;
737+
handle.free_filename = 0;
738+
handle.opened_path = NULL;
739+
handle.type = ZEND_HANDLE_FILENAME;
740+
741+
orig_execute_data = EG(current_execute_data);
742+
743+
zend_try {
744+
op_array = persistent_compile_file(&handle, ZEND_INCLUDE TSRMLS_CC);
745+
} zend_catch {
746+
EG(current_execute_data) = orig_execute_data;
747+
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s" TSRMLS_CC, handle.filename);
748+
} zend_end_try();
749+
750+
if(op_array != NULL) {
751+
destroy_op_array(op_array TSRMLS_CC);
752+
efree(op_array);
753+
RETVAL_TRUE;
754+
} else {
755+
RETVAL_FALSE;
756+
}
757+
zend_destroy_file_handle(&handle TSRMLS_CC);
758+
}

0 commit comments

Comments
 (0)