Don't break the RE2 object when compiling the reverse Prog fails.
Change-Id: I3d34d0e971563991b64e60ba38c6311fa2fc03f7
Reviewed-on: https://code-review.googlesource.com/c/re2/+/52631
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/re2.cc b/re2/re2.cc
index 1395751..8c9ed4d 100644
--- a/re2/re2.cc
+++ b/re2/re2.cc
@@ -173,15 +173,20 @@
empty_group_names = new std::map<int, std::string>;
});
- pattern_ = std::string(pattern);
+ pattern_.assign(pattern.data(), pattern.size());
options_.Copy(options);
entire_regexp_ = NULL;
+ error_ = empty_string;
+ error_code_ = NoError;
+ error_arg_.clear();
+ prefix_.clear();
+ prefix_foldcase_ = false;
suffix_regexp_ = NULL;
prog_ = NULL;
num_captures_ = -1;
+ is_one_pass_ = false;
+
rprog_ = NULL;
- error_ = empty_string;
- error_code_ = NoError;
named_groups_ = NULL;
group_names_ = NULL;
@@ -240,9 +245,11 @@
if (re->rprog_ == NULL) {
if (re->options_.log_errors())
LOG(ERROR) << "Error reverse compiling '" << trunc(re->pattern_) << "'";
- re->error_ =
- new std::string("pattern too large - reverse compile failed");
- re->error_code_ = RE2::ErrorPatternTooLarge;
+ // We no longer touch error_ and error_code_ because failing to compile
+ // the reverse Prog is not a showstopper: falling back to NFA execution
+ // is fine. More importantly, an RE2 object is supposed to be logically
+ // immutable: whatever ok() would have returned after Init() completed,
+ // it should continue to return that no matter what ReverseProg() does.
}
}, this);
return rprog_;
diff --git a/re2/re2.h b/re2/re2.h
index 46409cb..44fb5af 100644
--- a/re2/re2.h
+++ b/re2/re2.h
@@ -741,29 +741,26 @@
re2::Prog* ReverseProg() const;
- std::string pattern_; // string regular expression
- Options options_; // option flags
- std::string prefix_; // required prefix (before regexp_)
- bool prefix_foldcase_; // prefix is ASCII case-insensitive
- re2::Regexp* entire_regexp_; // parsed regular expression
- re2::Regexp* suffix_regexp_; // parsed regular expression, prefix removed
- re2::Prog* prog_; // compiled program for regexp
- int num_captures_; // Number of capturing groups
- bool is_one_pass_; // can use prog_->SearchOnePass?
+ std::string pattern_; // string regular expression
+ Options options_; // option flags
+ re2::Regexp* entire_regexp_; // parsed regular expression
+ const std::string* error_; // error indicator (or points to empty string)
+ ErrorCode error_code_; // error code
+ std::string error_arg_; // fragment of regexp showing error
+ std::string prefix_; // required prefix (before suffix_regexp_)
+ bool prefix_foldcase_; // prefix_ is ASCII case-insensitive
+ re2::Regexp* suffix_regexp_; // parsed regular expression, prefix_ removed
+ re2::Prog* prog_; // compiled program for regexp
+ int num_captures_; // number of capturing groups
+ bool is_one_pass_; // can use prog_->SearchOnePass?
- mutable re2::Prog* rprog_; // reverse program for regexp
- mutable const std::string* error_; // Error indicator
- // (or points to empty string)
- mutable ErrorCode error_code_; // Error code
- mutable std::string error_arg_; // Fragment of regexp showing error
-
+ // Reverse Prog for DFA execution only
+ mutable re2::Prog* rprog_;
// Map from capture names to indices
mutable const std::map<std::string, int>* named_groups_;
-
// Map from capture indices to names
mutable const std::map<int, std::string>* group_names_;
- // Onces for lazy computations.
mutable std::once_flag rprog_once_;
mutable std::once_flag named_groups_once_;
mutable std::once_flag group_names_once_;