공백 정규 표현식을 사용할 때의 무한 순환
6279 단어 re2
묘사
다음은 무한 순환을 초래하는 간단한 테스트 용례이다.regex = RE2::Regexp.new('')
regex.scan('test').map { |match| match }
이것도 실패했다.regex = RE2::Regexp.new('()')
regex.scan('test').map { |match| match }
Ruby의 작동 방식은 다음과 같습니다.'test'.scan('').map { |match| match }
=> ["", "", "", "", ""]
관련 질문:https://stackoverflow.com/a/30047809/1992201re2의 노트.h 파일 정보:https://github.com/google/re2/blob/master/re2/re2.h#L133-L138
이러한 행과 연관:https://github.com/mudge/re2/blob/v1.0.0/ext/re2/re2.cc#L224- L225
토론 #1
이것은Scanner
가 실현한 문제인 것 같다. 일치하는 항목이 존재하면 입력이 고급이 아니더라도 무한 순환할 수 있다.올바른 형식:
r = RE2::Regexp.new('')
scanner = r.scan('test')
scanner.scan.to_a
잘못된 테이블:r = RE2::Regexp.new('')
r.scan('test').map { |x| x }
토론 #2
@stanhu:re2.h
에서 온 평론이 특히 유용합니다.당신은 올바른 행동이 무엇이어야 한다고 생각합니까?// If the regular expression being used might match
// an empty string, the loop body must check for this case and either
// advance the string or break out of the loop.
우리는 스스로 입력을 추진해야 합니까 아니면 순환을 중지해야 합니까?토론 #셋
는 빈 매칭이나 빈 포획 매칭을 만났을 때 우리가 직접 remove_prefix
를 사용하여 입력을 추진하는 것처럼 보이지만 무한 순환을 해결하지만 입력이 끝날 때 되돌아오기nil
는 좀 번거롭다.토론 #4
네, 저도 같은 방법을 시도해 봤는데 효과가 별로 없어요.--- a/ext/re2/re2.cc
+++ b/ext/re2/re2.cc
@@ -204,12 +204,15 @@ static VALUE re2_scanner_rewind(VALUE self) {
*/
static VALUE re2_scanner_scan(VALUE self) {
int i;
+ int found_match = 0;
+ size_t original_size;
re2_pattern *p;
re2_scanner *c;
VALUE result;
Data_Get_Struct(self, re2_scanner, c);
Data_Get_Struct(c->regexp, re2_pattern, p);
+ original_size = c->input->size();
vector<RE2::Arg> argv(c->number_of_capturing_groups);
vector<RE2::Arg*> args(c->number_of_capturing_groups);
@@ -228,6 +231,7 @@ static VALUE re2_scanner_scan(VALUE self) {
if (matches[i].empty()) {
rb_ary_push(result, Qnil);
} else {
+ found_match = 1;
rb_ary_push(result, ENCODED_STR_NEW(matches[i].data(),
matches[i].size(),
p->pattern->options().utf8() ? "UTF-8" : "ISO-8859-1"));
@@ -237,6 +241,17 @@ static VALUE re2_scanner_scan(VALUE self) {
result = Qnil;
}
+ /* In case we matched a null string, advance the pointer to avoid an infinite loop */
+ if (!found_match &&
+ c->number_of_capturing_groups &&
+ c->input->size() &&
+ (original_size == c->input->size())) {
+ c->input->remove_prefix(1);
+ }
+
return result;
}
GitLab에서, 우리는 교체 match
를 통해 루비 코드를 바꾸어 이 문제를 해결하고 있다.패치를 나중에 보낼게요.토론 #5
두 가지 상황에서 나는 입력에서 1바이트 접두사를 삭제하고(입력 크기가 0이 아니라면) 몇 가지 기능을 실현했다.또 다른 궁금한 것은 빈 포획조 (예를 들어 빈 문자열로 되돌아오는 것) 와 포획조가 전혀 일치하지 않는 것을 구분해야 하는지 하는 것이다.이것은 앞으로 호환되지 않을 수도 있기 때문에 우리는 잠시 연기할 수 있다.
토론 #6
GitLab에서 수행한 사항은 참고용으로만 제공됩니다.https://gitlab.com/nick.thomas/gitlab-ce/commit/dabc1fa388143808bab792448504dac4bae8992b토론 #7
루비의 Regexp 차이는 다음과 같습니다."foo".scan(//) # ["", "", "", ""]
"foo".scan(/()/) # [[""], [""], [""], [""]]
"foo".scan(/foo()/) # [[""]]
"foo".scan(/(foo())/) [["foo", ""]]
토론 #8
#35의 변화에 따른 결과는 다음과 같습니다.[9] pry(main)> RE2::Regexp.new('').scan("foo").to_a
=> [[], [], []]
[10] pry(main)> RE2::Regexp.new('()').scan("foo").to_a
=> [[nil], [nil], [nil]]
[11] pry(main)> RE2::Regexp.new('foo()').scan("foo").to_a
=> [[nil]]
[12] pry(main)> RE2::Regexp.new('(foo())').scan("foo").to_a
=> [["foo", nil]]
빈 문자열/nil
의 차이를 제외하고re2는 빈 패턴과 일치하는 것을 줄였다. 이것은 나에게 매우 직관적이다. (문자마다 일치하고 멈추는 것). 그러나 아마도 내가 무엇을 빠뜨렸을 것이다.토론 #9
네, 루비의 빈 문자열과 빈 모드의 기본 대소문자는 리2에서도 그것을 보존해야 하는지 알고 싶습니다.> ''.scan(//)
=> [""]
이를 위해 스캐너가 다 소모되었는지 다시 스캔해야 할 수도 있습니다. 즉, 일치하는 문자열은 입력 문자열의 끝을 넘어섰습니다. 입력 크기가 0일 때가 아니라.토론 #10
#35를 업데이트하여 Ruby 동작과 일치시킴(빈 문자열이 아닌 호환성 재반환nil
:[1] pry(main)> RE2::Regexp.new('').scan('foo').to_a
=> [[], [], [], []]
[2] pry(main)> RE2::Regexp.new('()').scan('foo').to_a
=> [[nil], [nil], [nil], [nil]]
[3] pry(main)> RE2::Regexp.new('foo()').scan('foo').to_a
=> [[nil]]
[4] pry(main)> RE2::Regexp.new('(foo())').scan('foo').to_a
=> [["foo", nil]]
이것은 당신의 기대에 부합됩니까?토론 #11
저는 v1.1.0를 발표했습니다. 이 문제를 해결할 수 있기를 바랍니다. 한번 해 보세요. 만약 그것이 당신의 문제를 해결할 수 있다면 저에게 알려주세요.토론 #12
@mudge에서 빠른 답변 감사합니다!https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13036re2 v1을 사용하려면 gitlab를 업데이트합니다.1.0 직접 만든 검색을 삭제할 수 있습니다.나는 1MiB 구축 추적에서 0 매칭과 빈 매칭 상황을 테스트했는데, 그것들은 모두 매우 빠르다.잘했어!
토론 #13
천만에요!(코드를 삭제하는 것은 확실히 나를 기쁘게 한다.)토론 #14
@mudge 감사합니다!Reference
이 문제에 관하여(공백 정규 표현식을 사용할 때의 무한 순환), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://github.com/mudge/re2/issues/32텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)