MatrixFuzzer.java
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.powsybl.commons.exceptions.UncheckedClassNotFoundException;
import com.powsybl.math.matrix.DenseMatrix;
import com.powsybl.math.matrix.Matrix;
import com.powsybl.math.matrix.MatrixException;
import com.powsybl.math.matrix.SparseMatrix;
import java.io.ByteArrayInputStream;
import java.io.UncheckedIOException;
public class MatrixFuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
try {
// Prepare matrix with constructor
Matrix matrix = null;
if (data.consumeBoolean()) {
matrix = new SparseMatrix(10, 10, new int[11], new int[11], new double[11]);
} else {
matrix = new DenseMatrix(10, 10, new double[100]);
}
matrix.reset();
if (matrix == null) {
return;
}
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 10; i++) {
matrix.set(i, j, data.consumeDouble());
}
}
// Fuzz operational methods
matrix.decomposeLU();
matrix.transpose().decomposeLU();
matrix.toDense();
matrix.toSparse();
// Fuzz deserailisation
Integer remaining = data.remainingBytes();
byte[] eof = new byte[] {(byte) 0x04};
byte[] random = new byte[remaining + eof.length];
System.arraycopy(data.consumeRemainingAsBytes(), 0, random, 0, remaining);
System.arraycopy(eof, 0, random, remaining, eof.length);
ByteArrayInputStream input = new ByteArrayInputStream(random);
Matrix other = SparseMatrix.read(input);
matrix.times(other);
matrix.add(other, 1, 1);
matrix.equals(other);
} catch (MatrixException
| UncheckedIOException
| IllegalArgumentException
| UncheckedClassNotFoundException
| ClassCastException e) {
// Known exceptions
} catch (NullPointerException e) {
// Capture known NPE from malformed JSON
if (!isExpected(e)) {
throw e;
}
}
}
private static boolean isExpected(Throwable e) {
String[] expectedString = {
"java.util.Objects.requireNonNull",
"Cannot invoke \"String.hashCode()\""
};
for (String expected : expectedString) {
if (e.toString().contains(expected)) {
return true;
}
for (StackTraceElement ste : e.getStackTrace()) {
if (ste.toString().contains(expected)) {
return true;
}
}
}
return false;
}
}