Crocoblock / suggestions

The suggestions for CrocoBlock project
196 stars 79 forks source link

Infinite loop with 100% CPU usage, in JetEngine's query builder preview #7818

Open aayla-secura opened 1 month ago

aayla-secura commented 1 month ago

Overview

There is a severe bug in JetEngine's query builder's preview functionality when previewing from specific page and the Wordpress permalink settings are set to plain.

Results in an infinite loop with 100% CPU usage that requires a server reboot.

Steps to reproduce

1. Ensure that the permalink settings are set to plain

In Wordpress dashboard > Settings > Permalink. They are plain by default.

2. Create a query in the query builder, any kind of query

3. Enable preview and choose a post or page (any post or page) as the "Preview from page"

4. Loop happens and CPU usage spikes to 100%

The preview results hangs, the docker container's CPU usage immediately spikes to 100% and the debug error log shows unstopping logging of the following line:

PHP Warning: Constant REST_REQUEST already defined in /var/www/html/wp-includes/rest-api.php on line 410

Tens of thousands of this entry within a couple of seconds, and I have to force shutdown the container. It happens every time I try to preview the results.

Video showing this on a completely clean latest Wordpress install inside Docker

https://www.youtube.com/watch?v=_Z-_nZt2Uvw

Why and when it happens

Firstly, when the permalink settings are set to Plain, this will make Wordpress switch from using wp-json to ?rest_route for the API. See the yellow warning box on this documentation page

As a result the preview results will now use index.php?rest_route=%2Fjet-engine%2Fv2%2Fupdate-query-preview instead of wp-json/jet-engine/v2/update-query-preview, this causes the loop.

In particular, I found (by adding some debug output statements) that it loops on line 110 in includes/components/query-builder/rest-api/update-preview.php:

$wp->parse_request();

And the reason it happens when using ?rest_route is because lines 102 to 105, make the assumption that the URL will include wp-json:

$_SERVER['REQUEST_URI'] = preg_replace(
    '/wp-json\/.*/',
    ltrim( $preview['page_url'], '/' ),
    $_SERVER['REQUEST_URI']
);

And when it doesn't, the URL remains unchanged and $wp->parse_request(); loops back to the update-query-preview handler.

I don't have a patch, unfortunately though.