Skip to content

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

@Nesrine-larbi

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]);

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