// 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 #include #include #include #include /// 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