Repository navigation
Description
FilteredRE2's lowercased-text atom search misses a case-sensitive Greek literal identical to the input, because Compile returns a case-folded atom that isn't in the lowercased text.
The FilteredRE2 contract allows atom matching “on a lowercased version of the search text”. κόσμος is already lowercase, so FirstMatch should return 0.
Save these as repro.cc and CMakeLists.txt and run.
#include <iostream>
#include <string>
#include <vector>
#include "re2/filtered_re2.h"
int main() {
// U+03BA U+03CC U+03C3 U+03BC U+03BF U+03C2: all lowercase.
const std::string text = u8"κόσμος";
const std::string lower_text = text;
re2::FilteredRE2 filter;
int id = -1;
if (filter.Add(text, RE2::Options(), &id) != RE2::NoError || id != 0)
return 2;
std::vector<std::string> atoms;
filter.Compile(&atoms);
std::vector<int> found;
for (size_t i = 0; i < atoms.size(); ++i) {
std::cout << "atom=" << atoms[i] << '\n';
if (lower_text.find(atoms[i]) != std::string::npos)
found.push_back(static_cast<int>(i));
}
const int actual = filter.FirstMatch(text, found);
std::cout << "expected=0 actual=" << actual << '\n';
return actual == 0 ? 0 : 1;
}cmake_minimum_required(VERSION 3.22)
project(re2_repro LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE)
set(ABSL_BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(RE2_BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(RE2_TEST OFF CACHE BOOL "" FORCE)
set(RE2_BENCHMARK OFF CACHE BOOL "" FORCE)
set(RE2_INSTALL OFF CACHE BOOL "" FORCE)
if(NOT RE2_SOURCE_DIR OR NOT ABSL_SOURCE_DIR)
message(FATAL_ERROR "Set RE2_SOURCE_DIR and ABSL_SOURCE_DIR to the source checkouts")
endif()
add_subdirectory("${ABSL_SOURCE_DIR}" abseil EXCLUDE_FROM_ALL)
add_subdirectory("${RE2_SOURCE_DIR}" re2 EXCLUDE_FROM_ALL)
add_executable(repro repro.cc)
target_link_libraries(repro PRIVATE re2::re2)git clone https://github.com/google/re2.git re2
git -C re2 checkout --detach 2da0056814cf180480a19f5cf811e7e1c054bf6d
git clone https://github.com/abseil/abseil-cpp.git abseil-cpp
git -C abseil-cpp checkout --detach d38452e1ee03523a208362186fd42248ff2609f6
cmake -S . -B build-gcc \
-DRE2_SOURCE_DIR="$PWD/re2" -DABSL_SOURCE_DIR="$PWD/abseil-cpp" \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++
cmake --build build-gcc --target repro --parallel 3
./build-gcc/repro
cmake -S . -B build-clang \
-DRE2_SOURCE_DIR="$PWD/re2" -DABSL_SOURCE_DIR="$PWD/abseil-cpp" \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang++
cmake --build build-clang --target repro --parallel 3
./build-clang/reproGCC and Clang both printed this and exited 1.
atom=κόσμοσ
expected=0 actual=-1
The atom ends in U+03C3 where the input has U+03C2, because Prefilter::Info::Literal calls ToLowerRune, built from Unicode C/S case-fold mappings. UnicodeLower expects folded atoms, so a code or doc change could reconcile the two. Long s fails the same way (abcſ gives atom abcs).
Version: RE2 2da0056814cf180480a19f5cf811e7e1c054bf6d, Abseil 20250814.1 d38452e1ee03523a208362186fd42248ff2609f6, GCC 13.3.0, Clang 18.1.3, CMake 3.28.3, Ubuntu 24.04.5 LTS x86-64
The example and build file are offered under CC0-1.0.
— ChipLab
Activity