|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-12-23 08:38 UTC] andrew at jmpesp dot org
Description:
------------
Supplying a large negative number as the second parameter to round() reliably produces a segmentation fault. Tested on Linux with both v7.0.0 and v5.6.16. This issue appears to only affect 64-bit builds.
Due to the limited range of values which cause a crash I do not believe this issue is exploitable. However given the nature of the crash (out of bounds read) I am classifying this as "security" just in case. I'll let you smart people make that call.
Here's some gdb output that may be helpful to you...
====================================================
(gdb) r -r 'echo round(1.0, -2147483648);'
Starting program: /tmp/php-7.0.1/sapi/cli/php -r 'echo round(1, -2147483648);'
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x0000000000628fe7 in php_intpow10 (power=-2147483648) at /tmp/php-7.0.1/ext/standard/math.c:93
93 return powers[power];
(gdb) i r
rax 0xffffffff80000000 -2147483648
rbx 0x80000000 2147483648
rcx 0xb5f5c0 11924928
rdx 0xb5f500 11924736
rsi 0x9 9
rdi 0x80000000 2147483648
rbp 0x1 0x1
rsp 0x7fffffffc8c0 0x7fffffffc8c0
r8 0x0 0
r9 0x0 0
r10 0x1 1
r11 0x1 1
r12 0xe 14
r13 0x7ffff60120a0 140737320657056
r14 0x7ffff6012030 140737320656944
r15 0x7ffff6070360 140737321042784
rip 0x628fe7 0x628fe7 <_php_math_round+279>
eflags 0x10a12 [ AF IF OF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) x/1i $rip
=> 0x628fe7 <_php_math_round+279>: movsd xmm5,QWORD PTR [rdx+rax*8]
(gdb) bt
#0 0x0000000000628fe7 in php_intpow10 (power=-2147483648) at /tmp/php-7.0.1/ext/standard/math.c:93
#1 _php_math_round (value=1, places=-2147483648, mode=1) at /tmp/php-7.0.1/ext/standard/math.c:152
#2 0x0000000000629916 in zif_round (execute_data=0x7ffff60120a0, return_value=0x7ffff6012090) at /tmp/php-7.0.1_32/ext/standard/math.c:408
#3 0x000000000071796d in ZEND_DO_ICALL_SPEC_HANDLER () at /tmp/php-7.0.1/Zend/zend_vm_execute.h:586
#4 0x0000000000708e0b in execute_ex (ex=<optimized out>) at /tmp/php-7.0.1/Zend/zend_vm_execute.h:414
#5 0x000000000075ad47 in zend_execute (op_array=op_array@entry=0x7ffff607c000, return_value=return_value@entry=0x7fffffffca50)
at /tmp/php-7.0.1/Zend/zend_vm_execute.h:458
#6 0x00000000006beb77 in zend_eval_stringl (str=0x7ffff6012030 "`\003\a\366\377\177", str@entry=0xec02a0 "echo round(1, -2147483648);",
str_len=<optimized out>, retval_ptr=retval_ptr@entry=0x0, string_name=string_name@entry=0xb853df "Command line code")
at /tmp/php-7.0.1/Zend/zend_execute_API.c:1125
#7 0x00000000006bec49 in zend_eval_stringl_ex (str=str@entry=0xec02a0 "echo round(1, -2147483648);", str_len=<optimized out>,
retval_ptr=retval_ptr@entry=0x0, string_name=string_name@entry=0xb853df "Command line code", handle_exceptions=handle_exceptions@entry=1)
at /tmp/php-7.0.1/Zend/zend_execute_API.c:1166
#8 0x00000000006becb9 in zend_eval_string_ex (str=str@entry=0xec02a0 "echo round(1, -2147483648);", retval_ptr=retval_ptr@entry=0x0,
string_name=string_name@entry=0xb853df "Command line code", handle_exceptions=handle_exceptions@entry=1)
at /tmp/php-7.0.1/Zend/zend_execute_API.c:1177
#9 0x000000000075c76c in do_cli (argc=3, argv=0xec0220) at /tmp/php-7.0.1/sapi/cli/php_cli.c:1005
#10 0x0000000000429718 in main (argc=3, argv=0xec0220) at /tmp/php-7.0.1/sapi/cli/php_cli.c:1345
(gdb)
Test script:
---------------
<?php
echo round(1.0, -2147483648);
?>
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Nov 05 23:00:01 2025 UTC |
The Linux pow() function seems to be sensitive to the overflowed values. Please check the patch below (against 7.0) diff --git a/ext/standard/math.c b/ext/standard/math.c index 6059f3d..e79817e 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -390,7 +390,11 @@ PHP_FUNCTION(round) } if (ZEND_NUM_ARGS() >= 2) { - places = (int) precision; + if (precision >= 0) { + places = precision > INT_MAX ? INT_MAX : (int)precision; + } else { + places = precision <= INT_MIN ? INT_MIN+1 : (int)precision; + } } convert_scalar_to_number_ex(value); Thanks