Skip to content

HorizontalStacker.operate() fails with ArrayIndexOutOfBoundsException for non 2 row matrices #65

Description

@Nesrine-larbi

Environment

  • Repository: java-utils
  • File: JavaUtils/src/id/ac/ub/filkom/rendicahya/utils/matrix/operators/HorizontalStacker.java
  • Method: operate(int[][ a, int[][] b) (line 66)

Bug Description

The HorizontalStacker.operate() method assumes input matrices have exactly 2 rows and throws ArrayIndexOutOfBoundsException when given matrices with different row counts.

Reproducing HorizontalStacker.operate() Bug

Create an instance of HorizontalStacker
Call operate() with matrices having non-2 row counts
Observe the exception

HorizontalStacker stacker = new HorizontalStacker();
int[][] oneRow = {{1, 2, 3}};        // 1 row
int[][] anotherMatrix = {{4, 5}};     // 1 row
stacker.operate(oneRow, anotherMatrix); // Throws ArrayIndexOutOfBoundsException

Expected vs Actual Behavior

Expected Behavior:
The method should either:

  • Support matrices with any number of rows (generalized horizontal stacking), OR
  • Validate input and throw a descriptive error for unsupported dimensions

Actual Behavior:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1

Root Cause

The method hardcodes array access to indices [0] and [1] without checking matrix dimensions:

public int[][] operate(int[][] a, int[][] b) {
    int[][] c = new int[2][a[0].length + b[0].length]; // ← Line 67: Assumes 2 rows
    
    for (int i = 0; i < a.length; i++) {
        for (int j = 0; j < a[i].length; j++) {
            if (i == 0) {
                c[0][j] = a[0][j];
            } else {
                c[0][j + a[i].length] = b[0][j];
            }
        }
    }
    
    // Second loop also accesses a[1] and assumes exactly 2 rows
    for (int i = 0; i < a.length; i++) {
        for (int j = 0; j < a[i].length; j++) {
            if (i == 0) {
                c[1][j] = a[1][j]; // ← Line 81: Will fail if a has < 2 rows
            } else {
                c[1][j + a[i].length] = b[1][j]; // ← Will fail if b has < 2 rows
            }
        }
    }
    return c;
}

Additional Issues & Suggested Fix

Additional Issues:

  • Logic error in index calculation: c[0][j + a[i].length] should use a[0].length
  • No validation of input matrix dimensions
  • Code duplication in the two loops

Suggested Fix:

Option 1: Add validation for 2-row requirement

public int[][] operate(int[][] a, int[][] b) {
    if (a.length != 2 || b.length != 2) {
        throw new IllegalArgumentException("Both matrices must have exactly 2 rows. " +
            "Got: a=" + a.length + " rows, b=" + b.length + " rows");
    }
    
    if (a[0].length != a[1].length || b[0].length != b[1].length) {
        throw new IllegalArgumentException("Matrix rows must have consistent lengths");
    }
    
    int[][] c = new int[2][a[0].length + b[0].length];
    
    // First row: concatenate a[0] and b[0]
    System.arraycopy(a[0], 0, c[0], 0, a[0].length);
    System.arraycopy(b[0], 0, c[0], a[0].length, b[0].length);
    
    // Second row: concatenate a[1] and b[1]
    System.arraycopy(a[1], 0, c[1], 0, a[1].length);
    System.arraycopy(b[1], 0, c[1], a[1].length, b[1].length);
    
    return c;
}

**Option 2: Generalize for any number of rows

public int[][] operate(int[][] a, int[][] b) {
    if (a.length != b.length) {
        throw new IllegalArgumentException("Matrices must have same number of rows");
    }
    
    int rows = a.length;
    int[][] c = new int[rows][a[0].length + b[0].length];
    
    for (int i = 0; i < rows; i++) {
        System.arraycopy(a[i], 0, c[i], 0, a[i].length);
        System.arraycopy(b[i], 0, c[i], a[i].length, b[i].length);
    }
    
    return c;
}
public int[][] operate(int[][] a, int[][] b) {
    if (a.length != b.length) {
        throw new IllegalArgumentException("Matrices must have same number of rows");
    }
    
    int rows = a.length;
    int[][] c = new int[rows][a[0].length + b[0].length];
    
    for (int i = 0; i < rows; i++) {
        System.arraycopy(a[i], 0, c[i], 0, a[i].length);
        System.arraycopy(b[i], 0, c[i], a[i].length, b[i].length);
    }
    
    return c;
}

Impact & Test Cases to Add

Impact:

  • Severity: High
  • Affected Methods: All operate() overloads in HorizontalStacker
  • Use Cases: Matrix operations, image processing, data table manipulation

Test Cases to Add:

// Should fail with descriptive error
assertThrows(IllegalArgumentException.class, () -> 
    stacker.operate(new int[][]{{1,2,3}}, new int[][]{{4,5}}));

// Should work for valid 2x2 matrices
int[][] a = {{1, 2}, {3, 4}};
int[][] b = {{5, 6}, {7, 8}};
int[][] result = stacker.operate(a, b);
assertArrayEquals(new int[]{1, 2, 5, 6}, result[0]);
assertArrayEquals(new int[]{3, 4, 7, 8}, result[1]);

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions