]> granicus.if.org Git - re2c/commitdiff
Fixed out-of-bounds write caused by misuse of slab allocator in case of large allocat...
authorUlya Trofimovich <skvadrik@gmail.com>
Fri, 4 Jan 2019 12:54:03 +0000 (12:54 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Fri, 4 Jan 2019 13:14:23 +0000 (13:14 +0000)
This fixes bug #238.
Found by american fuzzy lop (thanks to Henri Salo).

re2c/src/dfa/determinization.h
re2c/src/dfa/tcmd.h
re2c/src/re/re.h
re2c/src/util/slab_allocator.h

index cd90298f1a255c5b78e32877b05a126c9ce89bc4..7a23d6a9a5cfeb9d0098930e3e46a5ee8265373b 100644 (file)
@@ -27,7 +27,7 @@ struct dfa_t;
 struct tcmd_t;
 
 
-typedef slab_allocator_t<4 * 1024, 1024 * 1024, sizeof(void*)> allocator_t;
+typedef slab_allocator_t<1024 * 1024, sizeof(void*)> allocator_t;
 
 
 struct clos_t
index 46ce86fc756cded88e7edfe188cf8af074218c6a..0aadafdceefa2e626034f2f498edd642dac83ac9 100644 (file)
@@ -33,7 +33,7 @@ static const tcid_t TCID0 = 0;
 
 class tcpool_t
 {
-    typedef slab_allocator_t<~0u, 4096, sizeof(void*)> alc_t;
+    typedef slab_allocator_t<4096, sizeof(void*)> alc_t;
     typedef lookup_t<const tcmd_t*> index_t;
 
     alc_t alc;
index a75b56bfbce7c6d2852727f5161d96a0e70ea4a1..2c79c7f5b4bbe9e81ad362718f2733c2800ede0e 100644 (file)
@@ -15,7 +15,7 @@ namespace re2c
 
 struct RE
 {
-    typedef slab_allocator_t<~0u, 4096, sizeof(void*)> alc_t;
+    typedef slab_allocator_t<4096, sizeof(void*)> alc_t;
     enum type_t {NIL, SYM, ALT, CAT, ITER, TAG} type;
     union {
         const Range *sym;
index 50ca3797785afa02ed58a5712ed0e0836d63c50f..08faaa7ef973532d3fc9f84f2af102cd9be9f2fa 100644 (file)
@@ -8,15 +8,14 @@
 
 #include "src/util/forbid_copy.h"
 
+
 /*
  * Works nice for tiny POD objects (~30 bytes and lower)
  * WARNING: Does not free memory for distinct objects!
  *
  * Works ~20 times faster, than linux's glibc allocator :]
  */
-template<uint32_t MAXIMUM_INLINE = 4 * 1024,
-    uint32_t SLAB_SIZE = 1024 * 1024,
-    size_t ALIGN = 1>
+template<uint32_t SLAB_SIZE = 1024 * 1024, size_t ALIGN = 1>
 class slab_allocator_t
 {
     typedef std::vector<char*> slabs_t;
@@ -34,26 +33,27 @@ public:
     {
         char *result;
 
-        /* alignment */
-        size += ALIGN - size % ALIGN;
+        // alignment (we assume that malloc aligns depending on size)
+        size += ALIGN - (size % ALIGN);
 
-        /* very large objects */
-        if (size > MAXIMUM_INLINE) {
-            result = static_cast<char*>(malloc(size));
-            slabs_.push_back(result);
-            return result;
+        if (size <= static_cast<size_t>(current_slab_end_ - current_slab_)) {
+            // enough space in slab
+            result = current_slab_;
+            current_slab_ += size;
         }
-
-        /* no space in slab */
-        const size_t yet_in_slab = static_cast<size_t>(current_slab_end_ - current_slab_);
-        if (yet_in_slab < size) {
+        else if (size <= SLAB_SIZE / 4) {
+            // start new slab
             current_slab_ = static_cast<char*>(malloc(SLAB_SIZE));
             current_slab_end_ = current_slab_ + SLAB_SIZE;
             slabs_.push_back(current_slab_);
+            result = current_slab_;
+            current_slab_ += size;
+        }
+        else {
+            // large size; allocate standalone piece of memory
+            result = static_cast<char*>(malloc(size));
+            slabs_.push_back(result);
         }
-
-        result = current_slab_;
-        current_slab_ += size;
 
         return result;
     }