Repository: valkey-io/valkey
File: src/valkey-check-rdb.c (C)

Code before:
            rdbstate.functions_num++;
            continue;
        } else if (rdbIsForeignVersion(rdbver) &&
                   type >= RDB_FOREIGN_TYPE_MIN &&
                   type <= RDB_FOREIGN_TYPE_MAX) {
            rdbCheckError("Unknown object type %d in RDB file with foreign version %d", type, rdbver);
            goto err;
        } else if (!rdbIsObjectType(type)) {
            if (rdbver > RDB_VERSION) {
                rdbCheckError("Unknown object type %d in RDB file with future version %d", type, rdbver);
            } else {
                rdbCheckError("Invalid object type: %d", type);
            }
            goto err;
        } else {
            rdbstate.key_type = type;
        }

        /* Read key */
        rdbstate.doing = RDB_CHECK_DOING_READ_KEY;
        if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
        rdbstate.key = key;
        rdbstate.keys++;
        /* Read value */
        rdbstate.doing = RDB_CHECK_DOING_READ_OBJECT_VALUE;
        if ((val = rdbLoadObject(type, &rdb, objectGetVal(key), selected_dbid, NULL, RDBFLAGS_NONE, now)) == NULL) goto eoferr;
        if (rdbCheckStats) {
            int max_stats_num = (rdbstate.databases + 1) * OBJ_TYPE_MAX;
            if (max_stats_num > rdbstate.stats_num) {
                rdbstate.stats = tryExpandRdbStats(rdbstate.stats, rdbstate.stats_num, max_stats_num);
                rdbstate.stats_num = max_stats_num;
            }

            computeDatasetProfile(selected_dbid, key, val, expiretime);
        }
        /* Check if the key already expired. */
        if (expiretime != -1 && expiretime < now) rdbstate.already_expired++;
        if (expiretime != -1) rdbstate.expires++;
        rdbstate.key = NULL;
        decrRefCount(key);
        decrRefCount(val);
        rdbstate.key_type = -1;
        expiretime = -1;
    }
    /* Verify the checksum if RDB version is >= 5 */
    if (rdbver >= 5 && server.rdb_checksum) {
        uint64_t cksum, expected = rdb.cksum;

        rdbstate.doing = RDB_CHECK_DOING_CHECK_SUM;
        if (rioRead(&rdb, &cksum, 8) == 0) goto eoferr;
        memrev64ifbe(&cksum);

Review comment (bug):
I think setting the time to now is problematic. If we are trying to validate an rdb which hash fields are already expired but where encoded wrong (which is what the user was trying to locate) the check inside rdbLoadObject will skip trying to load the entry. I think that we should consider allow setting a now time to '0' and have the internal check in the rdbLoadObject also consider if now == 0 than consider any entry as NOT expired.

Code after:
            rdbstate.functions_num++;
            continue;
        } else if (rdbIsForeignVersion(rdbver) &&
                   type >= RDB_FOREIGN_TYPE_MIN &&
                   type <= RDB_FOREIGN_TYPE_MAX) {
            rdbCheckError("Unknown object type %d in RDB file with foreign version %d", type, rdbver);
            goto err;
        } else if (!rdbIsObjectType(type)) {
            if (rdbver > RDB_VERSION) {
                rdbCheckError("Unknown object type %d in RDB file with future version %d", type, rdbver);
            } else {
                rdbCheckError("Invalid object type: %d", type);
            }
            goto err;
        } else {
            rdbstate.key_type = type;
        }

        /* Read key */
        rdbstate.doing = RDB_CHECK_DOING_READ_KEY;
        if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
        rdbstate.key = key;
        rdbstate.keys++;
        /* Read value */
        rdbstate.doing = RDB_CHECK_DOING_READ_OBJECT_VALUE;
        if ((val = rdbLoadObject(type, &rdb, objectGetVal(key), selected_dbid, NULL, RDBFLAGS_NONE, 0)) == NULL) goto eoferr;
        if (rdbCheckStats) {
            int max_stats_num = (rdbstate.databases + 1) * OBJ_TYPE_MAX;
            if (max_stats_num > rdbstate.stats_num) {
                rdbstate.stats = tryExpandRdbStats(rdbstate.stats, rdbstate.stats_num, max_stats_num);
                rdbstate.stats_num = max_stats_num;
            }

            computeDatasetProfile(selected_dbid, key, val, expiretime);
        }
        /* Check if the key already expired. */
        if (expiretime != -1 && expiretime < now) rdbstate.already_expired++;
        if (expiretime != -1) rdbstate.expires++;
        rdbstate.key = NULL;
        decrRefCount(key);
        decrRefCount(val);
        rdbstate.key_type = -1;
        expiretime = -1;
    }
    /* Verify the checksum if RDB version is >= 5 */
    if (rdbver >= 5 && server.rdb_checksum) {
        uint64_t cksum, expected = rdb.cksum;

        rdbstate.doing = RDB_CHECK_DOING_CHECK_SUM;
        if (rioRead(&rdb, &cksum, 8) == 0) goto eoferr;
        memrev64ifbe(&cksum);