Valkey repairs HyperLogLog bounds and connection acceptance
Valkey 8.1.3 fixes CVE-2025-32023 in HyperLogLog processing and CVE-2025-48367 in connection acceptance. The corrections protect two different boundaries in the server.
A compact encoding can describe more output than its decoder has room to store. Valkey's HyperLogLog implementation uses run-length encoding for sparse data, so each decoded run must stay within the fixed register count. Today's Valkey 8.1.3 release repairs missing checks in that processing as CVE-2025-32023. It also fixes connection starvation associated with transient accept errors, identified as CVE-2025-48367.
Maintainers recommend applying the security release as soon as possible. The two fixes have different prerequisites and consequences, which matter when explaining their urgency. A malformed data representation reaching a decoder and a failed connection obstructing other pending connections are separate failure paths.
I default to Valkey where Redis semantics are needed, and these corrections affect the implementation behind that familiar interface. A compatible command set does not eliminate the need to validate encoded data or interpret operating-system errors correctly. Both responsibilities remain inside the server process.
Sparse data needs a bounded logical position
The 8.1.3 HyperLogLog implementation represents dense registers directly and sparse registers as runs. Sparse entries can describe a sequence of zeros or a short sequence of equal nonzero values. Decoding advances a logical register position by the length of each run, even when the encoded input occupies only a few bytes.
The relevant safety question is whether the next run fits in the remaining logical capacity. Checking the byte pointer against the end of the encoded string establishes a different property. A decoder can remain within the input string while accepting run lengths whose expanded result exceeds the register array. Both input consumption and expanded position require validation.
Comparing the previous released implementation with the new one shows the added checks. Sparse-to-dense conversion now validates zero runs as well as value runs. Histogram processing and merging receive corresponding checks, and the code carries an explicit validity flag into its final result.
That flag addresses another subtle condition. Ending with a register index equal to the expected total does not necessarily prove that every earlier step was valid. A decoder needs to preserve the fact that it encountered an invalid run when it stops. The final success test can then require both a valid traversal and the expected total register count.
This is why checking only at the end of expansion is insufficient. Any write beyond a destination's bounds has already happened by the time the routine examines its final index. The size check must precede the update or write whose safety depends on it. The patch applies that ordering across the affected decoding paths.
The implementation's sparse representation is an optimization for datasets with many zero registers. It trades decoding work for a smaller stored representation. The vulnerability does not mean that compact representations are inherently unsuitable. It means the decoder must validate the relationship between each encoded run and the fixed logical structure it represents.
A useful way to read this change is to separate representation length from represented length. The former is the number of bytes available to the parser. The latter is the number of register positions those bytes claim to describe. Run-length encoding deliberately allows a small input to represent many positions, so validating only the former leaves the central expansion invariant unproved. The added checks enforce that invariant before the decoder updates its position.
The advisory distinguishes authentication from memory safety
The Redis advisory for the same HyperLogLog CVE, published on July 6, describes an authenticated user supplying a specially crafted string. It identifies out-of-bounds writes and possible remote code execution. That provides context for the shared defect without turning Redis's version statements into claims about Valkey's release branches.
The authenticated prerequisite is material. It distinguishes this issue from a pre-authentication network defect. Authentication establishes who may issue commands, but a permitted command still needs to process its input safely. A user allowed to operate on a data structure should not thereby gain the ability to corrupt the native process implementing it.
The advisory also describes restricting HyperLogLog commands through ACLs as a mitigation. That is a reduction in access to the affected operations, with an application-visible cost for workloads that use them. It is not equivalent to repairing the decoder. The release distributes the implementation correction so valid HyperLogLog operations can continue through the repaired path.
The distinction helps explain what an upgrade changes. An application does not need a new cardinality-estimation API to benefit. Existing commands operate through code that now checks the expanded representation's bounds. The correction concerns accepting and processing the stored representation, rather than a change in the mathematical purpose of the data structure.
One failed accept must not obstruct other clients
The connection-error advisory describes an unauthenticated connection causing repeated IP protocol errors, leading to client starvation and denial of service. This defect acts before normal database command authorization. Credentials cannot protect an operation which the server must perform to establish a connection in the first place.
Valkey's patch in pull request 2315 adds a helper that identifies transient errors for which acceptance should continue. It treats an aborted connection as retryable. On Linux it also recognizes a set of pending network errors which the operating system can return through accept.
The call sites change the accept loop's response to those errors. Instead of returning immediately, they continue trying to accept other connections. The patch applies this handling to ordinary sockets, TLS, Unix-domain sockets and the cluster connection path. The shared helper keeps the error classification consistent across those entry points.
An aborted connection is not proof that the listening socket has no other useful work. A peer can begin a connection and disappear before the server accepts it. The server needs to distinguish that per-connection failure from a condition that should end the current accept attempt. Otherwise one unsuccessful pending connection can interfere with unrelated clients waiting behind it.
The repair retains bounded accept loops at the call sites. Retrying a recognized error therefore means continuing the existing connection-processing work, not introducing an unbounded busy loop. That detail matters because indiscriminately repeating every failed system call could create a different availability problem.
The released accept helper also makes the platform distinction explicit. Some error classification is conditional on Linux, while the aborted-connection case is handled independently. Portable network software cannot assume identical failure reporting across operating systems merely because the socket interface has the same function name.
I find the two repairs useful to consider together because they correct different assumptions about progress. Consuming another encoded byte does not prove that a decoded run fits. Receiving an accept error does not prove that other pending connections should wait. In both cases the implementation needs the more specific condition before it advances or stops.
Replies belong to individual commands
The release's other listed fix addresses a missing AUTH error reply inside transactions. Pull request 2287 explains that module authentication can supply its own reply or return an error object for the caller to report. The previous check looked for any pending replies on the client, which can include replies belonging to earlier commands in a pipeline or transaction.
The replacement checks whether the current command has buffered a reply. That is the property needed to avoid adding a duplicate while still supplying a missing error. A connection-level queue contains output from multiple operations, so its nonempty state cannot establish that one particular operation has already responded.
This correction has a practical protocol consequence. A client associates replies with the commands it sent. Suppressing one command's response because an earlier command already has queued output can break that correspondence. The patch's regression test exercises an AUTH error inside MULTI and EXEC, making the required reply observable at the client interface.
Valkey 8.1.3 changes these internal decisions without asking applications to adopt a new data model. Decoders reject invalid expansion, accept loops continue past recognized transient errors, and authentication error handling checks the current command's reply state. The security fixes determine upgrade priority, while the source changes establish the specific behavior the patch corrects.