The code of _unsigned long zslGetRank(zskiplist zsl, double score, robj o) _ can be found in t_zset.c
unsigned long zslGetRank(zskiplist *zsl, double score, sds ele) {
zskiplistNode *x;
unsigned long rank = 0;
int i;
x = zsl->header;
for (i = zsl->level-1; i >= 0; i--) {
while (x->level[i].forward &&
(x->level[i].forward->score < score ||
(x->level[i].forward->score == score &&
sdscmp(x->level[i].forward->ele,ele) <= 0))) {
rank += x->level[i].span;
x = x->level[i].forward;
}
/* x might be equal to zsl->header, so test if obj is non-NULL */
if (x->ele && sdscmp(x->ele,ele) == 0) {
return rank;
}
}
return 0;
}
It seems that the function will return rank even when there is no corresponding score in the SkipList. x may stop at a point when x->level[i].forward->score > score and x -> score < score. if x->obj is equal to robj* o as well, then the rank is returned, even though the score does not match.
When Redis use this function, it is used with dict; therefore this may be why it does not cause a problem for now. But for robustness and consistency of API (it does return 0 for unfound objects), shouldn't we check the score as well?