folly: ubsan: &v[0] is undefined if v.empty()
authorLucian Grijincu <lucian@fb.com>
Tue, 10 May 2016 00:03:34 +0000 (17:03 -0700)
committerFacebook Github Bot 8 <facebook-github-bot-8-bot@fb.com>
Tue, 10 May 2016 00:05:18 +0000 (17:05 -0700)
Summary:
before:

  [ RUN      ] RangeFunc.Vector
  bits/stl_vector.h:866:9: runtime error: reference binding to null pointer of type 'int'

Reviewed By: yfeldblum

Differential Revision: D3279253

fbshipit-source-id: 957a8ec050f5c3b27febf7e6cd16ad1d307da169

folly/test/RangeTest.cpp

index 42a76ac5e2f9bd98d4c77a5511d673a756d56790..49830d7ce236e6d3f7f401ad5b19b2b74351f4bc 100644 (file)
@@ -1049,6 +1049,19 @@ TEST(NonConstTest, StringPiece) {
   }
 }
 
+// Similar to the begin() template functions, but instread of returing
+// an iterator, return a pointer to data.
+template <class Container>
+typename Container::value_type* dataPtr(Container& cont) {
+  // NOTE: &cont[0] is undefined if cont is empty (it creates a
+  // reference to nullptr - which is not dereferenced, but still UBSAN).
+  return cont.data();
+}
+template <class T, size_t N>
+constexpr T* dataPtr(T (&arr)[N]) noexcept {
+  return &arr[0];
+}
+
 template<class C>
 void testRangeFunc(C&& x, size_t n) {
   const auto& cx = x;
@@ -1057,8 +1070,8 @@ void testRangeFunc(C&& x, size_t n) {
   Range<const int*> r2 = range(std::forward<C>(x));
   Range<const int*> r3 = range(cx);
   Range<const int*> r5 = range(std::move(cx));
-  EXPECT_EQ(r1.begin(), &x[0]);
-  EXPECT_EQ(r1.end(), &x[n]);
+  EXPECT_EQ(r1.begin(), dataPtr(x));
+  EXPECT_EQ(r1.end(), dataPtr(x) + n);
   EXPECT_EQ(n, r1.size());
   EXPECT_EQ(n, r2.size());
   EXPECT_EQ(n, r3.size());