summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2017-07-20 15:17:35 +0200
committerantirez <antirez@gmail.com>2017-07-20 15:17:35 +0200
commita3778f3b0f0aacbb34ecc77541615a9eda251443 (patch)
tree67ec0063322d6bf84646e43b0e7a123e627ad80a
parentb1c2e1a19c549a49cc124571849976e7ab91d4d1 (diff)
downloadredis-a3778f3b0f0aacbb34ecc77541615a9eda251443.tar.gz
Make representClusterNodeFlags() more robust.
This function failed when an internal-only flag was set as an only flag in a node: the string was trimmed expecting a final comma before exiting the function, causing a crash. See issue #4142. Moreover generation of flags representation only needed at DEBUG log level was always performed: a waste of CPU time. This is fixed as well by this commit.
-rw-r--r--src/cluster.c35
1 files changed, 18 insertions, 17 deletions
diff --git a/src/cluster.c b/src/cluster.c
index a516e911f..89765e37d 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -1323,14 +1323,16 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
clusterNode *node;
sds ci;
- ci = representClusterNodeFlags(sdsempty(), flags);
- serverLog(LL_DEBUG,"GOSSIP %.40s %s:%d@%d %s",
- g->nodename,
- g->ip,
- ntohs(g->port),
- ntohs(g->cport),
- ci);
- sdsfree(ci);
+ if (server.verbosity == LL_DEBUG) {
+ ci = representClusterNodeFlags(sdsempty(), flags);
+ serverLog(LL_DEBUG,"GOSSIP %.40s %s:%d@%d %s",
+ g->nodename,
+ g->ip,
+ ntohs(g->port),
+ ntohs(g->cport),
+ ci);
+ sdsfree(ci);
+ }
/* Update our state accordingly to the gossip sections */
node = clusterLookupNode(g->nodename);
@@ -3835,15 +3837,14 @@ static struct redisNodeFlags redisNodeFlagsTable[] = {
/* Concatenate the comma separated list of node flags to the given SDS
* string 'ci'. */
sds representClusterNodeFlags(sds ci, uint16_t flags) {
- if (flags == 0) {
- ci = sdscat(ci,"noflags,");
- } else {
- int i, size = sizeof(redisNodeFlagsTable)/sizeof(struct redisNodeFlags);
- for (i = 0; i < size; i++) {
- struct redisNodeFlags *nodeflag = redisNodeFlagsTable + i;
- if (flags & nodeflag->flag) ci = sdscat(ci, nodeflag->name);
- }
- }
+ size_t orig_len = sdslen(ci);
+ int i, size = sizeof(redisNodeFlagsTable)/sizeof(struct redisNodeFlags);
+ for (i = 0; i < size; i++) {
+ struct redisNodeFlags *nodeflag = redisNodeFlagsTable + i;
+ if (flags & nodeflag->flag) ci = sdscat(ci, nodeflag->name);
+ }
+ /* If no flag was added, add the "noflags" special flag. */
+ if (sdslen(ci) == orig_len) ci = sdscat(ci,"noflags,");
sdsIncrLen(ci,-1); /* Remove trailing comma. */
return ci;
}