Skip to content

Commit

Permalink
Redis 5.0.14
Browse files Browse the repository at this point in the history
- synced with redis/redis@5.0.14
- enabled "SCRIPT DEBUG SYNC"
  • Loading branch information
tporadowski committed Oct 17, 2021
1 parent b20d6d4 commit a7c01ef
Show file tree
Hide file tree
Showing 30 changed files with 520 additions and 73 deletions.
30 changes: 30 additions & 0 deletions 00-RELEASENOTES
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,36 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
SECURITY: There are security fixes in the release.
--------------------------------------------------------------------------------

================================================================================
Redis 5.0.14 Released Mon Oct 4 12:00:00 IDT 2021
================================================================================

Upgrade urgency: SECURITY, contains fixes to security issues.

Security Fixes:
* (CVE-2021-41099) Integer to heap buffer overflow handling certain string
commands and network payloads, when proto-max-bulk-len is manually configured
to a non-default, very large value [reported by yiyuaner].
* (CVE-2021-32762) Integer to heap buffer overflow issue in redis-cli and
redis-sentinel parsing large multi-bulk replies on some older and less common
platforms [reported by Microsoft Vulnerability Research].
* (CVE-2021-32687) Integer to heap buffer overflow with intsets, when
set-max-intset-entries is manually configured to a non-default, very large
value [reported by Pawel Wieczorkiewicz, AWS].
* (CVE-2021-32675) Denial Of Service when processing RESP request payloads with
a large number of elements on many connections.
* (CVE-2021-32672) Random heap reading issue with Lua Debugger [reported by
Meir Shpilraien].
* (CVE-2021-32628) Integer to heap buffer overflow handling ziplist-encoded
data types, when configuring a large, non-default value for
hash-max-ziplist-entries, hash-max-ziplist-value, zset-max-ziplist-entries
or zset-max-ziplist-value [reported by sundb].
* (CVE-2021-32627) Integer to heap buffer overflow issue with streams, when
configuring a non-default, large value for proto-max-bulk-len and
client-query-buffer-limit [reported by sundb].
* (CVE-2021-32626) Specially crafted Lua scripts may result with Heap buffer
overflow [reported by Meir Shpilraien].

================================================================================
Redis 5.0.13 Released Wed Jul 21 16:32:19 IDT 2021
================================================================================
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Redis 5.0.9 for Windows
# Redis 5.0.14 for Windows

You can find the release of **Redis 5.0.9 for Windows** on [releases page](https://github.com/tporadowski/redis/releases). Please test it and [report any issues](https://github.com/tporadowski/redis/wiki/Submitting-an-Issue), thanks in advance!
You can find the release of **Redis 5.0.14 for Windows** on [releases page](https://github.com/tporadowski/redis/releases). Please test it and [report any issues](https://github.com/tporadowski/redis/wiki/Submitting-an-Issue), thanks in advance!

## Redis 4.0.14 for Windows

You can find the release of **Redis 4.0.14 for Windows** on [releases page](https://github.com/tporadowski/redis/releases). Please test it and [report any issues](https://github.com/tporadowski/redis/wiki/Submitting-an-Issue), thanks in advance!

**DISCLAIMER**

At the moment [win-4.0.14 branch](https://github.com/tporadowski/redis/tree/win-4.0.14) provides a **stable port of [Redis 4.0.14](https://github.com/antirez/redis/releases/tag/4.0.14) for Windows x64** and [win-5.0 branch](https://github.com/tporadowski/redis/tree/win-5.0) provides a **fairly stable port of [Redis 5.0.9](https://github.com/antirez/redis/releases/tag/5.0.9) for Windows x64**, both merged with archived port of [win-3.2.100 version](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100) from MS Open Tech team. Since the latter is no longer maintained - the sources were merged by hand, projects updated to Visual Studio 2019 (v16.2.5) and any findings (mostly via unit tests) were fixed.
At the moment [win-4.0.14 branch](https://github.com/tporadowski/redis/tree/win-4.0.14) provides a **stable port of [Redis 4.0.14](https://github.com/antirez/redis/releases/tag/4.0.14) for Windows x64** and [win-5.0 branch](https://github.com/tporadowski/redis/tree/win-5.0) provides a **stable port of [Redis 5.0.14](https://github.com/antirez/redis/releases/tag/5.0.14) for Windows x64**, both merged with archived port of [win-3.2.100 version](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100) from MS Open Tech team. Since the latter is no longer maintained - the sources were merged by hand, projects updated to Visual Studio 2019 (v16.2.5) and any findings (mostly via unit tests) were fixed.

You can find the original description of what this fork provides, how it evolved, what are its requirements, etc. on Wiki: https://github.com/tporadowski/redis/wiki/Old-MSOpenTech-redis-README.md

Expand Down
1 change: 1 addition & 0 deletions deps/hiredis/hiredis.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ static void *createArrayObject(const redisReadTask *task, int elements) {
return NULL;

if (elements > 0) {
if (SIZE_MAX / sizeof(redisReply*) < elements) return NULL; /* Don't overflow */
r->element = calloc(elements, sizeof(redisReply*));
if (r->element == NULL) {
freeReplyObject(r);
Expand Down
14 changes: 14 additions & 0 deletions deps/hiredis/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,20 @@ static void test_reply_reader(void) {
strncasecmp(reader->errstr,"No support for",14) == 0);
redisReaderFree(reader);

test("Multi-bulk never overflows regardless of maxelements: ");
size_t bad_mbulk_len = (SIZE_MAX / sizeof(void *)) + 3;
char bad_mbulk_reply[100];
snprintf(bad_mbulk_reply, sizeof(bad_mbulk_reply), "*%llu\r\n+asdf\r\n",
(unsigned long long) bad_mbulk_len);

reader = redisReaderCreate();
reader->maxelements = 0; /* Don't rely on default limit */
redisReaderFeed(reader, bad_mbulk_reply, strlen(bad_mbulk_reply));
ret = redisReaderGetReply(reader,&reply);
test_cond(ret == REDIS_ERR && strcasecmp(reader->errstr, "Out of memory") == 0);
freeReplyObject(reply);
redisReaderFree(reader);

test("Works with NULL functions for reply: ");
reader = redisReaderCreate();
reader->fn = NULL;
Expand Down
8 changes: 4 additions & 4 deletions msvs/RedisForWindows.rc
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 5,0,13
PRODUCTVERSION 5,0,13
FILEVERSION 5,0,14
PRODUCTVERSION 5,0,14
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -68,10 +68,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Poradowski.com Tomasz Poradowski"
VALUE "FileDescription", "Redis for Windows, based on MS OpenTech port."
VALUE "FileVersion", "5.0.13"
VALUE "FileVersion", "5.0.14"
VALUE "LegalCopyright", "Copyright (C) 2006-2018 Salvatore Sanfilippo, Microsoft Open Technologies Inc., Tomasz Poradowski"
VALUE "ProductName", "Redis for Windows"
VALUE "ProductVersion", "5.0.13"
VALUE "ProductVersion", "5.0.14"
END
END
BLOCK "VarFileInfo"
Expand Down
2 changes: 1 addition & 1 deletion msvs/msi/RedisMsi/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<Product Id="*"
Name="Redis on Windows"
Language="1033"
Version="5.0.13"
Version="5.0.14"
Manufacturer="Poradowski.com"
UpgradeCode="{05410198-7212-4FC4-B7C8-AFEFC3DA0FBC}">
<Package InstallerVersion="200"
Expand Down
2 changes: 1 addition & 1 deletion msvs/setups/chocolatey/Redis.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<metadata>
<id>redis-64</id>
<title>Redis 64-bit</title>
<version>5.0.13</version>
<version>5.0.14</version>
<authors>Alexis Campailla, Enrico Giordani, Jonathan Pickett</authors>
<owners>Microsoft Open Technologies, Inc.</owners>
<description>A porting of Redis on Windows 64-bit.
Expand Down
2 changes: 1 addition & 1 deletion msvs/setups/nuget/Redis.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<metadata>
<id>redis-64</id>
<title>Redis 64-bit</title>
<version>5.0.13</version>
<version>5.0.14</version>
<authors>Alexis Campailla, Enrico Giordani, Jonathan Pickett</authors>
<owners>Microsoft Open Technologies, Inc.</owners>
<description>A porting of Redis on Windows 64-bit.
Expand Down
5 changes: 3 additions & 2 deletions src/geo.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ void georadiusGeneric(client *c, int flags) {
robj *zobj;
zset *zs;
int i;
size_t maxelelen = 0;
size_t maxelelen = 0, totelelen = 0;

if (returned_items) {
zobj = createZsetObject();
Expand All @@ -650,13 +650,14 @@ void georadiusGeneric(client *c, int flags) {
size_t elelen = sdslen(gp->member);

if (maxelelen < elelen) maxelelen = elelen;
totelelen += elelen;
znode = zslInsert(zs->zsl,score,gp->member);
serverAssert(dictAdd(zs->dict,gp->member,&znode->score) == DICT_OK);
gp->member = NULL;
}

if (returned_items) {
zsetConvertToZiplistIfNeeded(zobj,maxelelen);
zsetConvertToZiplistIfNeeded(zobj,maxelelen,totelelen);
setKey(c->db,storekey,zobj);
decrRefCount(zobj);
notifyKeyspaceEvent(NOTIFY_ZSET,"georadiusstore",storekey,
Expand Down
4 changes: 3 additions & 1 deletion src/intset.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "intset.h"
#include "zmalloc.h"
#include "endianconv.h"
#include "redisassert.h"

/* Note that these encodings are ordered, so:
* INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */
Expand Down Expand Up @@ -107,7 +108,8 @@ intset *intsetNew(void) {

/* Resize the intset */
static intset *intsetResize(intset *is, uint32_t len) {
uint32_t size = len*intrev32ifbe(is->encoding);
uint64_t size = (uint64_t)len*intrev32ifbe(is->encoding);
assert(size <= SIZE_MAX - sizeof(intset));
is = zrealloc(is,sizeof(intset)+size);
return is;
}
Expand Down
2 changes: 1 addition & 1 deletion src/listpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ int lpEncodeGetType(unsigned char *ele, uint32_t size, unsigned char *intenc, ui
} else {
if (size < 64) *enclen = 1+size;
else if (size < 4096) *enclen = 2+size;
else *enclen = 5+size;
else *enclen = 5+(uint64_t)size;
return LP_ENCODING_STRING;
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,10 @@ int processMultibulkBuffer(client *c) {
addReplyError(c,"Protocol error: invalid multibulk length");
setProtocolError("invalid mbulk count",c);
return C_ERR;
} else if (ll > 10 && server.requirepass && !c->authenticated) {
addReplyError(c, "Protocol error: unauthenticated multibulk length");
setProtocolError("unauth mbulk count", c);
return C_ERR;
}

c->qb_pos = (newline-c->querybuf)+2;
Expand Down Expand Up @@ -1456,6 +1460,10 @@ int processMultibulkBuffer(client *c) {
addReplyError(c,"Protocol error: invalid bulk length");
setProtocolError("invalid bulk length",c);
return C_ERR;
} else if (ll > 16384 && server.requirepass && !c->authenticated) {
addReplyError(c, "Protocol error: unauthenticated bulk length");
setProtocolError("unauth bulk length", c);
return C_ERR;
}

c->qb_pos = newline-c->querybuf+2;
Expand Down
17 changes: 15 additions & 2 deletions src/quicklist.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*/

#include <string.h> /* for memcpy */
#include "redisassert.h"
#include "quicklist.h"
#include "zmalloc.h"
#include "ziplist.h"
Expand All @@ -43,11 +44,16 @@
#define REDIS_STATIC static
#endif

/* Optimization levels for size-based filling */
/* Optimization levels for size-based filling.
* Note that the largest possible limit is 16k, so even if each record takes
* just one byte, it still won't overflow the 16 bit count field. */
static const size_t optimization_level[] = {4096, 8192, 16384, 32768, 65536};

/* Maximum size in bytes of any multi-element ziplist.
* Larger values will live in their own isolated ziplists. */
* Larger values will live in their own isolated ziplists.
* This is used only if we're limited by record count. when we're limited by
* size, the maximum limit is bigger, but still safe.
* 8k is a recommended / default size limit */
#define SIZE_SAFETY_LIMIT 8192

/* Minimum ziplist size in bytes for attempting compression. */
Expand Down Expand Up @@ -441,6 +447,8 @@ REDIS_STATIC int _quicklistNodeAllowInsert(const quicklistNode *node,
unsigned int new_sz = (unsigned int)(node->sz + sz + ziplist_overhead); WIN_PORT_FIX /* cast (unsigned int) */
if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(new_sz, fill)))
return 1;
/* when we return 1 above we know that the limit is a size limit (which is
* safe, see comments next to optimization_level and SIZE_SAFETY_LIMIT) */
else if (!sizeMeetsSafetyLimit(new_sz))
return 0;
else if ((int)node->count < fill)
Expand All @@ -460,6 +468,8 @@ REDIS_STATIC int _quicklistNodeAllowMerge(const quicklistNode *a,
unsigned int merge_sz = a->sz + b->sz - 11;
if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(merge_sz, fill)))
return 1;
/* when we return 1 above we know that the limit is a size limit (which is
* safe, see comments next to optimization_level and SIZE_SAFETY_LIMIT) */
else if (!sizeMeetsSafetyLimit(merge_sz))
return 0;
else if ((int)(a->count + b->count) <= fill)
Expand All @@ -479,6 +489,7 @@ REDIS_STATIC int _quicklistNodeAllowMerge(const quicklistNode *a,
* Returns 1 if new head created. */
int quicklistPushHead(quicklist *quicklist, void *value, size_t sz) {
quicklistNode *orig_head = quicklist->head;
assert(sz < UINT32_MAX); /* TODO: add support for quicklist nodes that are sds encoded (not zipped) */
if (likely(
_quicklistNodeAllowInsert(quicklist->head, quicklist->fill, sz))) {
quicklist->head->zl =
Expand All @@ -502,6 +513,7 @@ int quicklistPushHead(quicklist *quicklist, void *value, size_t sz) {
* Returns 1 if new tail created. */
int quicklistPushTail(quicklist *quicklist, void *value, size_t sz) {
quicklistNode *orig_tail = quicklist->tail;
assert(sz < UINT32_MAX); /* TODO: add support for quicklist nodes that are sds encoded (not zipped) */
if (likely(
_quicklistNodeAllowInsert(quicklist->tail, quicklist->fill, sz))) {
quicklist->tail->zl =
Expand Down Expand Up @@ -835,6 +847,7 @@ REDIS_STATIC void _quicklistInsert(quicklist *quicklist, quicklistEntry *entry,
int fill = quicklist->fill;
quicklistNode *node = entry->node;
quicklistNode *new_node = NULL;
assert(sz < UINT32_MAX); /* TODO: add support for quicklist nodes that are sds encoded (not zipped) */

if (!node) {
/* we have no reference node, so let's create only node in the list */
Expand Down
40 changes: 27 additions & 13 deletions src/rdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,9 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;

/* Use a regular set when there are too many entries. */
if (len > server.set_max_intset_entries) {
size_t max_entries = server.set_max_intset_entries;
if (max_entries >= 1<<30) max_entries = 1<<30;
if (len > max_entries) {
o = createSetObject();
/* It's faster to expand the dict to the right size asap in order
* to avoid rehashing */
Expand Down Expand Up @@ -1541,7 +1543,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
} else if (rdbtype == RDB_TYPE_ZSET_2 || rdbtype == RDB_TYPE_ZSET) {
/* Read list/set value. */
uint64_t zsetlen;
size_t maxelelen = 0;
size_t maxelelen = 0, totelelen = 0;
zset *zs;

if ((zsetlen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
Expand All @@ -1568,15 +1570,19 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {

/* Don't care about integer-encoded strings. */
if (sdslen(sdsele) > maxelelen) maxelelen = sdslen(sdsele);
totelelen += sdslen(sdsele);

znode = zslInsert(zs->zsl,score,sdsele);
dictAdd(zs->dict,sdsele,&znode->score);
}

/* Convert *after* loading, since sorted sets are not stored ordered. */
if (zsetLength(o) <= server.zset_max_ziplist_entries &&
maxelelen <= server.zset_max_ziplist_value)
zsetConvert(o,OBJ_ENCODING_ZIPLIST);
maxelelen <= server.zset_max_ziplist_value &&
ziplistSafeToAdd(NULL, totelelen))
{
zsetConvert(o,OBJ_ENCODING_ZIPLIST);
}
} else if (rdbtype == RDB_TYPE_HASH) {
uint64_t len;
int ret;
Expand All @@ -1600,21 +1606,25 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
if ((value = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL))
== NULL) return NULL;

/* Add pair to ziplist */
o->ptr = ziplistPush(o->ptr, (unsigned char*)field,
sdslen(field), ZIPLIST_TAIL);
o->ptr = ziplistPush(o->ptr, (unsigned char*)value,
sdslen(value), ZIPLIST_TAIL);

/* Convert to hash table if size threshold is exceeded */
if (sdslen(field) > server.hash_max_ziplist_value ||
sdslen(value) > server.hash_max_ziplist_value)
sdslen(value) > server.hash_max_ziplist_value ||
!ziplistSafeToAdd(o->ptr, sdslen(field)+sdslen(value)))
{
sdsfree(field);
sdsfree(value);
hashTypeConvert(o, OBJ_ENCODING_HT);
ret = dictAdd((dict*)o->ptr, field, value);
if (ret == DICT_ERR) {
rdbExitReportCorruptRDB("Duplicate hash fields detected");
}
break;
}

/* Add pair to ziplist */
o->ptr = ziplistPush(o->ptr, (unsigned char*)field,
sdslen(field), ZIPLIST_TAIL);
o->ptr = ziplistPush(o->ptr, (unsigned char*)value,
sdslen(value), ZIPLIST_TAIL);

sdsfree(field);
sdsfree(value);
}
Expand Down Expand Up @@ -1683,6 +1693,10 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
while ((zi = zipmapNext(zi, &fstr, &flen, &vstr, &vlen)) != NULL) {
if (flen > maxlen) maxlen = flen;
if (vlen > maxlen) maxlen = vlen;
if (!ziplistSafeToAdd(zl, (size_t)flen + vlen)) {
rdbExitReportCorruptRDB("Hash zipmap too big (%u)", flen);
}

zl = ziplistPush(zl, fstr, flen, ZIPLIST_TAIL);
zl = ziplistPush(zl, vstr, vlen, ZIPLIST_TAIL);
}
Expand Down
4 changes: 3 additions & 1 deletion src/redisassert.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
#ifndef __REDIS_ASSERT_H__
#define __REDIS_ASSERT_H__

POSIX_ONLY(#include <unistd.h>) /* for _exit() */
#ifndef _WIN32
#include <unistd.h> /* for _exit() */
#endif

#ifdef _WIN32
#include "Win32_Interop/Win32_Portability.h"
Expand Down
Loading

0 comments on commit a7c01ef

Please sign in to comment.