[client-v2] Float NaN and Infinity are silently written into integer columns (NaN -> 0, Inf -> MAX_VALUE), also into Nullable(Int*)
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 55/100
Piste de recherche
Start with client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java, especially convertToInteger, convertToLong, and the NumberConverter.toBigInteger path. Trace how integer and Decimal targets handle non-finite Float and Double inputs, then locate or add coverage for the listed scalar and nested types. Done means those inputs fail with a clear client-side error instead of being written as zero or maximum values.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Describe the bug
SerializerUtils.serializePrimitiveData converts a user-supplied Number to an integer column value with plain Java narrowing — convertToInteger / convertToLong call ((Number) value).intValue() / .longValue() (client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java:1056-1082, used at lines 656-681 and 746).
Java narrowing of a non-finite double produces a legal-looking number instead of failing:
| Written value | Column | Stored value |
|---|---|---|
Double.NaN |
Nullable(Int32) |
0 (not NULL, no error) |
Double.POSITIVE_INFINITY |
Int32 |
2147483647 |
Double.POSITIVE_INFINITY |
Int64 |
9223372036854775807 |
No exception is raised and nothing is logged, so the row is silently corrupted. The server itself rejects both conversions (SELECT toInt32(nan) and SELECT toInt32(inf) fail with code 70, CANNOT_CONVERT_TYPE), so the client is more permissive than the server it writes to.
This is related to #3176 (silent wrapping of out-of-range integers) but is a distinct failure mode: the intValue() vs longValue() comparison suggested there (NumberConverter.toInt) does not catch NaN — both accessors return 0 for it — and does not catch +Inf for Int64 either. A non-finite check is needed on top of the range check.
ClickHouse server version
26.10.3.7 (local server at http://localhost:8123). The test below was run against it.
Reproduction
TestNG test in client-v2:
package com.clickhouse.client.insert;
import com.clickhouse.client.api.Client;
import com.clickhouse.client.api.data_formats.RowBinaryFormatWriter;
import com.clickhouse.client.api.insert.InsertResponse;
import com.clickhouse.client.api.insert.InsertSettings;
import com.clickhouse.client.api.metadata.TableSchema;
import com.clickhouse.client.api.query.GenericRecord;
import com.clickhouse.data.ClickHouseFormat;
import org.testng.annotations.Test;
import java.util.List;
public class NanIntScratchTest {
@Test
public void nanAndInfIntoIntegerColumns() throws Exception {
try (Client client = new Client.Builder()
.addEndpoint("http://localhost:8123")
.setUsername("default").setPassword("")
.compressServerResponse(false).compressClientRequest(false)
.build()) {
client.execute("DROP TABLE IF EXISTS nan_int_test").get();
client.execute("CREATE TABLE nan_int_test (v Nullable(Int32), w Int32, i64 Int64, f Float64) ENGINE Memory").get();
TableSchema schema = client.getTableSchema("nan_int_test");
Object[][] rows = new Object[][]{
{13.0d, 13.0d, 13.0d, 13.0d},
{Double.NaN, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0d},
};
ClickHouseFormat format = ClickHouseFormat.RowBinary;
try (InsertResponse r = client.insert("nan_int_test", out -> {
RowBinaryFormatWriter w = new RowBinaryFormatWriter(out, schema, format);
for (Object[] row : rows) {
for (int i = 0; i < row.length; i++) {
w.setValue(i + 1, row[i]);
}
w.commitRow();
}
}, format, new InsertSettings()).get()) {
System.out.println("written rows = " + r.getWrittenRows());
}
for (GenericRecord rec : client.queryAll("SELECT v, w, i64, f FROM nan_int_test ORDER BY f")) {
System.out.println("v=" + rec.getObject(1) + " w=" + rec.getInteger(2)
+ " i64=" + rec.getLong(3) + " f=" + rec.getDouble(4));
}
}
}
}
Actual output:
written rows = 2
v=0 w=2147483647 i64=9223372036854775807 f=1.0
v=13 w=13 i64=13 f=13.0
Expected: the insert fails with a clear client-side error for the non-finite values (as the server does), instead of writing 0 / MAX_VALUE.
Suggested fix
In client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java, reject non-finite values before narrowing — in convertToInteger (line 1056) and convertToLong (line 1070), and in the NumberConverter.toBigInteger path used for UInt64/Int128/Int256, throw when a Float/Double argument is NaN or infinite. The same check is needed for Decimal targets. Nested containers (Array(Nullable(Int*)), Tuple, Map, LowCardinality(Nullable(Int*))) go through the same converters, so one check covers them.
Link
Relayed from the equivalent bug in clickhouse-connect: https://github.com/ClickHouse/clickhouse-connect/issues/1172
- Langage dominant
- Java
- Étoiles
- 1.6k
- Forks
- 649
- Merge moyen
- 1 j 20 h
- PR mergées (30 j)
- 39
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de ClickHouse/clickhouse-java
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
ClickHouse/clickhouse-java#3349 ·
Les mainteneurs répondent en général sous 1 jour
-
bug jdbc-v2
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
ClickHouse/clickhouse-java#3347 ·
Les mainteneurs répondent en général sous 1 jour
-
bug jdbc-v2
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
ClickHouse/clickhouse-java#3326 ·
Les mainteneurs répondent en général sous 1 jour
-
[client-v2] Enum8/Enum16 insert accepts a non-member integer and uses Enum.ordinal(), silently storing values that are not enum membersPeut-être pris @jaya232 l’a pris il y a 6 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
ClickHouse/clickhouse-java#3304 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
bug jdbc-v2
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
ClickHouse/clickhouse-java#3214 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de ClickHouse/clickhouse-java
Issues similaires
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
dekobon/big-code-analysis#1913 ·
Les mainteneurs répondent en général sous 1 jour
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour
-
bug:unconfirmed
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
UniversalMediaServer/UniversalMediaServer#6473 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 82/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
Les mainteneurs répondent en général sous 1 jour