Skip to content

Commit 05e1edb

Browse files
committed
fixed security issue and minor sonar issues
1 parent 670d86f commit 05e1edb

File tree

6 files changed

+36
-25
lines changed

6 files changed

+36
-25
lines changed

clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseDatabaseMetaDataTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ public void testGetTypeInfo() throws SQLException {
9696
props.setProperty("decompress", "0");
9797
try (ClickHouseConnection conn = newConnection(props); ResultSet rs = conn.getMetaData().getTypeInfo()) {
9898
while (rs.next()) {
99-
rs.getString(1);
100-
System.out.println(rs.getString(1));
101-
rs.getInt(2);
99+
Assert.assertNotNull(rs.getString(1));
102100
}
103101
}
104102
}

client-v2/src/test/java/com/clickhouse/client/datatypes/DataTypeTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,15 @@ public void testVariantWithSimpleDataTypes() throws Exception {
159159
case BFloat16:
160160
// TODO: add support
161161
continue dataTypesLoop;
162+
// skipped
162163
case String:
163164
case FixedString:
164165
case Nothing:
165166
case Variant:
166167
case JSON:
167168
case Object:
168169
case Dynamic:
169-
// skipped
170-
continue dataTypesLoop;
171-
170+
// no tests or tested in other tests
172171
case Decimal:
173172
case Decimal32:
174173
case Decimal64:

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.clickhouse.client.api.data_formats.internal.BinaryStreamReader;
44
import com.clickhouse.data.ClickHouseDataType;
55
import com.clickhouse.jdbc.types.Array;
6-
import org.jspecify.annotations.Nullable;
76

87
import java.sql.Date;
98
import java.sql.JDBCType;
@@ -20,11 +19,7 @@
2019
import java.util.HashMap;
2120
import java.util.List;
2221
import java.util.Map;
23-
import java.util.Optional;
24-
import java.util.Set;
2522
import java.util.TreeMap;
26-
import java.util.regex.Matcher;
27-
import java.util.regex.Pattern;
2823

2924
public class JdbcUtils {
3025
//Define a map to store the mapping between ClickHouse data types and SQL data types
@@ -259,4 +254,13 @@ public static Object convert(Object value, Class<?> type) throws SQLException {
259254

260255
throw new SQLException("Unsupported conversion from " + value.getClass().getName() + " to " + type.getName(), ExceptionUtils.SQL_STATE_DATA_EXCEPTION);
261256
}
257+
258+
public static String escapeQuotes(String str) {
259+
if (str == null || str.isEmpty()) {
260+
return str;
261+
}
262+
return str
263+
.replace("'", "\\'")
264+
.replace("\"", "\\\"");
265+
}
262266
}

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/MetadataResultSet.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
import java.util.HashMap;
1212
import java.util.List;
1313
import java.util.Map;
14-
import java.util.function.Function;
14+
import java.util.function.UnaryOperator;
1515

1616
public class MetadataResultSet extends ResultSetImpl {
17-
private final Map<String, Function<String, String>> columnTransformers = new HashMap<>();
17+
private final Map<String, UnaryOperator<String>> columnTransformers = new HashMap<>();
1818
private final String[] cachedColumnLabels;
1919

2020
private final OverridingSchemaAdaptor overridingSchemaAdaptor;
@@ -28,17 +28,16 @@ public MetadataResultSet(ResultSetImpl resultSet) throws SQLException {
2828
for (int i = 1; i <= count; i++) {
2929
cachedColumnLabels[i - 1] = metaData.getColumnLabel(i).toUpperCase();
3030
}
31-
3231
}
3332

3433
/**
3534
* Registers a transformer function for a given column.
3635
* The transformer takes the original String value and returns a new String.
3736
*
38-
* @param columnLabel The name of the column (case insensitive).
37+
* @param columnLabel The name of the column (case-insensitive).
3938
* @param transformer The function that transforms the value.
4039
*/
41-
public MetadataResultSet transform(String columnLabel, ClickHouseColumn column, Function<String, String> transformer) {
40+
public MetadataResultSet transform(String columnLabel, ClickHouseColumn column, UnaryOperator<String> transformer) {
4241
if (columnLabel != null && transformer != null) {
4342
columnTransformers.put(columnLabel.toUpperCase(), transformer);
4443
}
@@ -49,7 +48,7 @@ public MetadataResultSet transform(String columnLabel, ClickHouseColumn column,
4948
@Override
5049
public String getString(String columnLabel) throws SQLException {
5150
String value = super.getString(columnLabel);
52-
Function<String, String> transformer = columnTransformers.get(columnLabel.toUpperCase());
51+
UnaryOperator<String> transformer = columnTransformers.get(columnLabel.toUpperCase());
5352
if (transformer != null && value != null) {
5453
return transformer.apply(value);
5554
}
@@ -97,7 +96,7 @@ public short getShort(int columnIndex) throws SQLException {
9796

9897
@Override
9998
public long getLong(int columnIndex) throws SQLException {
100-
return (long) getInt(columnIndex);
99+
return getInt(columnIndex);
101100
}
102101

103102
@Override

jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaData.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import com.clickhouse.jdbc.ResultSetImpl;
99
import com.clickhouse.jdbc.internal.ClientInfoProperties;
1010
import com.clickhouse.jdbc.internal.DriverProperties;
11-
import com.clickhouse.jdbc.internal.JdbcUtils;
1211
import com.clickhouse.jdbc.internal.ExceptionUtils;
12+
import com.clickhouse.jdbc.internal.JdbcUtils;
1313
import com.clickhouse.jdbc.internal.MetadataResultSet;
1414
import com.clickhouse.logging.Logger;
1515
import com.clickhouse.logging.LoggerFactory;
@@ -826,7 +826,9 @@ public ResultSet getTableTypes() throws SQLException {
826826
}
827827
}
828828

829+
private static final String DATA_TYPE_COL = "DATA_TYPE";
829830
@Override
831+
@SuppressWarnings({"squid:S2077"})
830832
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
831833
//TODO: Best way to convert type to JDBC data type
832834
// TODO: handle useCatalogs == true and return schema catalog name
@@ -856,13 +858,13 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa
856858
"'NO' as IS_AUTOINCREMENT, " +
857859
"'NO' as IS_GENERATEDCOLUMN " +
858860
" FROM system.columns" +
859-
" WHERE database LIKE '" + (schemaPattern == null ? "%" : schemaPattern) + "'" +
860-
" AND table LIKE '" + (tableNamePattern == null ? "%" : tableNamePattern) + "'" +
861-
" AND name LIKE '" + (columnNamePattern == null ? "%" : columnNamePattern) + "'" +
861+
" WHERE database LIKE '" + (schemaPattern == null ? "%" : JdbcUtils.escapeQuotes(schemaPattern)) + "'" +
862+
" AND table LIKE '" + (tableNamePattern == null ? "%" : JdbcUtils.escapeQuotes(tableNamePattern)) + "'" +
863+
" AND name LIKE '" + (columnNamePattern == null ? "%" : JdbcUtils.escapeQuotes(columnNamePattern)) + "'" +
862864
" ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION";
863865
try {
864866
return new MetadataResultSet((ResultSetImpl) connection.createStatement().executeQuery(sql))
865-
.transform("DATA_TYPE", ClickHouseColumn.of("DATA_TYPE", "Int32"), DatabaseMetaData::columnDataTypeToSqlType);
867+
.transform(DATA_TYPE_COL, ClickHouseColumn.of(DATA_TYPE_COL, ClickHouseDataType.Int32.name()), DatabaseMetaData::columnDataTypeToSqlType);
866868
} catch (Exception e) {
867869
throw ExceptionUtils.toSqlState(e);
868870
}

jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcUtilsTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package com.clickhouse.jdbc.internal;
22

3-
import com.clickhouse.jdbc.JdbcIntegrationTest;
43
import org.testng.annotations.Test;
54

65
import java.util.List;
76

87
import static org.testng.Assert.assertEquals;
98

10-
public class JdbcUtilsTest extends JdbcIntegrationTest {
9+
public class JdbcUtilsTest {
1110
@Test(groups = { "integration" })
1211
public void testTokenizeSQL() {
1312
String sql1 = "SELECT * FROM table WHERE id = 1";
@@ -48,4 +47,14 @@ public void testTokenizeSQL() {
4847
assertEquals(tokens3.get(4), "WHERE");
4948
assertEquals(tokens3.get(5).replace("\"", ""), "id = 1 AND name = 'John' OR age = 30");
5049
}
50+
51+
@Test
52+
public void testEscapeQuotes() {
53+
String[] inStr = new String[]{"%valid_name%", "' OR 1=1 --", "\" OR 1=1 --"};
54+
String[] outStr = new String[]{"%valid_name%", "\\' OR 1=1 --", "\\\" OR 1=1 --"};
55+
56+
for (int i = 0; i < inStr.length; i++) {
57+
assertEquals(JdbcUtils.escapeQuotes(inStr[i]), outStr[i]);
58+
}
59+
}
5160
}

0 commit comments

Comments
 (0)