On Tue, 27 Sep 2022 11:16:36 GMT, Prasanta Sadhukhan <[email protected]>
wrote:
> javax.swing.text.AbstractDocument$BranchElement.replace(...) method throws an
> `ArrayIndexOutOfBoundsException: arraycopy: length -1 is negative` when using
> an UndoManager on the default document of a JTextArea and you try to undo the
> insertion of a LEFT-TO-RIGHT language (e.g. Arabic) that is immediately
> followed by setting the component orientation on the JTextArea.
>
> This is because System.arrayCopy() is called with -ve length because of the
> calculation done in AbstractDocment.replace where `src` is of 2bytes because
> of unicode text causing `nmove` to become -ve if `nchildren` is 1 (an unicode
> character is inserted)
>
> System.arrayCopy throws `IndexOutOfBoundsException if:
>
> The srcPos argument is negative.
> The destPos argument is negative.
> The length argument is negative
>
>
> so the fix is made to make nmove, src, dest +ve
> Also, Element.getElement() can return null which is not checked, causing NPE,
> if deletion of text is done which results in no element, which is also fixed
> in the PR
>
> All jtreg testsuite tests are run without any regression.
src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java line 958:
> 956: int index = bidiRoot.getElementIndex(p0);
> 957: Element bidiElem = bidiRoot.getElement(index);
> 958: if (bidiElem != null && bidiElem.getEndOffset() >= p1) {
Is it possible that `bidiElem` is `null`? It should never be. If it is, it is a
bug in the code and throwing NPE seems good — it will be the indication of the
bug.
Since the NPE has never been thrown from this code, I'd rather leave it
unchanged here.
src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java line 2325:
> 2323: int src = Math.abs(offset + length);
> 2324: int nmove = Math.abs(nchildren - src);
> 2325: int dest = Math.abs(src + delta);
I'm rather unsure why any of these could become negative. Would it be possible
that using `Math.abs` corrupts the document or leads to a data loss?
The thing is the `UndoableEdit` was produced while the document and the
component didn't have `bidi` set to `true`. Inserting a right-to-left text
changes that situation, and `bidiRoot` starts to contain elements. I assume
changing the component orientation also modifies the contents of `bidiRoot`. As
such, performing the undo operation may become impossible because the recorded
state in the `UndoableEdit` is inconsistent with the current state of the
document.
test/jdk/javax/swing/text/AbstractDocument/TestUndoError.java line 39:
> 37: import javax.swing.undo.UndoManager;
> 38:
> 39: public class TestUndoError {
`TestUndoInsertArabicText`? It's more specific this way.
test/jdk/javax/swing/text/AbstractDocument/TestUndoError.java line 42:
> 40:
> 41: private static JTextArea textArea_;
> 42: private static UndoManager manager_;
Is the underscore necessary at the end of the field names?
test/jdk/javax/swing/text/AbstractDocument/TestUndoError.java line 51:
> 49: textArea_ = new JTextArea();
> 50: manager_ = new UndoManager();
> 51: frame = new JFrame("Undo - Redo Error");
Is `frame` even required? Using `textArea` should be enough.
-------------
PR: https://git.openjdk.org/jdk/pull/10446