The problem arises because of the multiple constructors available for std::regex. Tracing into the constructor showed it using one I didn't intend!
I wanted to use this one:
explicit basic_regex(_In_z_ const _Elem *_Ptr,
flag_type _Flags = regex_constants::ECMAScript)
But I got this one instead:
basic_regex(_In_reads_(_Count) const _Elem *_Ptr, size_t _Count,
flag_type _Flags = regex_constants::ECMAScript)
The ternary expression in the flags causes the type to change to int, which no longer matches flag_type in the constructor signature. Since it does match on size_t it calls that constructor instead. The flags are misinterpreted as the size of the string, resulting in undefined behavior when the memory past the end of the string is accessed.
The problem is not specific to Visual Studio. I was able to duplicate it in gcc: http://ideone.com/5DjYiz
It can be fixed two ways. First is an explicit cast of the argument:
std::regex re(pattern, static_cast<std::regex::flag_type>(std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0)));
Second is to avoid integer constants in the ternary expression:
std::regex re(pattern, caseInsensitive ? std::regex_constants::ECMAScript | std::regex_constants::icase : std::regex_constants::ECMAScript);