Turns out that the loop is actually caused by the <ws>+, not the subst, as I had the same inside an ordinary match. jnthn tells me that the + is a bit redundant, but it shouldn't cause a loop.
<ws>* also succumbs.
signature.asc
Description: This is a digitally signed message part