Add fxcrt::AutoRestorer<T>::AbandonRestoration().

Kinda like reaching a commit point, makes going forward more useful.

Change-Id: I7695b6e627d4cd8ed2bccb667d0cabd7f42c7b1c
Reviewed-on: https://pdfium-review.googlesource.com/35970
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 6c26519..fb251fc 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2899,6 +2899,7 @@
     "core/fxcodec/codec/fx_codec_rle_unittest.cpp",
     "core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp",
     "core/fxcodec/jbig2/JBig2_Image_unittest.cpp",
+    "core/fxcrt/autorestorer_unittest.cpp",
     "core/fxcrt/bytestring_unittest.cpp",
     "core/fxcrt/cfx_bitstream_unittest.cpp",
     "core/fxcrt/cfx_seekablemultistream_unittest.cpp",
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
index 3cce446..0910a39 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
@@ -359,7 +359,7 @@
 std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetObjectBodyInternal(
     CPDF_IndirectObjectHolder* pObjList,
     ParseType parse_type) {
-  AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
+  AutoRestorer<int> depth_restorer(&s_CurrentRecursionDepth);
   if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth)
     return nullptr;
 
@@ -370,19 +370,21 @@
     return nullptr;
 
   if (bIsNumber) {
-    FX_FILESIZE SavedPos = m_Pos;
+    AutoRestorer<FX_FILESIZE> pos_restorer(&m_Pos);
     ByteString nextword = GetNextWord(&bIsNumber);
-    if (bIsNumber) {
-      ByteString nextword2 = GetNextWord(nullptr);
-      if (nextword2 == "R") {
-        uint32_t refnum = FXSYS_atoui(word.c_str());
-        if (refnum == CPDF_Object::kInvalidObjNum)
-          return nullptr;
-        return pdfium::MakeUnique<CPDF_Reference>(pObjList, refnum);
-      }
-    }
-    m_Pos = SavedPos;
-    return pdfium::MakeUnique<CPDF_Number>(word.AsStringView());
+    if (!bIsNumber)
+      return pdfium::MakeUnique<CPDF_Number>(word.AsStringView());
+
+    ByteString nextword2 = GetNextWord(nullptr);
+    if (nextword2 != "R")
+      return pdfium::MakeUnique<CPDF_Number>(word.AsStringView());
+
+    pos_restorer.AbandonRestoration();
+    uint32_t refnum = FXSYS_atoui(word.c_str());
+    if (refnum == CPDF_Object::kInvalidObjNum)
+      return nullptr;
+
+    return pdfium::MakeUnique<CPDF_Reference>(pObjList, refnum);
   }
 
   if (word == "true" || word == "false")
@@ -453,12 +455,10 @@
       }
     }
 
-    FX_FILESIZE SavedPos = m_Pos;
-    ByteString nextword = GetNextWord(nullptr);
-    if (nextword != "stream") {
-      m_Pos = SavedPos;
+    AutoRestorer<FX_FILESIZE> pos_restorer(&m_Pos);
+    if (GetNextWord(nullptr) != "stream")
       return std::move(pDict);
-    }
+    pos_restorer.AbandonRestoration();
     return ReadStream(std::move(pDict));
   }
   if (word == ">>")
diff --git a/core/fxcrt/autorestorer.h b/core/fxcrt/autorestorer.h
index 745a56f..cafa075 100644
--- a/core/fxcrt/autorestorer.h
+++ b/core/fxcrt/autorestorer.h
@@ -12,10 +12,14 @@
  public:
   explicit AutoRestorer(T* location)
       : m_Location(location), m_OldValue(*location) {}
-  ~AutoRestorer() { *m_Location = m_OldValue; }
+  ~AutoRestorer() {
+    if (m_Location)
+      *m_Location = m_OldValue;
+  }
+  void AbandonRestoration() { m_Location = nullptr; }
 
  private:
-  T* const m_Location;
+  T* m_Location;
   const T m_OldValue;
 };
 
diff --git a/core/fxcrt/autorestorer_unittest.cpp b/core/fxcrt/autorestorer_unittest.cpp
new file mode 100644
index 0000000..ac1d613
--- /dev/null
+++ b/core/fxcrt/autorestorer_unittest.cpp
@@ -0,0 +1,23 @@
+// Copyright 2018 PDFium 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 "core/fxcrt/autorestorer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(fxcrt, AutoRestorer) {
+  int x = 5;
+  {
+    AutoRestorer<int> restorer(&x);
+    x = 6;
+    EXPECT_EQ(6, x);
+  }
+  EXPECT_EQ(5, x);
+  {
+    AutoRestorer<int> restorer(&x);
+    x = 6;
+    EXPECT_EQ(6, x);
+    restorer.AbandonRestoration();
+  }
+  EXPECT_EQ(6, x);
+}