Skip to content

[Cache] RedisTrait doClear with ext-redis int overflow #54773

@Ahummeling

Description

@Ahummeling

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: phpredis/phpredis#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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions