这里写自定义目录标题
简要
最近在开始看Redis源码,比较各版本的代码看,看着看着就发现一些BUG。写个博客记录一下。
sdssplitlen是一个调用非常频繁的函数,这个BUG将会导致平均每次调用多浪费数十次左右加减法计算资源以及临时浪费5B左右的内存空间。这个BUG影响范围是全版本,从0.07一直到目前最新的5.0.6。
BUG介绍
源码与说明
输入长度为@len的字符串@s,以及长度为@seplen的字符串@sep。
使用@sep对@s进行切分。
切分好的字符串通过返回值@tokens传出,切分得到的个数通过参数@count传出。
/* Split 's' with separator in 'sep'. An array
* of sds strings is returned. *count will be set
* by reference to the number of tokens returned.
*
* On out of memory, zero length string, zero length
* separator, NULL is returned.
*
* Note that 'sep' is able to split a string using
* a multi-character separator. For example
* sdssplit("foo_-_bar","_-_"); will return two
* elements "foo" and "bar".
*
* This version of the function is binary-safe but
* requires length arguments. sdssplit() is just the
* same function but for zero-terminated strings.
*/
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) {
int elements = 0, slots = 5;
long start = 0, j;
sds *tokens;
if (seplen < 1 || len < 0) return NULL;
tokens = s_malloc(sizeof(sds)*slots);
if (tokens == NULL) return NULL;
if (len == 0) {
*count = 0;
return tokens;
}
for (j = 0; j < (len-(seplen-1)); j++) {
/* make sure there is room for the next element and the final one */
if (slots < elements+2) {
// Block 1
sds *newtokens;
slots *= 2;
newtokens = s_realloc(tokens,sizeof(sds)*slots);
if (newtokens == NULL) goto cleanup;
tokens = newtokens;
}
/* search the separator */
if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep