symfony icon indicating copy to clipboard operation
symfony copied to clipboard

[Cache] RedisTrait doClear with ext-redis int overflow

Open Ahummeling opened this issue 1 year ago • 2 comments

Symfony version(s) affected

4.4-7.x

Description

Since switching to AWS' serverless redis implementation, we've come across some redis scan cursors with values greater than PHP_MAX_INT.

When using phpredis the next bit of the doClear function might result in an integer overflow situation: (Taken from RedisTrait.php at branch 6.4, but the implementation hasn't changed much since 4.4)

$cursor = null;
do {
    $keys = $host->scan($cursor, $pattern, 1000);
    if (isset($keys[1]) && \is_array($keys[1])) {
        $cursor = $keys[0];
        $keys = $keys[1];
    }
    if ($keys) {
        if ($prefixLen) {
            foreach ($keys as $i => $key) {
                $keys[$i] = substr($key, $prefixLen);
            }
        }
        $this->doDelete($keys);
    }
} while ($cursor = (int) $cursor);

afaik php has no userland types that support values that exceed PHP_MAX_INT

Running the scan algorithm using the redis-cli as client, I see the following:

127.0.0.1:56381> scan 0 match finc-9754a4310b0* count 1000
1) "9286422431638129152"
2) (empty array)
127.0.0.1:56381> scan 9286422431638129152 match finc-9754a4310b0* count 1000
1) "9286422431638550784"
2) 1) "finc-9754a4310b0:project_4518"
   2) "finc-9754a4310b0:project_4182"
   3) "finc-9754a4310b0:project_4477"
   4) "finc-9754a4310b0:project_525"
   5) "finc-9754a4310b0:project_874"
   6) "finc-9754a4310b0:project_2878"
127.0.0.1:56381> scan 9286422431638550784 match finc-9754a4310b0* count 1000
1) "9286422431638337280"
2)  1) "finc-9754a4310b0:project_2785"
    2) "finc-9754a4310b0:project_3752"
    3) "finc-9754a4310b0:project_2676"
    4) "finc-9754a4310b0:project_3592"
    5) "finc-9754a4310b0:project_2881"
    6) "finc-9754a4310b0:person_3791"
    7) "finc-9754a4310b0:project_1682"
    8) "finc-9754a4310b0:project_94"
    9) "finc-9754a4310b0:project_1002"
   10) "finc-9754a4310b0:FilterOptionsCache^18^Invoice_all"

Scouring the internet for related issues, the most relevant one seemed to be this one: https://github.com/phpredis/phpredis/issues/2454 Attached are the PR's that fix part of the issue in the underlying implementation.

I believe by casting the cursor to string, we are triggering an overflow. This is supported by the fact that the doClear functions seems to have no effect whatsoever on our redis database.

How to reproduce

I don't understand redis well enough to be able to provide a reproducer for a redis database that yields these super high cursor values.

Possible Solution

I guess if we remove the cast to int, we might already be there.

Additional Context

No response

Ahummeling avatar Apr 29 '24 15:04 Ahummeling

Additionally, I'd be very happy to work on this issue and provide a PR. I just want to double check that I'm not seeing things that aren't really there

Ahummeling avatar Apr 29 '24 15:04 Ahummeling

Please send a PR yes. Dunno why we have this cast to int honestly. Let's remove it.

nicolas-grekas avatar Apr 29 '24 16:04 nicolas-grekas