php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74623 Infinite loop in type inference when using HTMLPurifier
Submitted: 2017-05-21 11:45 UTC Modified: 2017-06-07 22:53 UTC
Votes:8
Avg. Score:4.6 ± 0.5
Reproduced:7 of 8 (87.5%)
Same Version:7 (100.0%)
Same OS:4 (57.1%)
From: lkebin at gmail dot com Assigned:
Status: Closed Package: opcache
PHP Version: 7.1.5 OS: CentOS 6.9
Private report: No CVE-ID:
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: lkebin at gmail dot com
New email:
PHP Version: OS:

 

 [2017-05-21 11:45 UTC] lkebin at gmail dot com
Description:
------------
When the php run the code which invoke HTMLPurifier, The php-fpm or php cli processes CPU usage 100%, The php-fpm will occur Nginx response 504 (time out). When I run `php HTMLPurifier.standalone.php`, the process CPU usage to 100% and can not be exit normally. I need force kill it.

The problem occur php 7.1.5/7.1.4 (I tested versions on my virtual machine). Also I tested php 7.0.19, No problem with it.


I compiled the official released version:

./configure --enable-debug
make

Changed opcache.enable_cli=1 in the php.ini-development, and loaded opcache.so file from php-src/modules/ directory.

Run the script

./sapi/cli/php -c ~/HTMLPurifier.standalone.php


The gdb backtrace 

---- gdb backtrace ----

(gdb) bt
#0  0x00007ffff63b2495 in raise (sig=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007ffff63b3c75 in abort () at abort.c:92
#2  0x00007ffff63ab60e in __assert_fail_base (
    fmt=<value optimized out>, assertion=0x7fffef950328 "0",
    file=0x7fffef950268 "/root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c", line=<value optimized out>,
    function=<value optimized out>) at assert.c:96
#3  0x00007ffff63ab6d0 in __assert_fail (assertion=0x7fffef950328 "0",
    file=0x7fffef950268 "/root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c", line=1902,
    function=0x7fffef950cb0 "check_type_narrowing") at assert.c:105
#4  0x00007fffef92a210 in check_type_narrowing (
    op_array=0x7fffe74f06f8, ssa=0x7fffe7216700,
    worklist=0x7fffffffa700, var=37, old_type=402653444,
    new_type=411040760)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c:1902
#5  0x00007fffef939041 in zend_update_type_info (
    op_array=0x7fffe74f06f8, ssa=0x7fffe7216700, script=0x7ffff5a7a000,
    worklist=0x7fffffffa700, i=44)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c:3113
#6  0x00007fffef93b810 in zend_infer_types_ex (op_array=0x7fffe74f06f8,
    script=0x7ffff5a7a000, ssa=0x7fffe7216700, worklist=0x7fffffffa700)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c:3332
#7  0x00007fffef93d743 in zend_infer_types (op_array=0x7fffe74f06f8,
    script=0x7ffff5a7a000, ssa=0x7fffe7216700)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c:3811
#8  0x00007fffef93dbae in zend_ssa_inference (arena=0x7fffffffa860,
    op_array=0x7fffe74f06f8, script=0x7ffff5a7a000, ssa=0x7fffe7216700)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/zend_inference.c:3876
#9  0x00007fffef914839 in zend_dfa_analyze_op_array (
---Type <return> to continue, or q <return> to quit---
    op_array=0x7fffe74f06f8, ctx=0x7fffffffa860, ssa=0x7fffe7216700,
    flags=0x7fffe72166fc)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/dfa_pass.c:106
#10 0x00007fffef8feae5 in zend_optimize_script (script=0x7ffff5a7a000,
    optimization_level=2147467263, debug_level=0)
    at /root/download/php-7.1.5/ext/opcache/Optimizer/zend_optimizer.c:993
#11 0x00007fffef8dab79 in cache_script_in_shared_memory (
    new_persistent_script=0x7ffff5a7a000,
    key=0x1126d90 "/root/HTMLPurifier.standalone.php", key_length=33,
    from_shared_memory=0x7fffffffaaa0)
    at /root/download/php-7.1.5/ext/opcache/ZendAccelerator.c:1273
#12 0x00007fffef8dc5ad in persistent_compile_file (
    file_handle=0x7fffffffe030, type=8)
    at /root/download/php-7.1.5/ext/opcache/ZendAccelerator.c:1865
#13 0x000000000087b325 in zend_execute_scripts (type=8, retval=0x0,
    file_count=3) at /root/download/php-7.1.5/Zend/zend.c:1470
#14 0x00000000007e54a6 in php_execute_script (
    primary_file=0x7fffffffe030)
    at /root/download/php-7.1.5/main/main.c:2537
#15 0x000000000096f87a in do_cli (argc=4, argv=0x1126cf0)
    at /root/download/php-7.1.5/sapi/cli/php_cli.c:993
#16 0x00000000009707b9 in main (argc=4, argv=0x1126cf0)
    at /root/download/php-7.1.5/sapi/cli/php_cli.c:1381

Test script:
---------------
https://gist.github.com/lkebin/e25594cfd493e984054686a7cd2ec4b8

Expected result:
----------------
From php cli to run the test script should be empty output and exit 0


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-05-22 03:08 UTC] lkebin at gmail dot com
Run the script should be 

./sapi/cli/php -c ./php.ini-development ~/HTMLPurifier.standalone.php
 [2017-06-03 01:02 UTC] ezyang@php.net
Xiphin reports that the following patch to HTML Purifier solves the problem. Maybe this will help diagnose the opcode problem: https://github.com/ezyang/htmlpurifier/pull/137
 [2017-06-03 01:38 UTC] Xiphin at qq dot com
https://gist.github.com/lkebin/e25594cfd493e984054686a7cd2ec4b8
You can fix it by follow:
line 14727: change "$current_li = false;" to "$current_li = null;"
line 14748: change "if ($current_li === false) {" to "if ($current_li === null) {"
 [2017-06-07 22:39 UTC] phpbugs at ackermann dot ca
Hello,

just run into this bug. The boil down version is a file with the following content. Opening or including the file results in 100% CPU load.

<?php

function crash($arr) {
    $current_item = false;

    foreach($arr as $item) {
        $current_item = $item;
        $current_item->a[] = '';
    }

}
 [2017-06-07 22:45 UTC] phpbugs at ackermann dot ca
Wrong test code posted before. This one should do it.

<?php

function crash($arr) {
    $current_item = false;

    foreach($arr as $item) {
        if($item->name === 'string') {
            $current_item = $item;
        } else {
            $current_item->a[] = '';
        }
    }

}
 [2017-06-07 22:54 UTC] nikic@php.net
-Summary: Invoke HTMLPurifier occur CPU 100% +Summary: Infinite loop in type inference when using HTMLPurifier -Status: Open +Status: Verified
 [2017-06-23 15:34 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=5b5a92b8b6d96b8fbd8557645801ae99310cab2b
Log: Fixed bug #74623
 [2017-06-23 15:35 UTC] nikic@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Mon Jul 24 10:01:45 2017 UTC