CVE-2015-2310: Integer Overflow or Wraparound (CWE-190)
value: Integer overflow in layout.c++ in Sandstorm Cap'n Proto before 0.4.1.1 and 0.5.x before 0.5.1.1 allows remote peers to cause a denial of service or possibly obtain sensitive information from memory via a crafted message, related to pointer validation.
CWE description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
CVSS v3 base score: 9.1
Published: 2017-08-09T18:29Z
Repository: https://github.com/capnproto/capnproto
Language: Other
Files changed: c++/src/capnp/layout.c++
Commit date: 2015-03-02 10:32:39 -0800
Commit message: SECURITY: Integer overflow in pointer validation.

Details: https://github.com/sandstorm-io/capnproto/tree/master/security-advisories/2014-03-02-0-c++-integer-overflow.md

Diff: diff --git a/c++/src/capnp/layout.c++ b/c++/src/capnp/layout.c++
index 325ca40..a43dbcd 100644
--- a/c++/src/capnp/layout.c++
+++ b/c++/src/capnp/layout.c++
@@ -683,11 +683,12 @@ struct WireHelpers {
             KJ_REQUIRE(elementTag->kind() == WirePointer::STRUCT,
                        "Don't know how to handle non-STRUCT inline composite.") {
               return result;
             }
 
-            KJ_REQUIRE(elementTag->structRef.wordSize() / ELEMENTS * count <= wordCount,
+            KJ_REQUIRE(elementTag->structRef.wordSize() / ELEMENTS *
+                       ElementCount64(count) <= wordCount,
                        "Struct list pointer's elements overran size.") {
               return result;
             }
 
             WordCount dataSize = elementTag->structRef.dataSize.get();
@@ -1661,11 +1662,11 @@ struct WireHelpers {
           }
 
           ElementCount elementCount = tag->inlineCompositeListElementCount();
           auto wordsPerElement = tag->structRef.wordSize() / ELEMENTS;
 
-          KJ_REQUIRE(wordsPerElement * elementCount <= wordCount,
+          KJ_REQUIRE(wordsPerElement * ElementCount64(elementCount) <= wordCount,
                      "INLINE_COMPOSITE list's elements overrun its word count.") {
             goto useDefault;
           }
 
           return setListPointer(dstSegment, dst,
@@ -1917,11 +1918,11 @@ struct WireHelpers {
       }
 
       size = tag->inlineCompositeListElementCount();
       wordsPerElement = tag->structRef.wordSize() / ELEMENTS;
 
-      KJ_REQUIRE(size * wordsPerElement <= wordCount,
+      KJ_REQUIRE(ElementCount64(size) * wordsPerElement <= wordCount,
                  "INLINE_COMPOSITE list's elements overrun its word count.") {
         goto useDefault;
       }
 
       if (checkElementSize) {

Vulnerable code:             KJ_REQUIRE(elementTag->structRef.wordSize() / ELEMENTS * count <= wordCount,
          KJ_REQUIRE(wordsPerElement * elementCount <= wordCount,
      KJ_REQUIRE(size * wordsPerElement <= wordCount,
Fixed code:             KJ_REQUIRE(elementTag->structRef.wordSize() / ELEMENTS *
                       ElementCount64(count) <= wordCount,
          KJ_REQUIRE(wordsPerElement * ElementCount64(elementCount) <= wordCount,
      KJ_REQUIRE(ElementCount64(size) * wordsPerElement <= wordCount,