69 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clangxx -O0 -g %s -o %t && %run %t
 | 
						|
/// Check that REG_STARTEND is handled correctly.
 | 
						|
/// This is a regression test for https://github.com/google/sanitizers/issues/1371
 | 
						|
/// Previously, on GLibc systems, the interceptor was calling __compat_regexec
 | 
						|
/// (regexec@GLIBC_2.2.5) insead of the newer __regexec (regexec@GLIBC_2.3.4).
 | 
						|
/// The __compat_regexec strips the REG_STARTEND flag but does not report an error
 | 
						|
/// if other flags are present. This can result in infinite loops for programs that
 | 
						|
/// use REG_STARTEND to find all matches inside a buffer (since ignoring REG_STARTEND
 | 
						|
/// means that the search always starts from the first character).
 | 
						|
 | 
						|
#include <assert.h>
 | 
						|
#include <regex.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
/// REG_STARTEND is a BSD extension not supported everywhere.
 | 
						|
#ifdef REG_STARTEND
 | 
						|
void test_matched(const regex_t *preg, const char *string, size_t start,
 | 
						|
                  size_t end, const char *expected) {
 | 
						|
  regmatch_t match[1];
 | 
						|
  match[0].rm_so = start;
 | 
						|
  match[0].rm_eo = end;
 | 
						|
  int rv = regexec(preg, string, 1, match, REG_STARTEND);
 | 
						|
  int matchlen = (int)(match[0].rm_eo - match[0].rm_so);
 | 
						|
  const char *matchstart = string + match[0].rm_so;
 | 
						|
  if (rv == 0) {
 | 
						|
    if (expected == nullptr) {
 | 
						|
      fprintf(stderr, "ERROR: expected no match but got '%.*s'\n",
 | 
						|
              matchlen, matchstart);
 | 
						|
      abort();
 | 
						|
    } else if ((size_t)matchlen != strlen(expected) ||
 | 
						|
               memcmp(matchstart, expected, strlen(expected)) != 0) {
 | 
						|
      fprintf(stderr, "ERROR: expected '%s' match but got '%.*s'\n",
 | 
						|
              expected, matchlen, matchstart);
 | 
						|
      abort();
 | 
						|
    }
 | 
						|
  } else if (rv == REG_NOMATCH) {
 | 
						|
    if (expected != nullptr) {
 | 
						|
      fprintf(stderr, "ERROR: expected '%s' match but got no match\n", expected);
 | 
						|
      abort();
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    printf("ERROR: unexpected regexec return value %d\n", rv);
 | 
						|
    abort();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int main(void) {
 | 
						|
  regex_t regex;
 | 
						|
  int rv = regcomp(®ex, "[A-Z][A-Z]", 0);
 | 
						|
  assert(!rv);
 | 
						|
  test_matched(®ex, "ABCD", 0, 4, "AB");
 | 
						|
  test_matched(®ex, "ABCD", 0, 1, nullptr); // Not long enough
 | 
						|
  test_matched(®ex, "ABCD", 1, 4, "BC");
 | 
						|
  test_matched(®ex, "ABCD", 1, 2, nullptr); // Not long enough
 | 
						|
  test_matched(®ex, "ABCD", 2, 4, "CD");
 | 
						|
  test_matched(®ex, "ABCD", 2, 3, nullptr); // Not long enough
 | 
						|
  test_matched(®ex, "ABCD", 3, 4, nullptr); // Not long enough
 | 
						|
  regfree(®ex);
 | 
						|
  printf("Successful test\n");
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
#else
 | 
						|
int main(void) {
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
#endif
 |