Hello community,

here is the log from the commit of package re2 for openSUSE:Factory checked in 
at 2017-07-30 11:27:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/re2 (Old)
 and      /work/SRC/openSUSE:Factory/.re2.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "re2"

Sun Jul 30 11:27:26 2017 rev:9 rq:513010 version:MACRO

Changes:
--------
--- /work/SRC/openSUSE:Factory/re2/re2.changes  2017-06-13 16:09:00.739007915 
+0200
+++ /work/SRC/openSUSE:Factory/.re2.new/re2.changes     2017-07-30 
11:27:40.606882316 +0200
@@ -1,0 +2,6 @@
+Sat Jul 29 10:04:51 UTC 2017 - [email protected]
+
+- Update to version 2017-07-01
+  * No upstream changelog available 
+
+-------------------------------------------------------------------

Old:
----
  2017-06-01.tar.gz

New:
----
  2017-07-01.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ re2.spec ++++++
--- /var/tmp/diff_new_pack.3rrwPB/_old  2017-07-30 11:27:41.274788071 +0200
+++ /var/tmp/diff_new_pack.3rrwPB/_new  2017-07-30 11:27:41.282786942 +0200
@@ -16,7 +16,7 @@
 #
 
 
-%global longver 2017-06-01
+%global longver 2017-07-01
 %global shortver %(echo %{longver}|sed 's|-||g')
 %define libname libre2-0
 Name:           re2
@@ -90,12 +90,10 @@
 %postun -n %{libname} -p /sbin/ldconfig
 
 %files -n %{libname}
-%defattr(-,root,root)
 %doc LICENSE AUTHORS CONTRIBUTORS README
 %{_libdir}/lib%{name}.so.*
 
 %files devel
-%defattr(-,root,root)
 %{_includedir}/%{name}
 %{_libdir}/lib%{name}.so
 %{_libdir}/pkgconfig/%{name}.pc

++++++ 2017-06-01.tar.gz -> 2017-07-01.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/re2/dfa.cc 
new/re2-2017-07-01/re2/dfa.cc
--- old/re2-2017-06-01/re2/dfa.cc       2017-05-18 07:20:04.000000000 +0200
+++ new/re2-2017-07-01/re2/dfa.cc       2017-06-27 14:55:46.000000000 +0200
@@ -27,10 +27,12 @@
 #include <string.h>
 #include <algorithm>
 #include <atomic>
+#include <deque>
 #include <map>
 #include <mutex>
 #include <new>
 #include <string>
+#include <unordered_map>
 #include <unordered_set>
 #include <utility>
 #include <vector>
@@ -96,9 +98,11 @@
               bool anchored, bool want_earliest_match, bool run_forward,
               bool* failed, const char** ep, std::vector<int>* matches);
 
-  // Builds out all states for the entire DFA.  FOR TESTING ONLY
-  // Returns number of states.
-  int BuildAllStates();
+  // Builds out all states for the entire DFA.
+  // If cb is not empty, it receives one callback per state built.
+  // Returns the number of states built.
+  // FOR TESTING OR EXPERIMENTAL PURPOSES ONLY.
+  int BuildAllStates(const Prog::DFAStateCallback& cb);
 
   // Computes min and max for matching strings.  Won't return strings
   // bigger than maxlen.
@@ -1883,7 +1887,7 @@
 }
 
 // Build out all states in DFA.  Returns number of states.
-int DFA::BuildAllStates() {
+int DFA::BuildAllStates(const Prog::DFAStateCallback& cb) {
   if (!ok())
     return 0;
 
@@ -1892,34 +1896,67 @@
   RWLocker l(&cache_mutex_);
   SearchParams params(StringPiece(), StringPiece(), &l);
   params.anchored = false;
-  if (!AnalyzeSearch(&params) || params.start <= SpecialStateMax)
+  if (!AnalyzeSearch(&params) ||
+      params.start == NULL ||
+      params.start == DeadState)
     return 0;
 
   // Add start state to work queue.
-  StateSet queued;
-  std::vector<State*> q;
-  queued.insert(params.start);
+  // Note that any State* that we handle here must point into the cache,
+  // so we can simply depend on pointer-as-a-number hashing and equality.
+  std::unordered_map<State*, int> m;
+  std::deque<State*> q;
+  m.emplace(params.start, static_cast<int>(m.size()));
   q.push_back(params.start);
 
+  // Compute the input bytes needed to cover all of the next pointers.
+  int nnext = prog_->bytemap_range() + 1;  // + 1 for kByteEndText slot
+  std::vector<int> input(nnext);
+  for (int c = 0; c < 256; c++) {
+    int b = prog_->bytemap()[c];
+    while (c < 256-1 && prog_->bytemap()[c+1] == b)
+      c++;
+    input[b] = c;
+  }
+  input[prog_->bytemap_range()] = kByteEndText;
+
+  // Scratch space for the output.
+  std::vector<int> output(nnext);
+
   // Flood to expand every state.
-  for (size_t i = 0; i < q.size(); i++) {
-    State* s = q[i];
-    for (int c = 0; c < 257; c++) {
+  bool oom = false;
+  while (!q.empty()) {
+    State* s = q.front();
+    q.pop_front();
+    for (int c : input) {
       State* ns = RunStateOnByteUnlocked(s, c);
-      if (ns > SpecialStateMax && queued.find(ns) == queued.end()) {
-        queued.insert(ns);
+      if (ns == NULL) {
+        oom = true;
+        break;
+      }
+      if (ns == DeadState) {
+        output[ByteMap(c)] = -1;
+        continue;
+      }
+      if (m.find(ns) == m.end()) {
+        m.emplace(ns, static_cast<int>(m.size()));
         q.push_back(ns);
       }
+      output[ByteMap(c)] = m[ns];
     }
+    if (cb)
+      cb(oom ? NULL : output.data(),
+         s == FullMatchState || s->IsMatch());
+    if (oom)
+      break;
   }
 
-  return static_cast<int>(q.size());
+  return static_cast<int>(m.size());
 }
 
 // Build out all states in DFA for kind.  Returns number of states.
-int Prog::BuildEntireDFA(MatchKind kind) {
-  //LOG(ERROR) << "BuildEntireDFA is only for testing.";
-  return GetDFA(kind)->BuildAllStates();
+int Prog::BuildEntireDFA(MatchKind kind, const DFAStateCallback& cb) {
+  return GetDFA(kind)->BuildAllStates(cb);
 }
 
 void Prog::TEST_dfa_should_bail_when_slow(bool b) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/re2/nfa.cc 
new/re2-2017-07-01/re2/nfa.cc
--- old/re2-2017-06-01/re2/nfa.cc       2017-05-18 07:20:04.000000000 +0200
+++ new/re2-2017-07-01/re2/nfa.cc       2017-06-27 14:55:46.000000000 +0200
@@ -102,8 +102,8 @@
 
   // Run runq on byte c, appending new states to nextq.
   // Updates matched_ and match_ as new, better matches are found.
-  // p is the position of the previous byte (the one before c)
-  // in the input string, used when processing Match instructions.
+  // p is the position of byte c in the input string for AddToThreadq;
+  // p-1 will be used when processing Match instructions.
   // flag is the bitwise OR of Bol, Eol, etc., specifying whether
   // ^, $ and \b match the current input position (after c).
   // Frees all the threads on runq.
@@ -328,8 +328,8 @@
 
 // Run runq on byte c, appending new states to nextq.
 // Updates matched_ and match_ as new, better matches are found.
-// p is the position of the previous byte (the one before c)
-// in the input string, used when processing Match instructions.
+// p is the position of byte c in the input string for AddToThreadq;
+// p-1 will be used when processing Match instructions.
 // flag is the bitwise OR of Bol, Eol, etc., specifying whether
 // ^, $ and \b match the current input position (after c).
 // Frees all the threads on runq.
@@ -360,7 +360,7 @@
         break;
 
       case kInstByteRange:
-        AddToThreadq(nextq, ip->out(), c, flag, p+1, t);
+        AddToThreadq(nextq, ip->out(), c, flag, p, t);
         break;
 
       case kInstAltMatch:
@@ -381,8 +381,13 @@
         }
         break;
 
-      case kInstMatch:
-        if (endmatch_ && p != etext_)
+      case kInstMatch: {
+        // Avoid invoking undefined behavior when p happens
+        // to be null - and p-1 would be meaningless anyway.
+        if (p == NULL)
+          break;
+
+        if (endmatch_ && p-1 != etext_)
           break;
 
         if (longest_) {
@@ -390,16 +395,16 @@
           // it is either farther to the left or at the same
           // point but longer than an existing match.
           if (!matched_ || t->capture[0] < match_[0] ||
-              (t->capture[0] == match_[0] && p > match_[1])) {
+              (t->capture[0] == match_[0] && p-1 > match_[1])) {
             CopyCapture(match_, t->capture);
-            match_[1] = p;
+            match_[1] = p-1;
             matched_ = true;
           }
         } else {
           // Leftmost-biased mode: this match is by definition
           // better than what we've already found (see next line).
           CopyCapture(match_, t->capture);
-          match_[1] = p;
+          match_[1] = p-1;
           matched_ = true;
 
           // Cut off the threads that can only find matches
@@ -412,6 +417,7 @@
           return 0;
         }
         break;
+      }
     }
     Decref(t);
   }
@@ -546,12 +552,8 @@
       fprintf(stderr, "\n");
     }
 
-    // Note that we pass p-1 to Step() because it needs the previous pointer
-    // value in order to handle Match instructions appropriately. It plumbs
-    // c and flag through to AddToThreadq() along with p-1+1, which is p.
-    //
     // This is a no-op the first time around the loop because runq is empty.
-    int id = Step(runq, nextq, p < text.end() ? p[0] & 0xFF : -1, flag, p-1);
+    int id = Step(runq, nextq, p < text.end() ? p[0] & 0xFF : -1, flag, p);
     DCHECK_EQ(runq->size(), 0);
     using std::swap;
     swap(nextq, runq);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/re2/prog.cc 
new/re2-2017-07-01/re2/prog.cc
--- old/re2-2017-06-01/re2/prog.cc      2017-05-18 07:20:04.000000000 +0200
+++ new/re2-2017-07-01/re2/prog.cc      2017-06-27 14:55:46.000000000 +0200
@@ -540,7 +540,7 @@
 // dominator of the instructions reachable from some "successor root" (i.e. it
 // has an unreachable predecessor) and is considered a "dominator root". Since
 // only Alt instructions can be "dominator roots" (other instructions would be
-// "leaves"), only Alt instructions require their predecessors to be computed.
+// "leaves"), only Alt instructions are required to be marked as predecessors.
 //
 // Dividing the Prog into "trees" comprises two passes: marking the "successor
 // roots" and the predecessors; and marking the "dominator roots". Sorting the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/re2/prog.h 
new/re2-2017-07-01/re2/prog.h
--- old/re2-2017-06-01/re2/prog.h       2017-05-18 07:20:04.000000000 +0200
+++ new/re2-2017-07-01/re2/prog.h       2017-06-27 14:55:46.000000000 +0200
@@ -10,6 +10,7 @@
 // expression symbolically.
 
 #include <stdint.h>
+#include <functional>
 #include <mutex>
 #include <string>
 #include <vector>
@@ -256,11 +257,22 @@
                  Anchor anchor, MatchKind kind, StringPiece* match0,
                  bool* failed, std::vector<int>* matches);
 
-  // Build the entire DFA for the given match kind.  FOR TESTING ONLY.
+  // The callback issued after building each DFA state with BuildEntireDFA().
+  // If next is null, then the memory budget has been exhausted and building
+  // will halt. Otherwise, the state has been built and next points to an array
+  // of bytemap_range()+1 slots holding the next states as per the bytemap and
+  // kByteEndText. The number of the state is implied by the callback sequence:
+  // the first callback is for state 0, the second callback is for state 1, ...
+  // match indicates whether the state is a matching state.
+  using DFAStateCallback = std::function<void(const int* next, bool match)>;
+
+  // Build the entire DFA for the given match kind.
   // Usually the DFA is built out incrementally, as needed, which
-  // avoids lots of unnecessary work.  This function is useful only
-  // for testing purposes.  Returns number of states.
-  int BuildEntireDFA(MatchKind kind);
+  // avoids lots of unnecessary work.
+  // If cb is not empty, it receives one callback per state built.
+  // Returns the number of states built.
+  // FOR TESTING OR EXPERIMENTAL PURPOSES ONLY.
+  int BuildEntireDFA(MatchKind kind, const DFAStateCallback& cb);
 
   // Controls whether the DFA should bail out early if the NFA would be faster.
   // FOR TESTING ONLY.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/re2/testing/dfa_test.cc 
new/re2-2017-07-01/re2/testing/dfa_test.cc
--- old/re2-2017-06-01/re2/testing/dfa_test.cc  2017-05-18 07:20:04.000000000 
+0200
+++ new/re2-2017-07-01/re2/testing/dfa_test.cc  2017-06-27 14:55:46.000000000 
+0200
@@ -28,7 +28,7 @@
 
 // Helper function: builds entire DFA for prog.
 static void DoBuild(Prog* prog) {
-  CHECK(prog->BuildEntireDFA(Prog::kFirstMatch));
+  CHECK(prog->BuildEntireDFA(Prog::kFirstMatch, nullptr));
 }
 
 TEST(Multithreaded, BuildEntireDFA) {
@@ -63,7 +63,7 @@
       threads[j].join();
 
     // One more compile, to make sure everything is okay.
-    prog->BuildEntireDFA(Prog::kFirstMatch);
+    prog->BuildEntireDFA(Prog::kFirstMatch, nullptr);
     delete prog;
   }
 
@@ -88,8 +88,8 @@
       CHECK(prog);
       //progusage = m.HeapGrowth();
       //dfamem = prog->dfa_mem();
-      prog->BuildEntireDFA(Prog::kFirstMatch);
-      prog->BuildEntireDFA(Prog::kLongestMatch);
+      prog->BuildEntireDFA(Prog::kFirstMatch, nullptr);
+      prog->BuildEntireDFA(Prog::kLongestMatch, nullptr);
       usage = m.HeapGrowth();
       delete prog;
     }
@@ -279,8 +279,8 @@
 }
 
 struct ReverseTest {
-  const char *regexp;
-  const char *text;
+  const char* regexp;
+  const char* text;
   bool match;
 };
 
@@ -299,7 +299,7 @@
     const ReverseTest& t = reverse_tests[i];
     Regexp* re = Regexp::Parse(t.regexp, Regexp::LikePerl, NULL);
     CHECK(re);
-    Prog *prog = re->CompileToReverseProg(0);
+    Prog* prog = re->CompileToReverseProg(0);
     CHECK(prog);
     bool failed = false;
     bool matched = prog->SearchDFA(t.text, StringPiece(), Prog::kUnanchored,
@@ -309,6 +309,70 @@
       nfail++;
     }
     delete prog;
+    re->Decref();
+  }
+  EXPECT_EQ(nfail, 0);
+}
+
+struct CallbackTest {
+  const char* regexp;
+  const char* dump;
+};
+
+// Test that DFA::BuildAllStates() builds the expected DFA states
+// and issues the expected callbacks. These test cases reflect the
+// very compact encoding of the callbacks, but that also makes them
+// very difficult to understand, so let's work through "\\Aa\\z".
+// There are three slots per DFA state because the bytemap has two
+// equivalence classes and there is a third slot for kByteEndText:
+//   0: all bytes that are not 'a'
+//   1: the byte 'a'
+//   2: kByteEndText
+// -1 means that there is no transition from that DFA state to any
+// other DFA state for that slot. The valid transitions are thus:
+//   state 0 --slot 1--> state 1
+//   state 1 --slot 2--> state 2
+// The double brackets indicate that state 2 is a matching state.
+// Putting it together, this means that the DFA must consume the
+// byte 'a' and then hit end of text. Q.E.D.
+CallbackTest callback_tests[] = {
+  { "\\Aa\\z", "[-1,1,-1] [-1,-1,2] [[-1,-1,-1]]" },
+  { "\\Aab\\z", "[-1,1,-1,-1] [-1,-1,2,-1] [-1,-1,-1,3] [[-1,-1,-1,-1]]" },
+  { "\\Aa*b\\z", "[-1,0,1,-1] [-1,-1,-1,2] [[-1,-1,-1,-1]]" },
+  { "\\Aa+b\\z", "[-1,1,-1,-1] [-1,1,2,-1] [-1,-1,-1,3] [[-1,-1,-1,-1]]" },
+  { "\\Aa?b\\z", "[-1,1,2,-1] [-1,-1,2,-1] [-1,-1,-1,3] [[-1,-1,-1,-1]]" },
+  { "\\Aa\\C*\\z", "[-1,1,-1] [1,1,2] [[-1,-1,-1]]" },
+  { "\\Aa\\C*", "[-1,1,-1] [2,2,3] [[2,2,2]] [[-1,-1,-1]]" },
+  { "a\\C*", "[0,1,-1] [2,2,3] [[2,2,2]] [[-1,-1,-1]]" },
+  { "\\C*", "[1,2] [[1,1]] [[-1,-1]]" },
+  { "a", "[0,1,-1] [2,2,2] [[-1,-1,-1]]"} ,
+};
+
+TEST(DFA, Callback) {
+  int nfail = 0;
+  for (int i = 0; i < arraysize(callback_tests); i++) {
+    const CallbackTest& t = callback_tests[i];
+    Regexp* re = Regexp::Parse(t.regexp, Regexp::LikePerl, NULL);
+    CHECK(re);
+    Prog* prog = re->CompileToProg(0);
+    CHECK(prog);
+    string dump;
+    prog->BuildEntireDFA(Prog::kLongestMatch, [&](const int* next, bool match) 
{
+      CHECK(next != NULL);
+      if (!dump.empty())
+        StringAppendF(&dump, " ");
+      StringAppendF(&dump, match ? "[[" : "[");
+      for (int b = 0; b < prog->bytemap_range() + 1; b++)
+        StringAppendF(&dump, "%d,", next[b]);
+      dump.pop_back();
+      StringAppendF(&dump, match ? "]]" : "]");
+    });
+    if (dump != t.dump) {
+      LOG(ERROR) << t.regexp << " bytemap:\n" << prog->DumpByteMap();
+      LOG(ERROR) << t.regexp << " dump:\ngot " << dump << "\nwant " << t.dump;
+      nfail++;
+    }
+    delete prog;
     re->Decref();
   }
   EXPECT_EQ(nfail, 0);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/re2/testing/tester.cc 
new/re2-2017-07-01/re2/testing/tester.cc
--- old/re2-2017-06-01/re2/testing/tester.cc    2017-05-18 07:20:04.000000000 
+0200
+++ new/re2-2017-07-01/re2/testing/tester.cc    2017-06-27 14:55:46.000000000 
+0200
@@ -465,14 +465,6 @@
         break;
       }
       result->have_submatch = true;
-
-      // Work around RE interface bug: PCRE returns -1 as the
-      // offsets for an unmatched subexpression, and RE should
-      // turn that into StringPiece(NULL) but in fact it uses
-      // StringPiece(text.begin() - 1, 0).  Oops.
-      for (int i = 0; i < nsubmatch; i++)
-        if (result->submatch[i].begin() == text.begin() - 1)
-          result->submatch[i] = StringPiece();
       delete[] argptr;
       delete[] a;
       break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/util/pcre.cc 
new/re2-2017-07-01/util/pcre.cc
--- old/re2-2017-06-01/util/pcre.cc     2017-05-18 07:20:04.000000000 +0200
+++ new/re2-2017-07-01/util/pcre.cc     2017-06-27 14:55:46.000000000 +0200
@@ -635,7 +635,17 @@
   for (int i = 0; i < n; i++) {
     const int start = vec[2*(i+1)];
     const int limit = vec[2*(i+1)+1];
-    if (!args[i]->Parse(text.data() + start, limit-start)) {
+
+    // Avoid invoking undefined behavior when text.data() happens
+    // to be null and start happens to be -1, the latter being the
+    // case for an unmatched subexpression. Even if text.data() is
+    // not null, pointing one byte before was a longstanding bug.
+    const char* addr = NULL;
+    if (start != -1) {
+      addr = text.data() + start;
+    }
+
+    if (!args[i]->Parse(addr, limit-start)) {
       // TODO: Should we indicate what the error was?
       return false;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/util/sparse_array.h 
new/re2-2017-07-01/util/sparse_array.h
--- old/re2-2017-06-01/util/sparse_array.h      2017-05-18 07:20:04.000000000 
+0200
+++ new/re2-2017-07-01/util/sparse_array.h      2017-06-27 14:55:46.000000000 
+0200
@@ -310,6 +310,20 @@
   // and at the beginning and end of all public non-const member functions.
   void DebugCheckInvariants() const;
 
+  static bool ShouldInitializeMemory() {
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+    return true;
+#else
+    return false;
+#endif
+#elif defined(RE2_ON_VALGRIND)
+    return true;
+#else
+    return false;
+#endif
+  }
+
   int size_ = 0;
   int max_size_ = 0;
   std::unique_ptr<int[]> sparse_to_dense_;
@@ -415,14 +429,12 @@
 
     dense_.resize(max_size);
 
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-    for (int i = max_size_; i < max_size; i++) {
-      sparse_to_dense_[i] = 0xababababU;
-      dense_[i].index_ = 0xababababU;
+    if (ShouldInitializeMemory()) {
+      for (int i = max_size_; i < max_size; i++) {
+        sparse_to_dense_[i] = 0xababababU;
+        dense_[i].index_ = 0xababababU;
+      }
     }
-#endif
-#endif
   }
   max_size_ = max_size;
   if (size_ > max_size_)
@@ -485,14 +497,12 @@
   dense_.resize(max_size);
   size_ = 0;
 
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-  for (int i = 0; i < max_size; i++) {
-    sparse_to_dense_[i] = 0xababababU;
-    dense_[i].index_ = 0xababababU;
+  if (ShouldInitializeMemory()) {
+    for (int i = 0; i < max_size; i++) {
+      sparse_to_dense_[i] = 0xababababU;
+      dense_[i].index_ = 0xababababU;
+    }
   }
-#endif
-#endif
 
   DebugCheckInvariants();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/re2-2017-06-01/util/sparse_set.h 
new/re2-2017-07-01/util/sparse_set.h
--- old/re2-2017-06-01/util/sparse_set.h        2017-05-18 07:20:04.000000000 
+0200
+++ new/re2-2017-07-01/util/sparse_set.h        2017-06-27 14:55:46.000000000 
+0200
@@ -160,6 +160,20 @@
   // and at the beginning and end of all public non-const member functions.
   void DebugCheckInvariants() const;
 
+  static bool ShouldInitializeMemory() {
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+    return true;
+#else
+    return false;
+#endif
+#elif defined(RE2_ON_VALGRIND)
+    return true;
+#else
+    return false;
+#endif
+  }
+
   int size_ = 0;
   int max_size_ = 0;
   std::unique_ptr<int[]> sparse_to_dense_;
@@ -183,14 +197,12 @@
 
     dense_.resize(max_size);
 
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-    for (int i = max_size_; i < max_size; i++) {
-      sparse_to_dense_[i] = 0xababababU;
-      dense_[i] = 0xababababU;
+    if (ShouldInitializeMemory()) {
+      for (int i = max_size_; i < max_size; i++) {
+        sparse_to_dense_[i] = 0xababababU;
+        dense_[i] = 0xababababU;
+      }
     }
-#endif
-#endif
   }
   max_size_ = max_size;
   if (size_ > max_size_)
@@ -226,14 +238,12 @@
   dense_.resize(max_size);
   size_ = 0;
 
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-  for (int i = 0; i < max_size; i++) {
-    sparse_to_dense_[i] = 0xababababU;
-    dense_[i] = 0xababababU;
+  if (ShouldInitializeMemory()) {
+    for (int i = 0; i < max_size; i++) {
+      sparse_to_dense_[i] = 0xababababU;
+      dense_[i] = 0xababababU;
+    }
   }
-#endif
-#endif
 
   DebugCheckInvariants();
 }


Reply via email to