oss-fuzz/projects/h2database/CsvReadBackFuzzer.java

153 lines
5.2 KiB
Java

import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import org.h2.tools.Csv;
import org.h2.tools.SimpleResultSet;
public class CsvReadBackFuzzer {
static class TableContent
{
private static boolean contains(String haystack[], String needle, int n)
{
while (n-- > 0) {
if (haystack[n].equals(needle)) {
return true;
}
}
return false;
}
public TableContent(FuzzedDataProvider fuzzedDataProvider) {
m_columnCount = fuzzedDataProvider.consumeInt(1,4);
m_rowCount = fuzzedDataProvider.consumeInt(1,100);
m_headers = new String[getColumnCount()];
m_content = new String[getRowCount()][getColumnCount()];
for (int column = 0; column < getColumnCount(); ++column) {
m_headers[column] = "C_" + column;
}
for (int row = 0; row < getRowCount(); ++row) {
for (int column = 0; column < getColumnCount(); ++column) {
if (row == 0) {
m_content[row][column] = fuzzedDataProvider.consumeAsciiString(8);
} else {
m_content[row][column] = fuzzedDataProvider.consumeRemainingAsAsciiString();
}
}
}
}
public SimpleResultSet simpleResultSet() {
SimpleResultSet rs = new SimpleResultSet();
for (int column = 0; column < getColumnCount(); ++column) {
/*
* VARCHAR(255) might be insufficient
*/
rs.addColumn(columnHeader(column), Types.VARCHAR, 255, 0);
}
for (int row = 0; row < getRowCount(); ++row) {
rs.addRow(getRow(row));
}
return rs;
}
public String columnHeader(int column) {
return m_headers[column];
}
public int getColumnCount() {
return m_columnCount;
}
public int getRowCount() {
return m_rowCount;
}
public Object[] getRow(int row) {
return m_content[row];
}
public String getCell(int row, int column) {
return m_content[row][column];
}
int m_columnCount;
int m_rowCount;
String m_headers[];
String m_content[][];
};
public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) {
TableContent data = new TableContent(fuzzedDataProvider);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(outStream);
try {
new Csv().write(writer, data.simpleResultSet());
} catch (SQLException ex) {
/* documented, ignore */
return;
}
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
InputStreamReader reader = new InputStreamReader(inStream);
ResultSet resultSet = null;
try {
resultSet = new Csv().read(reader, null);
} catch (IOException e) {
return;
}
try {
ResultSetMetaData meta = resultSet.getMetaData();
if (meta.getColumnCount() != data.getColumnCount()) {
throw new FuzzerSecurityIssueLow("Column Count Mismatch");
}
for (int column = 0; column < meta.getColumnCount(); ++column) {
String have = meta.getColumnLabel(column + 1);
String want = data.columnHeader(column);
if ( ! have.equals(want) ) {
System.out.println("\'" + have + "\' != \'" + want + "\'");
throw new FuzzerSecurityIssueLow("Column Label Mismatch");
}
}
int row = 0;
while (resultSet.next()) {
for (int column = 0; column < meta.getColumnCount(); ++column) {
String have = resultSet.getString(column + 1);
String want = data.getCell(row, column);
if ( ! have.equals( want ) ) {
System.out.println("\'" + have + "\' != \'" + want + "\'");
throw new FuzzerSecurityIssueLow("Cell Value Mismatch");
}
}
++row;
}
if (row != data.getRowCount()) {
throw new FuzzerSecurityIssueLow("Row Count Mismatch");
}
resultSet.close();
} catch (SQLException ex) {
/* documented, but shouldn't happen on our well-known input */
ex.printStackTrace(System.out);
throw new FuzzerSecurityIssueLow("SQLException??");
}
}
}