Fix rdb.c dictionary iterator release.

Some times it was not released on error, sometimes it was released two
times because the error path expected the "di" var to be NULL if the
iterator was already released. Thanks to @oranagra for pinging me about
potential problems of this kind inside rdb.c.
This commit is contained in:
antirez 2018-05-09 11:03:27 +02:00
parent aaef5f00cc
commit cd87b3c71f

View File

@ -778,7 +778,11 @@ ssize_t rdbSaveObject(rio *rdb, robj *o) {
while((de = dictNext(di)) != NULL) { while((de = dictNext(di)) != NULL) {
sds ele = dictGetKey(de); sds ele = dictGetKey(de);
if ((n = rdbSaveRawString(rdb,(unsigned char*)ele,sdslen(ele))) if ((n = rdbSaveRawString(rdb,(unsigned char*)ele,sdslen(ele)))
== -1) return -1; == -1)
{
dictReleaseIterator(di);
return -1;
}
nwritten += n; nwritten += n;
} }
dictReleaseIterator(di); dictReleaseIterator(di);
@ -846,10 +850,18 @@ ssize_t rdbSaveObject(rio *rdb, robj *o) {
sds value = dictGetVal(de); sds value = dictGetVal(de);
if ((n = rdbSaveRawString(rdb,(unsigned char*)field, if ((n = rdbSaveRawString(rdb,(unsigned char*)field,
sdslen(field))) == -1) return -1; sdslen(field))) == -1)
{
dictReleaseIterator(di);
return -1;
}
nwritten += n; nwritten += n;
if ((n = rdbSaveRawString(rdb,(unsigned char*)value, if ((n = rdbSaveRawString(rdb,(unsigned char*)value,
sdslen(value))) == -1) return -1; sdslen(value))) == -1)
{
dictReleaseIterator(di);
return -1;
}
nwritten += n; nwritten += n;
} }
dictReleaseIterator(di); dictReleaseIterator(di);
@ -1088,7 +1100,6 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
dict *d = db->dict; dict *d = db->dict;
if (dictSize(d) == 0) continue; if (dictSize(d) == 0) continue;
di = dictGetSafeIterator(d); di = dictGetSafeIterator(d);
if (!di) return C_ERR;
/* Write the SELECT DB opcode */ /* Write the SELECT DB opcode */
if (rdbSaveType(rdb,RDB_OPCODE_SELECTDB) == -1) goto werr; if (rdbSaveType(rdb,RDB_OPCODE_SELECTDB) == -1) goto werr;
@ -1130,8 +1141,8 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
} }
} }
dictReleaseIterator(di); dictReleaseIterator(di);
}
di = NULL; /* So that we don't release it again on error. */ di = NULL; /* So that we don't release it again on error. */
}
/* If we are storing the replication information on disk, persist /* If we are storing the replication information on disk, persist
* the script cache as well: on successful PSYNC after a restart, we need * the script cache as well: on successful PSYNC after a restart, we need
@ -1145,6 +1156,7 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
goto werr; goto werr;
} }
dictReleaseIterator(di); dictReleaseIterator(di);
di = NULL; /* So that we don't release it again on error. */
} }
/* EOF opcode */ /* EOF opcode */