Redis repairs native buffer arithmetic in Lua serialization
Redis 7.0.12 fixes heap-overflow risks in Lua's cjson and cmsgpack libraries. The patch changes length types and validates allocation arithmetic before growing native buffers.
A scripting environment can restrict which database operations a program performs while still depending on native code to serialize its values. Redis's July security release fixes that lower-level boundary. A specially crafted Lua script could trigger heap overflow in the bundled cjson and cmsgpack libraries, causing heap corruption and potentially remote code execution.
The 7.0 release notes date Redis 7.0.12 to July 10 and identify CVE-2022-24834. The project advisory says the issue affects versions with Lua scripting support starting at Redis 2.6. It also states the access condition, which is an authenticated and authorized user executing a script.
I have used Redis since its early releases, and I find server-side scripting useful for operations that need to execute beside the data. That usefulness makes the native dependencies part of the database's security model. A program written in Lua can reach code that manages C buffers, so restricting the language alone cannot establish memory safety for the entire execution path.
Serialization expands the input representation
The changes between 7.0.11 and 7.0.12 modify the bundled serializers and their string-buffer helper. In cjson, appending a string reserves enough capacity for its escaped representation. That reserve uses a multiple of the source length plus space for the surrounding string representation.
The allocation requirement therefore differs from the original string length. Some characters need escape sequences in JSON. A safe calculation must account for the expanded output before writing it, while also ensuring that the multiplication and addition used to reserve that space remain representable.
The patched cjson source checks the input length against a bound derived from SIZE_MAX before calculating the reserve. The relevant expression uses six times the input length plus additional bytes. Checking the multiplication's domain first prevents that reserve calculation from silently wrapping to a smaller value.
The same file changes token indices and string lengths from int to size_t. Its encoder output length also becomes size_t. These changes align the representation of byte lengths with the types used for memory sizes, reducing conversions through a narrower signed integer.
Changing a type does not by itself make arithmetic safe. An unsigned size type can wrap too. The explicit precondition before the reserve calculation is therefore part of the repair, alongside using a more suitable type for the lengths that move through the serializer.
The shared buffer checks its own growth
The string-buffer implementation changes its allocation and content lengths to size_t throughout its interface. It also checks the addition used to reserve an optional terminating byte. If adding one produces a size below the supplied length, it detects overflow and aborts.
Its growth calculation normally doubles capacity until the requested size fits. Near the size type's upper bound, repeatedly doubling can itself overflow. The patch treats large requests separately and validates that the chosen capacity has not fallen below the requirement.
This is a second layer of arithmetic reasoning. The serializer validates its expansion formula, while the buffer validates the capacity strategy it applies to a requested length. Each component needs to preserve its own assumptions because the caller's valid request can still pass through further arithmetic inside the allocator helper.
The patch also removes the buffer's configurable linear-growth increment and uses the revised growth strategy. That reduces the number of capacity-calculation paths in this helper. It does not mean that arbitrary large values will fit in available process memory, only that arithmetic overflow must not produce an undersized allocation that subsequent writes treat as sufficient.
The distinction between representable size and available memory remains important. A request can be arithmetically valid and still exceed the resources available to the process. This patch addresses the arithmetic and memory-corruption boundary. It does not make serialization independent of the size of its output.
MessagePack has a separate growth expression
The cmsgpack changes address another buffer-growth calculation. The older expression combined the existing length and appended length, then doubled the sum. Its revised code first computes the sum and checks that it did not wrap below the existing length.
It then checks the total against half of SIZE_MAX before doubling it. Splitting the calculation makes the addition and multiplication obligations explicit. A single final comparison would be difficult to trust if one of those earlier operations had already wrapped.
Other MessagePack changes adjust encoded lengths and collection counts to types suited to their roles. Unpacking offsets and limits use lua_Integer, while a derived offset uses size_t and receives a range check before conversion back to the Lua-facing integer. These are related representation boundaries within the serializer.
The important connection is between allocated capacity and later writes. If capacity arithmetic produces a number smaller than the bytes the encoder intends to append, a successful allocation can still leave the write unsafe. The allocator returning a non-null pointer is insufficient evidence that the requested logical output fits.
These repairs concern native implementations used by scripts. They should not be described as a new restriction on ordinary JSON syntax or a change to MessagePack's wire format. The public impact is the removal of unsafe memory-handling paths reachable through serialization operations.
The access condition narrows exposure
The advisory explicitly requires authenticated and authorized users. That rules out describing this report as an unrestricted unauthenticated attack through any open network connection. The relevant capability is permission to execute a crafted Lua script within Redis.
Authorization still does not make every script benign. In a system where several application identities share a server, permission to perform useful scripted work does not imply that one identity should be able to corrupt the process hosting the others. The native serializer must enforce its memory assumptions for authorized callers too.
The reported consequence includes potential remote code execution. That is stronger than the denial-of-service impact of an ordinary assertion failure, but it remains qualified by the advisory. The source does not justify claiming that every affected installation has already suffered execution or that every crafted script reliably achieves it.
The patched versions named by the advisory are 7.0.12, 6.2.13, and 6.0.20. Those identify the fixes available in the maintained branches it lists. The statement that the issue reaches back to scripting support in 2.6 should not be confused with a claim that every historical branch receives a new patch release.
The documented workaround removes script execution
For an installation that cannot immediately patch the executable, the advisory describes using ACL rules to restrict EVAL and EVALSHA, preventing users from executing Lua scripts through those commands. That is a reduction in reachable functionality. It is useful only where the resulting application limitations are acceptable.
The workaround is not a replacement for the buffer corrections. It prevents access to the execution path identified by the advisory. Applications that require scripting still need a server implementation with the corrected native libraries, rather than assuming that trusted source code makes vulnerable buffer arithmetic safe.
The release notes also identify CVE-2023-36824, a separate heap-overflow issue involving extraction of command key names and arguments. They name COMMAND GETKEYS* and ACL key validation as relevant paths. That second flaw should remain distinct from the Lua serializers, even though it shares the same security release.
This distinction matters for interpreting an upgrade's scope. Restricting script execution addresses the workaround described for CVE-2022-24834. It does not establish that every unrelated issue in the release has become unreachable. Each affected path needs the scope supplied by its own description.
Native dependencies determine the full execution boundary
I regard the patch as a concrete example of why embedded libraries belong in database security review. cjson expands strings into escaped output, cmsgpack grows an encoding buffer, and the shared string helper chooses capacities. Each operation needs a representable size before it can safely allocate and write bytes.
Redis 7.0.12 changes those size representations and checks the arithmetic at the places that derive new capacities. The practical result is a repaired native serialization path for the scripting capability that authorized applications already use. The advisory's access condition and named patched branches define where that correction applies.