This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new bf93ece71c Fix intermittent AIOOBE when recording empty position undo
in Hop GUI (#7754)
bf93ece71c is described below
commit bf93ece71c8d1e56ec6801a27d12e4046ae9608c
Author: Lance <[email protected]>
AuthorDate: Mon Aug 3 15:55:45 2026 +0800
Fix intermittent AIOOBE when recording empty position undo in Hop GUI
(#7754)
Signed-off-by: lance <[email protected]>
---
.../java/org/apache/hop/base/AbstractMeta.java | 4 ++
.../org/apache/hop/core/undo/ChangeAction.java | 19 ++++++++-
.../java/org/apache/hop/base/AbstractMetaTest.java | 47 +++++++++++++++++++++-
.../hopgui/file/pipeline/HopGuiPipelineGraph.java | 4 +-
4 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/engine/src/main/java/org/apache/hop/base/AbstractMeta.java
b/engine/src/main/java/org/apache/hop/base/AbstractMeta.java
index acd7c544f1..ef59cc1030 100644
--- a/engine/src/main/java/org/apache/hop/base/AbstractMeta.java
+++ b/engine/src/main/java/org/apache/hop/base/AbstractMeta.java
@@ -502,6 +502,10 @@ public abstract class AbstractMeta
default:
break;
}
+ // Skip entries that were rejected (e.g. empty selection / length mismatch)
+ if (ta.getType() == ChangeAction.ActionType.None) {
+ return;
+ }
undo.add(ta);
undoPosition++;
diff --git a/engine/src/main/java/org/apache/hop/core/undo/ChangeAction.java
b/engine/src/main/java/org/apache/hop/core/undo/ChangeAction.java
index c25206879a..14f938e8ed 100644
--- a/engine/src/main/java/org/apache/hop/core/undo/ChangeAction.java
+++ b/engine/src/main/java/org/apache/hop/core/undo/ChangeAction.java
@@ -117,6 +117,10 @@ public class ChangeAction {
}
public void setDelete(Object[] prev, int[] idx) {
+ if (prev == null || prev.length == 0) {
+ return;
+ }
+
current = prev;
currentIndex = idx;
@@ -141,6 +145,10 @@ public class ChangeAction {
}
public void setChanged(Object[] prev, Object[] curr, int[] idx) {
+ if (prev == null || prev.length == 0) {
+ return;
+ }
+
previous = prev;
current = curr;
currentIndex = idx;
@@ -167,7 +175,7 @@ public class ChangeAction {
}
public void setNew(Object[] prev, int[] position) {
- if (prev.length == 0) {
+ if (prev == null || prev.length == 0) {
return;
}
@@ -196,7 +204,14 @@ public class ChangeAction {
}
public void setPosition(Object[] obj, int[] idx, Point[] prev, Point[] curr)
{
- if (prev.length != curr.length) {
+ // Nothing to record: empty selection, or mouse-down/up selection size
mismatch
+ if (obj == null
+ || obj.length == 0
+ || prev == null
+ || curr == null
+ || prev.length == 0
+ || prev.length != curr.length
+ || obj.length != prev.length) {
return;
}
diff --git a/engine/src/test/java/org/apache/hop/base/AbstractMetaTest.java
b/engine/src/test/java/org/apache/hop/base/AbstractMetaTest.java
index f585e8f503..cd4335b5af 100644
--- a/engine/src/test/java/org/apache/hop/base/AbstractMetaTest.java
+++ b/engine/src/test/java/org/apache/hop/base/AbstractMetaTest.java
@@ -187,7 +187,9 @@ class AbstractMetaTest {
assertNotNull(meta.viewPreviousUndo());
assertNotNull(meta.viewNextUndo());
meta.addUndo(from, to, pos, prev, curr, AbstractMeta.TYPE_UNDO_DELETE,
false);
- meta.addUndo(from, to, pos, prev, curr, AbstractMeta.TYPE_UNDO_POSITION,
false);
+ Point[] prevPos = new Point[] {new Point(10, 20)};
+ Point[] currPos = new Point[] {new Point(30, 40)};
+ meta.addUndo(from, to, pos, prevPos, currPos,
AbstractMeta.TYPE_UNDO_POSITION, false);
assertNotNull(meta.previousUndo());
assertNotNull(meta.nextUndo());
meta.setMaxUndo(1);
@@ -195,6 +197,49 @@ class AbstractMetaTest {
meta.addUndo(from, to, pos, prev, curr, AbstractMeta.TYPE_UNDO_NEW, false);
}
+ @Test
+ void testAddUndoPositionSkipsEmptyOrMismatched() {
+ meta.clearUndo();
+ meta.setMaxUndo(10);
+ TransformMeta transformMeta = mock(TransformMeta.class);
+ Object[] from = new Object[] {transformMeta};
+ int[] pos = new int[] {0};
+
+ // Empty location arrays must not be recorded (and must not throw)
+ meta.addUndo(
+ new Object[0],
+ null,
+ new int[0],
+ new Point[0],
+ new Point[0],
+ AbstractMeta.TYPE_UNDO_POSITION,
+ false);
+ assertEquals(0, meta.getUndoSize());
+
+ // Length mismatch between previous/current locations
+ meta.addUndo(
+ from,
+ null,
+ pos,
+ new Point[] {new Point(1, 1)},
+ new Point[0],
+ AbstractMeta.TYPE_UNDO_POSITION,
+ false);
+ assertEquals(0, meta.getUndoSize());
+
+ // Valid position undo is recorded
+ meta.addUndo(
+ from,
+ null,
+ pos,
+ new Point[] {new Point(1, 1)},
+ new Point[] {new Point(2, 2)},
+ AbstractMeta.TYPE_UNDO_POSITION,
+ false);
+ assertEquals(1, meta.getUndoSize());
+ assertEquals(ChangeAction.ActionType.PositionTransform,
meta.viewThisUndo().getType());
+ }
+
@Test
void testGetSetAttributes() {
assertNull(meta.getAttributesMap());
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index bd8060090f..f7db2c1486 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -1280,7 +1280,9 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
pipelineMeta.getSelectedNoteLocations(),
also);
}
- if (selectedTransforms != null && previousTransformLocations !=
null) {
+ if (selectedTransforms != null
+ && !selectedTransforms.isEmpty()
+ && previousTransformLocations != null) {
int[] indexes =
pipelineMeta.getTransformIndexes(selectedTransforms);
hopGui.undoDelegate.addUndoPosition(
pipelineMeta,