Redis: Memory Safety Spring Cleaning
Today we're diving into three crucial fixes that landed in Redis, focusing on memory safety and data integrity. The team tackled a sneaky listpack memory leak, an integer overflow vulnerability, and implemented smart filtering for expired stream entries. Contributors zzjas, Guy Korland, and Sergei Georgiev delivered some solid defensive programming that'll make Redis more robust.
Duration: PT4M
https://podlog.io/listen/redis-84394f5e/episode/redis-memory-safety-spring-cleaning-8facebf7
Transcript
Hey there, Redis enthusiasts! Welcome back to another episode of the Redis podcast. I'm your host, and wow, do we have some satisfying fixes to talk about today - March 16th, 2026. You know those days when you feel like you're really cleaning house in your codebase? That's exactly what happened in Redis land, and I'm honestly pretty excited about it.
So we had three pull requests merge today, and they all share this beautiful theme of making Redis more bulletproof. It's like the team decided to put on their detective hats and hunt down some really sneaky bugs that could cause real headaches in production.
Let's start with the most intricate one from zzjas. They found and fixed a memory leak that was hiding in the zipmap-to-hash conversion process. Now, this is one of those bugs that really shows how complex systems can have these tiny edge cases that slip through. Picture this: Redis is loading data from an RDB file, converting an old zipmap format to a more modern listpack, and everything's going smoothly until - whoops - there's a duplicate key or some other error. The error handling was doing a great job cleaning up most things, but it was forgetting to free that listpack memory. Just a single missing lpFree call, but in a high-throughput system, those kinds of leaks can really add up over time.
What I love about this fix is that zzjas didn't just patch it and move on. They added a regression test that actually exercises this exact code path by restoring a zipmap with duplicate keys. That's the kind of thorough thinking that prevents these issues from coming back to haunt you six months later.
Next up, Guy Korland tackled something that made my security-conscious heart happy - an integer overflow vulnerability in the lpSafeToAdd function. This is such a classic example of why boundary checking is tricky. The original code was doing a seemingly innocent check: "if length plus addition is greater than our safety limit, reject it." Sounds reasonable, right? But here's the gotcha - if someone passes in a value close to SIZE_MAX, that addition can wrap around and suddenly look like a small number again. Sneaky!
Guy's fix is elegant in its simplicity. Instead of risking that overflow, they check "is the addition itself too big, or would it make the length too big?" It's the same logic, but overflow-safe. Sometimes the best fixes are the ones that make you go "oh, of course!"
And then we have Sergei Georgiev with probably the most user-facing improvement of the day. They implemented filtering for expired IDMP entries during RDB save and load operations. This is one of those features that just makes sense once you hear it. Why would you bother saving stream entries that are already expired? Why load them just to immediately clean them up?
Sergei's approach is really thoughtful - they're filtering on both save AND load. So not only do new RDB files get smaller and cleaner, but if you're loading an older RDB file that has expired entries, the new code will skip those too. It's defense in depth, and it results in smaller files, faster restarts, and less memory usage. Win, win, win.
What strikes me about all three of these changes is how they represent different types of engineering maturity. You've got the careful memory management, the security-conscious boundary checking, and the performance-minded optimization. Each one makes Redis a little more production-ready.
For today's focus, if you're working on your own systems, these fixes offer some great lessons. First, when you're writing error handling code, trace through every allocation to make sure you're cleaning up properly. Second, be extra careful with arithmetic on user-controlled values - overflow bugs are sneaky. And third, don't be afraid to be smart about what data you persist. Sometimes the best optimization is just not doing unnecessary work.
That's a wrap for today's episode! Keep building awesome things with Redis, and remember - sometimes the most important code changes are the ones that prevent problems rather than add features. Until next time, happy coding!