[overnet] Re-enable linearizer, receive_mode fuzzers (and fix bugs)

Test: ran unit tests, and fuzzer to find the bugs

Change-Id: I64bddc5e8ff1277b18a0d90bb6b2ff154c821aad
diff --git a/lib/overnet/BUILD.gn b/lib/overnet/BUILD.gn
index 0d2b7bd..d64a08f 100644
--- a/lib/overnet/BUILD.gn
+++ b/lib/overnet/BUILD.gn
@@ -60,9 +60,11 @@
 
 fuzz_package("overnet_fuzzers") {
   targets = [ 
-    "vocabulary:internal_list_fuzzer",
+    "datagram_stream:linearizer_fuzzer",
+    "datagram_stream:receive_mode_fuzzer",
     "protocol:routable_message_fuzzer",
     "packet_protocol:packet_protocol_fuzzer",
+    "vocabulary:internal_list_fuzzer",
   ]
   sanitizers = [ "asan" ]
   fuzz_host = true
diff --git a/lib/overnet/datagram_stream/BUILD.gn b/lib/overnet/datagram_stream/BUILD.gn
index bb67d77..a2234de 100644
--- a/lib/overnet/datagram_stream/BUILD.gn
+++ b/lib/overnet/datagram_stream/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/fuzzing/fuzzer.gni")
+
 ###############################################################################
 # AGGREGATE LIBRARIES
 
@@ -69,13 +71,17 @@
   ]
 }
 
-source_set("linearizer_fuzzer_helpers") {
+source_set("linearizer_fuzzer_lib") {
+  testonly = true
   sources = [
-    "linearizer_fuzzer_helpers.h",
+    "linearizer_fuzzer.h",
+    "linearizer_fuzzer.cc",
   ]
   deps = [
     ":linearizer",
     "//garnet/lib/overnet/vocabulary:optional",
+    "//garnet/lib/overnet/testing:test_timer",
+    "//garnet/lib/overnet/testing:trace_cout",
   ]
 }
 
@@ -86,12 +92,22 @@
   ]
   deps = [
     ":linearizer",
-    ":linearizer_fuzzer_helpers",
+    ":linearizer_fuzzer_lib",
     "//third_party/googletest:gmock",
     "//third_party/googletest:gtest",
   ]
 }
 
+fuzz_target("linearizer_fuzzer") {
+  testonly = true
+  sources = [
+    "linearizer_fuzzer_main.cc",
+  ]
+  deps = [
+    ":linearizer_fuzzer_lib",
+  ]
+}
+
 # receive_mode
 source_set("receive_mode") {
   sources = [
@@ -132,3 +148,14 @@
     "//third_party/googletest:gtest",
   ]
 }
+
+fuzz_target("receive_mode_fuzzer") {
+  testonly = true
+  sources = [
+    "receive_mode_fuzzer.cc",
+  ]
+  deps = [
+    ":receive_mode_fuzzer_helpers",
+    "//garnet/lib/overnet/protocol:varint",
+  ]
+}
diff --git a/lib/overnet/datagram_stream/linearizer.cc b/lib/overnet/datagram_stream/linearizer.cc
index 2984f16..8768ff7 100644
--- a/lib/overnet/datagram_stream/linearizer.cc
+++ b/lib/overnet/datagram_stream/linearizer.cc
@@ -83,6 +83,15 @@
     Close(Status(StatusCode::CANCELLED, "Gaps existed at close time"));
     return;
   }
+  if (status.is_ok() && !length_) {
+    Close(Status(StatusCode::CANCELLED, "Closed before end of message seen"));
+    return;
+  }
+  if (status.is_ok() && offset_ != *length_) {
+    Close(
+        Status(StatusCode::CANCELLED, "Closed before end of message reached"));
+    return;
+  }
   switch (read_mode_) {
     case ReadMode::Closed:
       break;
@@ -152,6 +161,7 @@
                      "Already received bytes past end of message"));
       }
     }
+    length_ = chunk_end;
     if (offset_ == chunk_end) {
       Close(Status::Ok());
     }
@@ -162,9 +172,8 @@
     return false;
   }
 
-  if (chunk.end_of_message && !length_) {
-    OVERNET_TRACE(DEBUG) << "Push: record length";
-    length_ = chunk_end;
+  if (chunk_end == chunk_start) {
+    return true;
   }
 
   // Fast path: already a pending read ready, this chunk is at the head of what
diff --git a/lib/overnet/datagram_stream/linearizer_fuzzer.cc b/lib/overnet/datagram_stream/linearizer_fuzzer.cc
index fa4b026..0a41b23 100644
--- a/lib/overnet/datagram_stream/linearizer_fuzzer.cc
+++ b/lib/overnet/datagram_stream/linearizer_fuzzer.cc
@@ -2,69 +2,100 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <vector>
-#include "linearizer_fuzzer_helpers.h"
+#include "linearizer_fuzzer.h"
 
-using namespace overnet;
+namespace overnet {
+namespace linearizer_fuzzer {
 
-namespace {
-class InputStream {
- public:
-  InputStream(const uint8_t* data, size_t size)
-      : cur_(data), end_(data + size) {}
-
-  uint8_t NextByte() {
-    if (cur_ == end_)
-      return 0;
-    return *cur_++;
-  }
-
-  uint16_t NextShort() {
-    uint16_t x = NextByte();
-    x <<= 8;
-    x |= NextByte();
-    return x;
-  }
-
-  const uint8_t* Block(size_t bytes) {
-    if (bytes > end_ - cur_) {
-      tail_.clear();
-      tail_.resize(bytes, 0);
-      memcpy(tail_.data(), cur_, end_ - cur_);
-      cur_ = end_;
-      return tail_.data();
-    }
-    const uint8_t* out = cur_;
-    cur_ += bytes;
-    return out;
-  }
-
- private:
-  const uint8_t* cur_;
-  const uint8_t* end_;
-  std::vector<uint8_t> tail_;
-};
-}  // namespace
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  InputStream input(data, size);
-  linearizer_fuzzer::LinearizerFuzzer fuzzer;
-
-  for (;;) {
-    uint8_t op = input.NextByte();
-    if (op == 0) {
-      return 0;
-    } else if (op == 1) {
-      fuzzer.Close(input.NextByte());
-    } else if (op == 2) {
-      fuzzer.Pull();
+// Close the linearizer with some status code.
+void LinearizerFuzzer::Close(uint8_t status_code) {
+  if (status_code == 0) {
+    if (!length_.has_value()) {
+      status_code = 1;
+    } else if (offset_ != *length_) {
+      status_code = 1;
     } else {
-      uint8_t len = op - 2;
-      assert(len >= 1);
-      bool eom = (len & 1) != 0;
-      len >>= 1;
-      uint16_t offset = input.NextShort();
-      fuzzer.Push(offset, len, eom, input.Block(len));
+      for (uint64_t i = 0; i < *length_; i++) {
+        if (!bytes_[i].present) {
+          status_code = 1;
+        }
+      }
     }
   }
+  SetClosed(static_cast<StatusCode>(status_code));
+  linearizer_.Close(static_cast<StatusCode>(status_code));
 }
+
+// Push a new block onto the linearizer at offset 'offset', with length
+// 'length', an end_of_message flag, and data bytes in 'data'.
+void LinearizerFuzzer::Push(uint16_t offset, uint8_t length,
+                            bool end_of_message, const uint8_t* data) {
+  uint64_t last_byte = static_cast<uint64_t>(offset) + length;
+  const bool resource_exhausted = last_byte > offset_ + kBuffer;
+  if (!resource_exhausted) {
+    if (length_) {
+      if (last_byte > *length_) {
+        SetClosed(StatusCode::INVALID_ARGUMENT);
+      } else if (end_of_message && *length_ != last_byte) {
+        SetClosed(StatusCode::INVALID_ARGUMENT);
+      }
+    } else if (end_of_message) {
+      if (offset_ > last_byte)
+        SetClosed(StatusCode::INVALID_ARGUMENT);
+      for (unsigned i = last_byte; i < sizeof(bytes_) / sizeof(*bytes_); i++) {
+        if (bytes_[i].present)
+          SetClosed(StatusCode::INVALID_ARGUMENT);
+      }
+      if (offset_ == last_byte)
+        SetClosed(StatusCode::OK);
+      length_ = last_byte;
+    }
+    for (unsigned i = 0; i < length; i++) {
+      unsigned idx = i + offset;
+      ByteState& st = bytes_[idx];
+      if (st.present) {
+        if (st.byte != data[i] && idx >= offset_) {
+          SetClosed(StatusCode::DATA_LOSS);
+        }
+      } else {
+        st.byte = data[i];
+        st.present = true;
+      }
+    }
+  }
+  auto ignore = [](bool) {};
+  ignore(linearizer_.Push(
+      Chunk{offset, end_of_message, Slice::FromCopiedBuffer(data, length)}));
+}
+
+// Execute a pull op on the linearizer, and verify that it's as expected.
+void LinearizerFuzzer::Pull() {
+  if (waiting_for_pull_)
+    return;
+  waiting_for_pull_ = true;
+  linearizer_.Pull(StatusOrCallback<Optional<Slice>>(
+      [this](const StatusOr<Optional<Slice>>& status) {
+        assert(waiting_for_pull_);
+        waiting_for_pull_ = false;
+#ifndef NDEBUG
+        if (is_closed_) {
+          assert(status.code() == closed_status_);
+        } else {
+          assert(status.is_ok());
+          if (*status) {
+            for (auto b : **status) {
+              ByteState st = bytes_[offset_++];
+              assert(st.present);
+              assert(b == st.byte);
+            }
+          }
+          if (length_ && *length_ == offset_) {
+            SetClosed(StatusCode::OK);
+          }
+        }
+#endif
+      }));
+}
+
+}  // namespace linearizer_fuzzer
+}  // namespace overnet
diff --git a/lib/overnet/datagram_stream/linearizer_fuzzer.h b/lib/overnet/datagram_stream/linearizer_fuzzer.h
new file mode 100644
index 0000000..f38a13e
--- /dev/null
+++ b/lib/overnet/datagram_stream/linearizer_fuzzer.h
@@ -0,0 +1,69 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+#include "garnet/lib/overnet/testing/test_timer.h"
+#include "garnet/lib/overnet/testing/trace_cout.h"
+#include "garnet/lib/overnet/vocabulary/optional.h"
+#include "linearizer.h"
+
+namespace overnet {
+namespace linearizer_fuzzer {
+
+// Main fuzzer logic... to be used in the fuzzer itself, and in unit tests.
+// Includes a simple but inefficient emulation of what the real linearizer does
+// efficiently, and compares that the obtained results are identical.
+class LinearizerFuzzer {
+ public:
+  static constexpr inline uint64_t kBuffer = 1024;
+
+  LinearizerFuzzer(bool log_stuff)
+      : logging_(log_stuff ? new Logging(&timer_) : nullptr) {}
+
+  ~LinearizerFuzzer() { SetClosed(StatusCode::CANCELLED); }
+
+  // Close the linearizer with some status code.
+  void Close(uint8_t status_code);
+
+  // Push a new block onto the linearizer at offset 'offset', with length
+  // 'length', an end_of_message flag, and data bytes in 'data'.
+  void Push(uint16_t offset, uint8_t length, bool end_of_message,
+            const uint8_t* data);
+
+  // Execute a pull op on the linearizer, and verify that it's as expected.
+  void Pull();
+
+ private:
+  void SetClosed(StatusCode status_code) {
+    if (!is_closed_) {
+      is_closed_ = true;
+      closed_status_ = status_code;
+    }
+  }
+
+  struct ByteState {
+    bool present = false;
+    uint8_t byte = 0;
+  };
+
+  TestTimer timer_;
+  struct Logging {
+    Logging(Timer* timer) : tracer(timer) {}
+    TraceCout tracer;
+    ScopedRenderer set_tracer{&tracer};
+  };
+  std::unique_ptr<Logging> logging_;
+
+  uint64_t offset_ = 0;
+  Optional<uint64_t> length_;
+  ByteState bytes_[(1 << 16) + (1 << 8)];
+  bool is_closed_ = false;
+  StatusCode closed_status_;
+  bool waiting_for_pull_ = false;
+
+  Linearizer linearizer_{kBuffer};
+};
+
+}  // namespace linearizer_fuzzer
+}  // namespace overnet
diff --git a/lib/overnet/datagram_stream/linearizer_fuzzer_corpus_to_code.py b/lib/overnet/datagram_stream/linearizer_fuzzer_corpus_to_code.py
index fe12856..4b385b1 100755
--- a/lib/overnet/datagram_stream/linearizer_fuzzer_corpus_to_code.py
+++ b/lib/overnet/datagram_stream/linearizer_fuzzer_corpus_to_code.py
@@ -38,7 +38,7 @@
 
 
 print 'TEST(LinearizerFuzzed, _%s) {' % hashlib.sha1(inp).hexdigest()
-print '  linearizer_fuzzer::LinearizerFuzzer m;'
+print '  linearizer_fuzzer::LinearizerFuzzer m(true);'
 block_idx = 0
 while True:
     op = next_byte()
diff --git a/lib/overnet/datagram_stream/linearizer_fuzzer_helpers.h b/lib/overnet/datagram_stream/linearizer_fuzzer_helpers.h
deleted file mode 100644
index bfb2d31..0000000
--- a/lib/overnet/datagram_stream/linearizer_fuzzer_helpers.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <vector>
-#include "garnet/lib/overnet/vocabulary/optional.h"
-#include "linearizer.h"
-
-namespace overnet {
-namespace linearizer_fuzzer {
-
-// Main fuzzer logic... to be used in the fuzzer itself, and in unit tests
-class LinearizerFuzzer {
- public:
-  static const uint64_t kBuffer = 1024;
-
-  ~LinearizerFuzzer() { SetClosed(StatusCode::CANCELLED); }
-
-  void Close(uint8_t status_code) {
-    SetClosed(static_cast<StatusCode>(status_code));
-    linearizer_.Close(static_cast<StatusCode>(status_code));
-  }
-
-  void Push(uint16_t offset, uint8_t length, bool end_of_message,
-            const uint8_t* data) {
-    uint64_t last_byte = static_cast<uint64_t>(offset) + length;
-    const bool resource_exhausted = last_byte > offset_ + kBuffer;
-    if (!resource_exhausted) {
-      if (length_) {
-        if (last_byte > *length_) {
-          SetClosed(StatusCode::INVALID_ARGUMENT);
-        } else if (end_of_message && *length_ != last_byte) {
-          SetClosed(StatusCode::INVALID_ARGUMENT);
-        }
-      } else if (end_of_message) {
-        if (offset_ > last_byte)
-          SetClosed(StatusCode::INVALID_ARGUMENT);
-        for (unsigned i = last_byte; i < sizeof(bytes_) / sizeof(*bytes_);
-             i++) {
-          if (bytes_[i].present)
-            SetClosed(StatusCode::INVALID_ARGUMENT);
-        }
-        if (offset_ == last_byte)
-          SetClosed(StatusCode::OK);
-        length_ = last_byte;
-      }
-      for (unsigned i = 0; i < length; i++) {
-        unsigned idx = i + offset;
-        ByteState& st = bytes_[idx];
-        if (st.present) {
-          if (st.byte != data[i] && idx >= offset_) {
-            SetClosed(StatusCode::DATA_LOSS);
-          }
-        } else {
-          st.byte = data[i];
-          st.present = true;
-        }
-      }
-    }
-    auto ignore = [](bool) {};
-    ignore(linearizer_.Push(
-        Chunk{offset, end_of_message, Slice::FromCopiedBuffer(data, length)}));
-  }
-
-  void Pull() {
-    if (waiting_for_pull_)
-      return;
-    waiting_for_pull_ = true;
-    linearizer_.Pull(StatusOrCallback<Optional<Slice>>(
-        [this](const StatusOr<Optional<Slice>>& status) {
-          assert(waiting_for_pull_);
-          waiting_for_pull_ = false;
-#ifndef NDEBUG
-          if (is_closed_) {
-            assert(status.code() == closed_status_);
-          } else {
-            assert(status.is_ok());
-            if (*status) {
-              for (auto b : **status) {
-                ByteState st = bytes_[offset_++];
-                assert(st.present);
-                assert(b == st.byte);
-              }
-            }
-            if (length_ && *length_ == offset_) {
-              SetClosed(StatusCode::OK);
-            }
-          }
-#endif
-        }));
-  }
-
- private:
-  void SetClosed(StatusCode status_code) {
-    if (!is_closed_) {
-      is_closed_ = true;
-      closed_status_ = status_code;
-    }
-  }
-
-  struct ByteState {
-    bool present = false;
-    uint8_t byte = 0;
-  };
-  uint64_t offset_ = 0;
-  Optional<uint64_t> length_;
-  ByteState bytes_[(1 << 16) + (1 << 8)];
-  bool is_closed_ = false;
-  StatusCode closed_status_;
-  bool waiting_for_pull_ = false;
-
-  Linearizer linearizer_{kBuffer};
-};
-
-}  // namespace linearizer_fuzzer
-}  // namespace overnet
diff --git a/lib/overnet/datagram_stream/linearizer_fuzzer_main.cc b/lib/overnet/datagram_stream/linearizer_fuzzer_main.cc
new file mode 100644
index 0000000..4a90f56
--- /dev/null
+++ b/lib/overnet/datagram_stream/linearizer_fuzzer_main.cc
@@ -0,0 +1,71 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+#include "linearizer_fuzzer.h"
+
+using namespace overnet;
+
+namespace {
+class InputStream {
+ public:
+  InputStream(const uint8_t* data, size_t size)
+      : cur_(data), end_(data + size) {}
+
+  uint8_t NextByte() {
+    if (cur_ == end_)
+      return 0;
+    return *cur_++;
+  }
+
+  uint16_t NextShort() {
+    uint16_t x = NextByte();
+    x <<= 8;
+    x |= NextByte();
+    return x;
+  }
+
+  const uint8_t* Block(size_t bytes) {
+    if (bytes > size_t(end_ - cur_)) {
+      tail_.clear();
+      tail_.resize(bytes, 0);
+      memcpy(tail_.data(), cur_, end_ - cur_);
+      cur_ = end_;
+      return tail_.data();
+    }
+    const uint8_t* out = cur_;
+    cur_ += bytes;
+    return out;
+  }
+
+ private:
+  const uint8_t* cur_;
+  const uint8_t* end_;
+  std::vector<uint8_t> tail_;
+};
+}  // namespace
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  InputStream input(data, size);
+  // Instantiate fuzzer without logging.
+  linearizer_fuzzer::LinearizerFuzzer fuzzer(false);
+
+  for (;;) {
+    uint8_t op = input.NextByte();
+    if (op == 0) {
+      return 0;
+    } else if (op == 1) {
+      fuzzer.Close(input.NextByte());
+    } else if (op == 2) {
+      fuzzer.Pull();
+    } else {
+      uint8_t len = op - 2;
+      assert(len >= 1);
+      bool eom = (len & 1) != 0;
+      len >>= 1;
+      uint16_t offset = input.NextShort();
+      fuzzer.Push(offset, len, eom, input.Block(len));
+    }
+  }
+}
diff --git a/lib/overnet/datagram_stream/linearizer_test.cc b/lib/overnet/datagram_stream/linearizer_test.cc
index 4756fd6..5ac1f0a 100644
--- a/lib/overnet/datagram_stream/linearizer_test.cc
+++ b/lib/overnet/datagram_stream/linearizer_test.cc
@@ -5,7 +5,7 @@
 #include "linearizer.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-#include "linearizer_fuzzer_helpers.h"
+#include "linearizer_fuzzer.h"
 
 using testing::InSequence;
 using testing::Mock;
@@ -308,14 +308,14 @@
 //            (also, fix it)
 
 TEST(LinearizerFuzzed, _adc83b19e793491b1c6ea0fd8b46cd9f32e592fc) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00};
   m.Push(0, 8, false, block0);
 }
 
 TEST(LinearizerFuzzed, _a3761115222a684a7e0ec40d2ddd601f3815dbb0) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00};
   m.Push(0, 8, false, block0);
@@ -333,7 +333,7 @@
 }
 
 TEST(LinearizerFuzzed, _7513024e0ab94a294598985655ca34ca4113f1f7) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Close(0);
   static const uint8_t block0[] = {0x00};
   m.Push(226, 1, false, block0);
@@ -349,7 +349,7 @@
 }
 
 TEST(LinearizerFuzzed, _399d8fb423eea52f471c33784d3f981a634355d5) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Close(0);
   static const uint8_t block0[] = {0x00};
   m.Push(226, 1, false, block0);
@@ -378,7 +378,7 @@
 }
 
 TEST(LinearizerFuzzed, _dd43cb933e2c52c84b6d6f7279f6b1f49b9ecede) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Pull();
   static const uint8_t block0[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
                                    0xff, 0xd2, 0xff, 0xff, 0xff, 0xff};
@@ -389,7 +389,7 @@
 }
 
 TEST(LinearizerFuzzed, _946ff8cb484b160bf4e251212902c5e4b8b70f7b) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Pull();
   m.Pull();
   m.Pull();
@@ -398,7 +398,7 @@
 
 // Crashed fuzzer helpers
 TEST(LinearizerFuzzed, _025df41aed0b045a155f753a02991a564f5b7516) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {0x02, 0x02, 0x02, 0x02,
                                    0x02, 0x02, 0x02, 0x02};
   m.Push(2, 8, false, block0);
@@ -457,7 +457,7 @@
 }
 
 TEST(LinearizerFuzzed, _a769cfc3afa79bf00b5dc4a4413dfe1690c9e41b) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {0x00, 0xff, 0xff, 0x20,
                                    0x10, 0x01, 0xfe, 0x20};
   m.Push(105, 8, false, block0);
@@ -544,7 +544,7 @@
 
 // Caught off-by-one in ValidateInternals
 TEST(LinearizerFuzzed, _d7ecc6236a8732fb747f193116229534abdad5d4) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {0x00, 0xff, 0xff, 0x20,
                                    0x00, 0x01, 0xfe, 0xf9};
   m.Push(105, 8, false, block0);
@@ -656,7 +656,7 @@
 
 // Exposed some growing pains in end-of-message handling.
 TEST(LinearizerFuzzed, _ec62acf518af13e50b6accce7768ce52619cb9dd) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {};
   m.Push(8970, 0, true, block0);
   static const uint8_t block1[] = {};
@@ -665,7 +665,7 @@
 
 // Exposed some growing pains in end-of-message handling.
 TEST(LinearizerFuzzed, _85e53271e14006f0265921d02d4d736cdc580b0b) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -682,14 +682,14 @@
 }
 
 TEST(LinearizerFuzzed, _2215d90c8d9b57557cdd6c736ba44d5fd5b41869) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Pull();
   static const uint8_t block0[] = {};
   m.Push(0, 0, true, block0);
 }
 
 TEST(LinearizerFuzzed, _a830b81a5fd181534360433a63f58974d52c2d4b) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   static const uint8_t block0[] = {};
   m.Push(0, 0, true, block0);
   static const uint8_t block1[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -699,7 +699,7 @@
 }
 
 TEST(LinearizerFuzzed, _4c631f1b91d2df163096fc841f1dcc70cd4c6070) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Pull();
   static const uint8_t block0[] = {0x15, 0x02, 0x02, 0x02};
   m.Push(0, 4, true, block0);
@@ -722,7 +722,7 @@
 }
 
 TEST(LinearizerFuzzed, _f343b14aef72b93b6f83247b96a2ab7637327bad) {
-  linearizer_fuzzer::LinearizerFuzzer m;
+  linearizer_fuzzer::LinearizerFuzzer m(true);
   m.Pull();
   static const uint8_t block0[] = {
       0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x02, 0x02, 0x02, 0x02, 0x02,
@@ -741,5 +741,32 @@
   // Snipped: crash happens before here.
 }
 
+TEST(LinearizerFuzzed, _46357bce24897bd14d816a821493486337da509b) {
+  linearizer_fuzzer::LinearizerFuzzer m(true);
+  m.Pull();
+  m.Pull();
+  m.Pull();
+  static const uint8_t block0[] = {};
+  m.Push(256, 0, true, block0);
+  m.Close(0);
+}
+
+TEST(LinearizerFuzzed, _aa850f8180e69f68c4979a5abe56a18610a6f222) {
+  linearizer_fuzzer::LinearizerFuzzer m(true);
+  static const uint8_t block0[] = {0x41};
+  m.Push(0, 1, false, block0);
+  static const uint8_t block1[] = {};
+  m.Push(1, 0, true, block1);
+  m.Pull();
+  m.Pull();
+  m.Pull();
+  static const uint8_t block2[] = {
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  m.Push(0, 48, false, block2);
+}
+
 }  // namespace linearizer_test
 }  // namespace overnet
diff --git a/lib/overnet/datagram_stream/receive_mode_fuzzer.cc b/lib/overnet/datagram_stream/receive_mode_fuzzer.cc
index ac18d62..e2986bd 100644
--- a/lib/overnet/datagram_stream/receive_mode_fuzzer.cc
+++ b/lib/overnet/datagram_stream/receive_mode_fuzzer.cc
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include <unordered_set>
+#include "garnet/lib/overnet/protocol/varint.h"
 #include "receive_mode_fuzzer_helpers.h"
-#include "varint.h"
 
 using namespace overnet;