CVE-2020-36406: Out-of-bounds Write (CWE-787)
value: uWebSockets 18.11.0 and 18.12.0 has a stack-based buffer overflow in uWS::TopicTree::trimTree (called from uWS::TopicTree::unsubscribeAll). NOTE: the vendor's position is that this is "a minor issue or not even an issue at all" because the developer of an application (that uses uWebSockets) should not be allowing the large number of triggered topics to accumulate
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.8
Published: 2021-07-01T03:15Z
Repository: https://github.com/uNetworking/uWebSockets
Language: C
Files changed: src/TopicTree.h
Commit date: 2020-09-06 13:05:13 +0200
Commit message: Fix overflow of triggered topics

Diff: diff --git a/src/TopicTree.h b/src/TopicTree.h
index 0b945b3..80dd180 100644
--- a/src/TopicTree.h
+++ b/src/TopicTree.h
@@ -122,14 +122,10 @@ private:
         }
     }
 
     /* Should be getData and commit? */
     void publish(Topic *iterator, size_t start, size_t stop, std::string_view topic, std::pair<std::string_view, std::string_view> message) {
-        /* If we already have 64 triggered topics make sure to drain it here */
-        if (numTriggeredTopics == 64) {
-            drain();
-        }
 
         /* Iterate over all segments in given topic */
         for (; stop != std::string::npos; start = stop + 1) {
             stop = topic.find('/', start);
             std::string_view segment = topic.substr(start, stop - start);
@@ -149,10 +145,15 @@ private:
             if (iterator->terminatingWildcardChild) {
                 iterator->terminatingWildcardChild->messages[messageId] = message;
 
                 /* Add this topic to triggered */
                 if (!iterator->terminatingWildcardChild->triggered) {
+                    /* If we already have 64 triggered topics make sure to drain it here */
+                    if (numTriggeredTopics == 64) {
+                        drain();
+                    }
+
                     triggeredTopics[numTriggeredTopics++] = iterator->terminatingWildcardChild;
                     iterator->terminatingWildcardChild->triggered = true;
                 }
             }
 
@@ -173,10 +174,15 @@ private:
         /* If we went all the way we matched exactly */
         iterator->messages[messageId] = message;
 
         /* Add this topic to triggered */
         if (!iterator->triggered) {
+            /* If we already have 64 triggered topics make sure to drain it here */
+            if (numTriggeredTopics == 64) {
+                drain();
+            }
+
             triggeredTopics[numTriggeredTopics++] = iterator;
             iterator->triggered = true;
         }
     }
 

Vulnerable code:         /* If we already have 64 triggered topics make sure to drain it here */
        if (numTriggeredTopics == 64) {
            drain();
        }
Fixed code:                     /* If we already have 64 triggered topics make sure to drain it here */
                    if (numTriggeredTopics == 64) {
                        drain();
                    }

            /* If we already have 64 triggered topics make sure to drain it here */
            if (numTriggeredTopics == 64) {
                drain();
            }