This logic is incorrect. (p, 0) might be before the first step in the paragraph. Recently I've been upgrading blocks of code like this to use step iterators instead. See SelectionController.roundToClosestStep. It should look something like:
```
var stepIterator = odtDocument.createStepIterator(paragraphElement, 0, [baseFilter, rootFilter], paragraphElement);
stepIterator.roundToClosestStep(); // Round to the first step in the paragraph. Might not be (p, 0)
pStartContainer = stepIterator.container();
pStartOffset = stepIterator.offset();
stepIterator.setPosition(paragraphElement, paragraphElement.childNodes.length);
stepIterator.roundToClosestStep(); // Round to the last step in the paragraph. Might not be (p, p.childNodes.length);
pEndContainer = stepIterator.container();
pEndOffset = stepIterator.offset();
...
```