Comment 4 for bug 500031

Revision history for this message
Jay Pipes (jaypipes) wrote :

After investigation into this, I discovered that there was a race condition in TemporalFormat::match():

TemporalFormat::_re is the compiled PCRE regular expression object inside each of the TemporalFormat objects, which are shared among all threads and live in global scope.

Unfortunately, TemporalFormat::match() was using TemporalFormat::_match_vector as its match state. At high concurrency, this means that the following could happen:

Thread 1 executes pcre_exec() and finds a match, therefore populating TemporalFormat::_match_vector of integers with the position offsets of the matched pieces of the temporal object.

Thread 1, during construction of the Temporal output of TemporalFormat::match(), uses these _match_vector position offsets in calling std::string::substr on a copy of the matched string, essentially "cutting up" the string into year, month, day, etc.

Thread 2 executes pcre_exec() and also finds a match, thereby changing TemporalFormat::_match_vector to something different

Thread 1 continues trying to use std::string::substr(), but now uses offsets that are invalid for its string, thereby producing an out_of_range exception.

The solution is to pull the TemporalFormat::_match_vector member variable and instead put a function-scope-level match_vector variable on the stack inside TemporalFormat::match().