Hello community,

here is the log from the commit of package redis for openSUSE:Factory checked 
in at 2018-02-09 15:52:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/redis (Old)
 and      /work/SRC/openSUSE:Factory/.redis.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "redis"

Fri Feb  9 15:52:42 2018 rev:39 rq:574511 version:4.0.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/redis/redis.changes      2018-01-28 
20:33:44.833981955 +0100
+++ /work/SRC/openSUSE:Factory/.redis.new/redis.changes 2018-02-09 
15:52:54.871822767 +0100
@@ -1,0 +2,7 @@
+Thu Feb  8 23:23:58 UTC 2018 - i...@ilya.pp.ua
+
+- Update to 4.0.8
+  * Release notes: 
https://raw.githubusercontent.com/antirez/redis/4.0/00-RELEASENOTES
+  * Fix crash Redis Cluster instances during deletions.
+
+-------------------------------------------------------------------

Old:
----
  redis-4.0.7.tar.gz

New:
----
  redis-4.0.8.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ redis.spec ++++++
--- /var/tmp/diff_new_pack.4jMKDt/_old  2018-02-09 15:52:57.091743031 +0100
+++ /var/tmp/diff_new_pack.4jMKDt/_new  2018-02-09 15:52:57.091743031 +0100
@@ -19,7 +19,7 @@
 %define _log_dir        %{_localstatedir}/log/%{name}
 %define _conf_dir       %{_sysconfdir}/%{name}
 Name:           redis
-Version:        4.0.7
+Version:        4.0.8
 Release:        0
 Summary:        Persistent key-value database
 License:        BSD-3-Clause

++++++ redis-4.0.7.tar.gz -> redis-4.0.8.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-4.0.7/00-RELEASENOTES 
new/redis-4.0.8/00-RELEASENOTES
--- old/redis-4.0.7/00-RELEASENOTES     2018-01-24 11:16:18.000000000 +0100
+++ new/redis-4.0.8/00-RELEASENOTES     2018-02-02 17:39:14.000000000 +0100
@@ -11,6 +11,31 @@
 
--------------------------------------------------------------------------------
 
 
================================================================================
+Redis 4.0.8     Released Fri Feb 2 11:17:40 CET 2018
+================================================================================
+
+Upgrade urgency CRITICAL ONLY for Redis Cluster users. Otherwise no reason
+to upgrade at all.
+
+Redis 4.0.8 fixes a single critical bug in the radix tree data structure
+used for Redis Cluster keys slot tracking. The problem was actually fixed
+10 months ago into unstable, but it was fixed in a commit related to Streams
+so it was never backported (for error) into the 4.0 branch.
+
+The problem will crash Redis Cluster instances during deletions, but it is
+very hard to trigger: only when the node removed is in the edge of a memory
+mapped area there are the conditions to create an issue, because otherwise
+the code just accesses an out of range word in read-only way in an allocated
+structure: this is almost always harmless.
+
+The single commit in this release:
+
+f603940f Rax updated to latest antirez/rax commit. (Salvatore Sanfilippo)
+
+Cheers,
+Salvatore
+
+================================================================================
 Redis 4.0.7     Released Wed Jan 24 11:01:40 CET 2018
 
================================================================================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-4.0.7/src/rax.c new/redis-4.0.8/src/rax.c
--- old/redis-4.0.7/src/rax.c   2018-01-24 11:16:18.000000000 +0100
+++ new/redis-4.0.8/src/rax.c   2018-02-02 17:39:14.000000000 +0100
@@ -131,7 +131,7 @@
 }
 
 /* ----------------------------------------------------------------------------
- * Radis tree implementation
+ * Radix tree implementation
  * --------------------------------------------------------------------------*/
 
 /* Allocate a new non compressed node with the specified number of children.
@@ -186,10 +186,10 @@
 void raxSetData(raxNode *n, void *data) {
     n->iskey = 1;
     if (data != NULL) {
+        n->isnull = 0;
         void **ndata = (void**)
             ((char*)n+raxNodeCurrentLength(n)-sizeof(void*));
         memcpy(ndata,&data,sizeof(data));
-        n->isnull = 0;
     } else {
         n->isnull = 1;
     }
@@ -396,6 +396,7 @@
                   position to 0 to signal this node represents
                   the searched key. */
     }
+    debugnode("Lookup stop node is",h);
     if (stopnode) *stopnode = h;
     if (plink) *plink = parentlink;
     if (splitpos && h->iscompr) *splitpos = j;
@@ -424,18 +425,21 @@
      * our key. We have just to reallocate the node and make space for the
      * data pointer. */
     if (i == len && (!h->iscompr || j == 0 /* not in the middle if j is 0 */)) 
{
+        debugf("### Insert: node representing key exists\n");
+        if (!h->iskey || h->isnull) {
+            h = raxReallocForData(h,data);
+            if (h) memcpy(parentlink,&h,sizeof(h));
+        }
+        if (h == NULL) {
+            errno = ENOMEM;
+            return 0;
+        }
         if (h->iskey) {
             if (old) *old = raxGetData(h);
             raxSetData(h,data);
             errno = 0;
             return 0; /* Element already exists. */
         }
-        h = raxReallocForData(h,data);
-        if (h == NULL) {
-            errno = ENOMEM;
-            return 0;
-        }
-        memcpy(parentlink,&h,sizeof(h));
         raxSetData(h,data);
         rax->numele++;
         return 1; /* Element inserted. */
@@ -734,9 +738,7 @@
     }
 
     /* We walked the radix tree as far as we could, but still there are left
-     * chars in our string. We need to insert the missing nodes.
-     * Note: while loop never entered if the node was split by ALGO2,
-     * since i == len. */
+     * chars in our string. We need to insert the missing nodes. */
     while(i < len) {
         raxNode *child;
 
@@ -871,7 +873,8 @@
     memmove(((char*)cp)-1,cp,(parent->size-taillen-1)*sizeof(raxNode**));
 
     /* Move the remaining "tail" pointer at the right position as well. */
-    
memmove(((char*)c)-1,c+1,taillen*sizeof(raxNode**)+parent->iskey*sizeof(void*));
+    size_t valuelen = (parent->iskey && !parent->isnull) ? sizeof(void*) : 0;
+    memmove(((char*)c)-1,c+1,taillen*sizeof(raxNode**)+valuelen);
 
     /* 4. Update size. */
     parent->size--;
@@ -1090,27 +1093,36 @@
 
 /* This is the core of raxFree(): performs a depth-first scan of the
  * tree and releases all the nodes found. */
-void raxRecursiveFree(rax *rax, raxNode *n) {
+void raxRecursiveFree(rax *rax, raxNode *n, void (*free_callback)(void*)) {
+    debugnode("free traversing",n);
     int numchildren = n->iscompr ? 1 : n->size;
     raxNode **cp = raxNodeLastChildPtr(n);
     while(numchildren--) {
         raxNode *child;
         memcpy(&child,cp,sizeof(child));
-        raxRecursiveFree(rax,child);
+        raxRecursiveFree(rax,child,free_callback);
         cp--;
     }
     debugnode("free depth-first",n);
+    if (free_callback && n->iskey && !n->isnull)
+        free_callback(raxGetData(n));
     rax_free(n);
     rax->numnodes--;
 }
 
-/* Free a whole radix tree. */
-void raxFree(rax *rax) {
-    raxRecursiveFree(rax,rax->head);
+/* Free a whole radix tree, calling the specified callback in order to
+ * free the auxiliary data. */
+void raxFreeWithCallback(rax *rax, void (*free_callback)(void*)) {
+    raxRecursiveFree(rax,rax->head,free_callback);
     assert(rax->numnodes == 0);
     rax_free(rax);
 }
 
+/* Free a whole radix tree. */
+void raxFree(rax *rax) {
+    raxFreeWithCallback(rax,NULL);
+}
+
 /* ------------------------------- Iterator --------------------------------- 
*/
 
 /* Initialize a Rax iterator. This call should be performed a single time
@@ -1172,7 +1184,7 @@
  * The function returns 1 on success or 0 on out of memory. */
 int raxIteratorNextStep(raxIterator *it, int noup) {
     if (it->flags & RAX_ITER_EOF) {
-        return 0;
+        return 1;
     } else if (it->flags & RAX_ITER_JUST_SEEKED) {
         it->flags &= ~RAX_ITER_JUST_SEEKED;
         return 1;
@@ -1184,10 +1196,6 @@
     size_t orig_stack_items = it->stack.items;
     raxNode *orig_node = it->node;
 
-    /* Clear the EOF flag: it will be set again if the EOF condition
-     * is still valid. */
-    it->flags &= ~RAX_ITER_EOF;
-
     while(1) {
         int children = it->node->iscompr ? 1 : it->node->size;
         if (!noup && children) {
@@ -1288,7 +1296,7 @@
  * effect to the one of raxIteratorPrevSte(). */
 int raxIteratorPrevStep(raxIterator *it, int noup) {
     if (it->flags & RAX_ITER_EOF) {
-        return 0;
+        return 1;
     } else if (it->flags & RAX_ITER_JUST_SEEKED) {
         it->flags &= ~RAX_ITER_JUST_SEEKED;
         return 1;
@@ -1409,6 +1417,7 @@
         it->node = it->rt->head;
         if (!raxSeekGreatest(it)) return 0;
         assert(it->node->iskey);
+        it->data = raxGetData(it->node);
         return 1;
     }
 
@@ -1427,6 +1436,7 @@
         /* We found our node, since the key matches and we have an
          * "equal" condition. */
         if (!raxIteratorAddChars(it,ele,len)) return 0; /* OOM. */
+        it->data = raxGetData(it->node);
     } else if (lt || gt) {
         /* Exact key not found or eq flag not set. We have to set as current
          * key the one represented by the node we stopped at, and perform
@@ -1499,6 +1509,7 @@
                  * the previous sub-tree. */
                 if (nodechar < keychar) {
                     if (!raxSeekGreatest(it)) return 0;
+                    it->data = raxGetData(it->node);
                 } else {
                     if (!raxIteratorAddChars(it,it->node->data,it->node->size))
                         return 0;
@@ -1615,8 +1626,8 @@
     int eq = 0, lt = 0, gt = 0;
 
     if (op[0] == '=' || op[1] == '=') eq = 1;
-    if (op[1] == '>') gt = 1;
-    else if (op[1] == '<') lt = 1;
+    if (op[0] == '>') gt = 1;
+    else if (op[0] == '<') lt = 1;
     else if (op[1] != '=') return 0; /* Syntax error. */
 
     size_t minlen = key_len < iter->key_len ? key_len : iter->key_len;
@@ -1644,6 +1655,19 @@
     raxStackFree(&it->stack);
 }
 
+/* Return if the iterator is in an EOF state. This happens when raxSeek()
+ * failed to seek an appropriate element, so that raxNext() or raxPrev()
+ * will return zero, or when an EOF condition was reached while iterating
+ * with raxNext() and raxPrev(). */
+int raxEOF(raxIterator *it) {
+    return it->flags & RAX_ITER_EOF;
+}
+
+/* Return the number of elements inside the radix tree. */
+uint64_t raxSize(rax *rax) {
+    return rax->numele;
+}
+
 /* ----------------------------- Introspection ------------------------------ 
*/
 
 /* This function is mostly used for debugging and learning purposes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-4.0.7/src/rax.h new/redis-4.0.8/src/rax.h
--- old/redis-4.0.7/src/rax.h   2018-01-24 11:16:18.000000000 +0100
+++ new/redis-4.0.8/src/rax.h   2018-02-02 17:39:14.000000000 +0100
@@ -148,6 +148,7 @@
 int raxRemove(rax *rax, unsigned char *s, size_t len, void **old);
 void *raxFind(rax *rax, unsigned char *s, size_t len);
 void raxFree(rax *rax);
+void raxFreeWithCallback(rax *rax, void (*free_callback)(void*));
 void raxStart(raxIterator *it, rax *rt);
 int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len);
 int raxNext(raxIterator *it);
@@ -155,6 +156,8 @@
 int raxRandomWalk(raxIterator *it, size_t steps);
 int raxCompare(raxIterator *iter, const char *op, unsigned char *key, size_t 
key_len);
 void raxStop(raxIterator *it);
+int raxEOF(raxIterator *it);
 void raxShow(rax *rax);
+uint64_t raxSize(rax *rax);
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-4.0.7/src/version.h 
new/redis-4.0.8/src/version.h
--- old/redis-4.0.7/src/version.h       2018-01-24 11:16:18.000000000 +0100
+++ new/redis-4.0.8/src/version.h       2018-02-02 17:39:14.000000000 +0100
@@ -1 +1 @@
-#define REDIS_VERSION "4.0.7"
+#define REDIS_VERSION "4.0.8"


Reply via email to