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,

Reply via email to