June 1, 2021·4 min read·engineeringvalkeyredissecuritymemory

Redis 6.2.4 completes the LCS allocation-overflow correction

Redis 6.2.4 adds input-length and allocation checks for STRALGO LCS after an incomplete earlier repair. The source separates representable dimensions, byte-size overflow and allocation failure.

Widening a multiplication does not by itself establish that an allocation expression is safe. Redis 6.2.4 revisits STRALGO LCS after the earlier integer-overflow repair proved incomplete. The new correction checks input lengths, computes the table size in a wider type and verifies the byte allocation before using it. These checks address different points where the intended dimensions can cease to match the storage obtained.

The 6.2 release notes date the release to June 1. The project advisory published that day identifies CVE-2021-32625 and explicitly describes it as the result of the incomplete CVE-2021-29477 fix. It names 6.2.4 and 6.0.14 as patched versions. The consequence remains possible heap corruption and remote code execution through the affected command.

I have used Redis since its early releases, and I value a correction whose implementation explains what the earlier patch omitted. This is an allocation problem with several independent constraints. The command's intermediate matrix needs a representable number of cells, a representable byte size and an allocation that actually succeeds.

Input lengths must fit the algorithm's representation

The 6.2.3-to-6.2.4 patch adds a check before converting string lengths into the variables used by the LCS algorithm. It rejects either input at or beyond UINT32_MAX - 1. The source comment identifies truncation and later overflow as the reasons for this guard.

The algorithm stores input lengths and iteration variables in 32-bit unsigned types. A string length available from the underlying string representation cannot simply be assigned to that narrower type without considering its range. The new check establishes a limit before the subsequent dimension arithmetic uses those variables.

The dimensions include one extra position for an empty prefix. That addition is part of the storage calculation, so checking only that the original length fits would not account for every arithmetic step. The source places the rejection before computing the matrix dimensions. This makes the accepted input range explicit within the implementation.

An error from this guard reports that the string is too long for LCS. It is different from the error used when the matrix cannot be allocated. That distinction tells a caller whether the request exceeds the algorithm's accepted representation or fails the subsequent storage step.

Cell count and byte count are checked separately

The 6.2.4 string-command source computes the number of matrix entries using unsigned long long. A comment connects the multiplication's safety to the earlier input limits. This is a dependency between checks, not a claim that any multiplication in that type is automatically safe.

The implementation then multiplies the entry count by sizeof(uint32_t) to obtain a byte count. Before allocation, it compares the result with SIZE_MAX and divides the calculated byte size by the entry count to verify that the expected element width survives. This inverse check detects a wrapped multiplication that no longer corresponds to the intended number of entries.

Only after those conditions pass does the code attempt allocation. It uses ztrymalloc, and a null result becomes an insufficient-memory error. The same error path also covers a size that fails the preceding allocation checks. The code does not proceed to populate the table without obtaining suitable storage.

These stages explain the follow-up more clearly than describing it as another cast. The earlier version already cast an operand to size_t before multiplying dimensions. The new implementation introduces a guard on the incoming lengths and checks both the calculated storage size and the allocation outcome. Its reasoning spans the complete transition from strings to a matrix buffer.

These checks do not replace the dynamic-programming algorithm. The source still builds the table from both string lengths before producing the requested reply. A length-only answer therefore retains the intermediate matrix and its allocation requirements.

A narrow mitigation has explicit prerequisites

The advisory also supplies mitigations. Restricting access to STRALGO LCS through ACLs prevents clients from invoking the affected operation. For 64-bit systems already carrying the earlier fix, it additionally identifies keeping proto-max-bulk-len below 2 GB as sufficient mitigation for this issue. The default is 512 MB.

Those conditions belong together. The bulk-length guidance is qualified by platform width and the presence of the previous correction. It should not be generalized to every older Redis binary. Restricting command access and applying the new release are different ways to change exposure, and the advisory describes their scope.

I find the source useful for understanding why configuration and platform details appear in that advice. Input sizes meet several arithmetic representations before storage is allocated. A mitigation that constrains one boundary can depend on protections already present at another. The advisory's qualifications correspond to that layered implementation problem.

The maintenance release also repairs lifecycle edges

The tagged release notes contain other corrections, including a crash after terminating a diskless-replication child and a crash when unlinking a stream whose consumer groups have been deleted. They also enforce the client-output-buffer soft limit when no traffic arrives. These address lifecycle conditions separate from the LCS allocation.

The tag's release header contains a month typo, saying July where the maintained branch notes and June 1 advisory establish June. Its technical list still describes this release. Using the corroborated June date avoids moving the event merely because one checked-in header has an incorrect month.

Another listed improvement hides authentication passwords in MIGRATE commands from the slow log. That concerns retained diagnostic information, whereas the LCS repair concerns memory sizing before a computation. Both are included in the patch, but they should retain separate explanations.

The LCS correction establishes a more explicit failure path for oversized or unallocatable work. Input lengths must fit the algorithm's representation, calculated bytes must correspond to the intended cell count and the allocation must succeed. The table-building loops run only after those conditions have been satisfied.