php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81226 Integer overflow behavior is different with JIT enabled
Submitted: 2021-07-06 00:39 UTC Modified: 2021-07-21 12:20 UTC
From: smokey101stair at gmail dot com Assigned: dmitry (profile)
Status: Closed Package: JIT
PHP Version: 8.0.8 OS: Ubuntu 20.04
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: smokey101stair at gmail dot com
New email:
PHP Version: OS:

 

 [2021-07-06 00:39 UTC] smokey101stair at gmail dot com
Description:
------------
When $characterReferenceCode overflows in the test script with the JIT enabled, sometimes it evaluates to 65 and other times it evaluates to 1.844674407371E+19. The expected value is 1.844674407371E+19.

With opcache.jit_debug=1 I get the following:

TRACE-1$/home/trevor/jit_test2.php$9: ; (unknown)
        mov $EG(jit_trace_num), %rax
        mov $0x1, (%rax)
        mov $EG(vm_stack_end), %rax
        mov (%rax), %rcx
        mov $EG(vm_stack_top), %rax
        sub (%rax), %rcx
        cmp $0x60, %rcx
        jb jit$$trace_exit_0
.L1:
        cmp $0x4, 0x88(%r14)
        jnz jit$$trace_exit_1
        cmp $0x4, 0x98(%r14)
        jnz jit$$trace_exit_1
        mov 0x80(%r14), %rax
        cmp 0x90(%r14), %rax
        jge jit$$trace_exit_2
        cmp $0x4, 0x78(%r14)
        jnz jit$$trace_exit_3
        mov 0x70(%r14), %rax
        shl $0x4, %rax
        jo .L6
        mov %rax, 0x70(%r14)
.L2:
        mov $EG(vm_stack_top), %r15
        mov (%r15), %r15
        mov $EG(vm_stack_top), %rdx
        add $0x60, (%rdx)
        mov $0x0, 0x28(%r15)
        mov $0x5572643c6590, %rcx
        mov %rcx, 0x18(%r15)
        mov $0x0, 0x20(%r15)
        mov $0x1, 0x2c(%r15)
        cmp $0x6, 0x58(%r14)
        jnz jit$$trace_exit_4
        cmp $0x4, 0x88(%r14)
        jnz jit$$trace_exit_4
        mov $0x409da8e0, (%r14)
        mov 0x50(%r14), %rdi
        mov 0x80(%r14), %rsi
        mov $zend_jit_fetch_dim_str_offset_r_helper, %rax
        call *%rax
        mov %rax, 0xa0(%r14)
        mov $0x6, 0xa8(%r14)
        mov $EG(exception), %rax
        cmp $0x0, (%rax)
        jnz JIT$$exception_handler
        cmp $0x6, 0xa8(%r14)
        jnz jit$$trace_exit_6
        mov 0xa0(%r14), %rdx
        mov %rdx, 0x50(%r15)
        mov 0xa8(%r14), %eax
        mov %eax, 0x58(%r15)
        mov $0x409da920, (%r14)
        mov %r14, 0x30(%r15)
        lea 0xb0(%r14), %rsi
        mov $0x1, 0x8(%rsi)
        mov $EG(current_execute_data), %rcx
        mov %r15, (%rcx)
        mov %r15, %rdi
        mov $0x557262a8e270, %rax
        call *%rax
        mov $EG(current_execute_data), %rax
        mov %r14, (%rax)
        test $0x1, 0x59(%r15)
        jnz .L7
.L3:
        mov $EG(vm_stack_top), %rax
        mov %r15, (%rax)
        mov $EG(exception), %rax
        cmp $0x0, (%rax)
        jnz JIT$$icall_throw
        mov $EG(vm_interrupt), %rax
        cmp $0x0, (%rax)
        jnz jit$$trace_exit_7
        mov 0xb0(%r14), %rax
        sub $0x30, %rax
        jo jit$$trace_exit_8
        mov %rax, 0xa0(%r14)
        mov $0x4, 0xa8(%r14)
        cmp $0x4, 0x78(%r14)
        jnz jit$$trace_exit_9
        mov 0x70(%r14), %rax
        add 0xa0(%r14), %rax
        jo .L8
        mov %rax, 0x70(%r14)
.L4:
        cmp $0x4, 0x88(%r14)
        jnz jit$$trace_exit_10
        add $0x1, 0x80(%r14)
        jo .L9
.L5:
        mov $EG(vm_interrupt), %rax
        cmp $0x0, (%rax)
        jz .L1
        jmp jit$$trace_exit_11
.L6:
        vxorps %xmm0, %xmm0, %xmm0
        vcvtsi2sd 0x70(%r14), %xmm0, %xmm0
        mov $0x10, %rax
        vxorps %xmm1, %xmm1, %xmm1
        vcvtsi2sd %rax, %xmm1, %xmm1
        vmulsd %xmm1, %xmm0, %xmm0
        vmovsd %xmm0, 0x70(%r14)
        mov $0x5, 0x78(%r14)
        jmp .L2
.L7:
        mov 0x50(%r15), %rdi
        sub $0x1, (%rdi)
        jnz .L3
        mov $0x409da920, (%r14)
        mov $rc_dtor_func, %rax
        call *%rax
        jmp .L3
.L8:
        vxorps %xmm0, %xmm0, %xmm0
        vcvtsi2sd 0x70(%r14), %xmm0, %xmm0
        vxorps %xmm1, %xmm1, %xmm1
        vcvtsi2sd 0xa0(%r14), %xmm1, %xmm1
        vaddsd %xmm1, %xmm0, %xmm0
        vmovsd %xmm0, 0x70(%r14)
        mov $0x5, 0x78(%r14)
        jmp .L4
.L9:
        mov $0x43e0000000000000, %rax
        mov %rax, 0x80(%r14)
        mov $0x5, 0x88(%r14)
        jmp .L5

Test script:
---------------
<?php

// 65-bit hexadecimal number
$hex = '10000000000000041';

for ($i = 0; $i < 200; ++$i) {
    $characterReferenceCode = 0;

    for ($j = 0, $len = strlen($hex); $j < $len; ++$j) {
        $characterReferenceCode *= 16;
        $characterReferenceCode += ord($hex[$j]) - 0x0030;
    }

    assert($characterReferenceCode > 0x10FFFF);
}



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-07-06 12:59 UTC] nikic@php.net
This one doesn't reproduce for me.
 [2021-07-06 13:54 UTC] smokey101stair at gmail dot com
Are you able to reproduce if you increase the iterations from 200 to 20000? If not, I'll have to recheck it when I get home. Is there any other info I can provide to help debug this?
 [2021-07-07 00:02 UTC] smokey101stair at gmail dot com
Perhaps you will have better luck reproducing when it is extracted into a function, which also reproduces the issue for me

<?php

// 65-bit hexadecimal number
$hex = '10000000000000041';

function getNumericReference(string $hex) {
    $characterReferenceCode = 0;

    for ($j = 0, $len = strlen($hex); $j < $len; ++$j) {
        $characterReferenceCode *= 16;
        $characterReferenceCode += ord($hex[$j]) - 0x0030;
    }

    return $characterReferenceCode;
}

for ($i = 0; $i < 20000; ++$i) {
    assert(getNumericReference($hex) > 0x10FFFF);
}
 [2021-07-12 13:15 UTC] hao dot sun at arm dot com
I can reproduce this bug in my local environment even with functional JIT.

I noticed that this bug doesn't occur in JIT/x86 on master branch.
After bisect, I guess the root cause is that the following patches in master branch are not merged to PHP-8.0.*.

https://github.com/php/php-src/commit/5e05c70ee727815805697a90b39f4d82cd4b4d3d#diff-c0fa9f6cbf84b02388699bafb28a11d7f69780bbf2b0e1bceea4cb99763c1328
https://github.com/php/php-src/commit/186a5277aa237b1f98cd0a74f43c535b8958f85b#
 [2021-07-20 19:02 UTC] smokey101stair at gmail dot com
Is there anything blocking the back-porting of these 2 commits?
 [2021-07-21 12:20 UTC] nikic@php.net
-Assigned To: +Assigned To: dmitry
 [2021-07-21 16:29 UTC] git@php.net
Automatic comment on behalf of dstogov
Revision: https://github.com/php/php-src/commit/053c56f52e094bcf57958e0d4e71c0c4e3f9a2b2
Log: Fixed bug #81226 (Integer overflow behavior is different with JIT enabled)
 [2021-07-21 16:29 UTC] git@php.net
-Status: Assigned +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Oct 27 16:01:27 2024 UTC