swiftlang/swift-experimental-string-processing

Regex: Inconsistent atomic access

lorentey opened this issue · 0 comments

In Regex/Core.swift, we have the following code:

    /// The program for execution with the matching engine.
    var loweredProgram: MEProgram {
      if let loweredObject = _loweredProgramStorage as? ProgramBox {
        return loweredObject.value
      }
      let lowered = try! Compiler(tree: tree, compileOptions: compileOptions).emit()
      _stdlib_atomicInitializeARCRef(object: &_loweredProgramStorage, desired: ProgramBox(lowered))
      return lowered
    }

This allows regular non-atomic loads of the _loweredProgramStorage variable to occur concurrently with atomic updates (cmpxchg) of it. This is explicitly undefined behavior per the Law of Exclusivity:

Two accesses to the same variable aren't allowed to overlap unless both accesses are reads or both accesses are atomic. -- SE-0282

We must avoid such accesses by converting the nonatomic load into an atomic load instruction:

    if let ref = _stdlib_atomicLoadARCRef(object: &_loweredProgramStorage) {
      return unsafeDowncast(ref, to: ProgramBox.self)
    }

On a secondary note, in case the current thread loses a concurrent update race, this property ought to return the winner program box, not the loser.