Skip to content

eloqkv2rdb: exported values silently corrupted — int32_t narrowing of numeric strings, TTL ms→s truncation, zset score precision loss #494

Open

Description

@liunyl

Summary

Three data-fidelity bugs in the offline RDB exporter (src/tools/eloqkv2rdb/eloqkv2rdb.cpp):

1. Numeric strings narrowed through int32_t (data corruption)

RedisRdbUtil::OutputString (~line 139):

if (std::regex_match(s, number_pattern))
{
    int32_t n = std::stol(s);   // <-- narrowing
    ...
    else if (n >= -2147483648 && n <= 2147483647)  // always true for int32_t
  • Digit strings between 2^31 and 2^63 (10–19 digits, e.g. a user ID "9876543210") wrap on the long → int32_t conversion and are emitted as a different INT32-encoded value — silent corruption in the exported RDB.
  • Digit strings ≥ 20 chars make std::stol throw std::out_of_range, uncaught in worker threads → crash.

Fix: parse into int64_t, fall through to raw-string encoding when the value exceeds the INT32 range (matching Redis rdbTryIntegerEncoding), and catch/route parse failures to the string path.

2. TTL truncated from milliseconds to seconds

OutputTTL (~line 230) emits a second-resolution EXPIRETIME (uint32_t expire = ttl / 1000). Redis RDB supports millisecond expiry (0xFC, 8-byte ms). Sub-second precision is lost on every exported key.

3. zset score precision loss

Line ~352 serializes scores with OutputString(std::to_string(score)) — std::to_string(double) formats with 6 fixed decimals, so scores that need full double precision (or large magnitudes) round-trip incorrectly. Use %.17g (or RDB binary score encoding) instead.

Impact

Exports used for migration produce silently wrong data: corrupted numeric values, shifted expiry, rounded scores.


Found during the module-docs review (#492); see docs/07-persistence-and-tools.md Gotchas.

🤖 Found with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions