[java-firestore] UserDataConverter throws IndexOutOfBoundsException on an empty __binary__ value
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 74/100
Piste de recherche
Lis java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UserDataConverter.java autour de decodeBsonBinary aux lignes 414–425, où l’issue signale l’appel non vérifié à bytes.byteAt(0). Ajoute un test de régression pour une valeur __binary__ vide et exécute les tests unitaires Firestore pertinents. Le travail est terminé lorsque le décodage signale une erreur de décodage propre au champ au lieu de IndexOutOfBoundsException.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Issue Details
UserDataConverter.decodeBsonBinary reads the subtype byte with bytes.byteAt(0) without checking that the __binary__ bytes are non-empty, so an empty __binary__ value throws ArrayIndexOutOfBoundsException (an IndexOutOfBoundsException) from DocumentSnapshot.get(...) instead of a decode error naming the field:
Reachability. Writing these forms through the Firestore API is refused with INVALID_ARGUMENT by the emulator (587.0.0-emulators) and by both a Standard-edition and an Enterprise-edition database, so a document written through that API should never carry them (measured 2026-10-03). Writes through the Enterprise edition's MongoDB-compatible API were not tried. Even if the input is unreachable today, the decoder assumes something it does not check, and the consequence is an unchecked runtime exception from a getter, where a FirestoreException naming the malformed value would be expected. A length check before byteAt(0) would fix it.
Found while building an Apache Flink source on google-cloud-firestore (flink-gcp/flink-connector-gcp).
Environment
- OS Type and Version: macOS 26 (arm64)
- Java Version and JDK Vendor: Eclipse Temurin 17.0.20
The reproducer is offline: it builds the snapshot from a Document proto with com.google.cloud.firestore.Internal, the way the client does for a server response, and sends nothing.
Dependencies
- Libraries-Bom: 26.90.0
- google-cloud-firestore 3.49.0
- Gax: 2.87.0
- Auth: 1.54.0
The affected code is identical in 3.49.0 and on main.
Reproducer
package repro;
import com.google.cloud.NoCredentials;
import com.google.cloud.Timestamp;
import com.google.cloud.firestore.DocumentSnapshot;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.FirestoreOptions;
import com.google.cloud.firestore.Internal;
import com.google.cloud.firestore.Query;
import com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc;
import com.google.firestore.v1.Document;
import com.google.firestore.v1.MapValue;
import com.google.firestore.v1.Value;
import com.google.protobuf.ByteString;
/** Offline: builds snapshots from protos as the client would receive them; nothing is sent. */
public class DecodeDefects {
public static void main(String[] args) throws Exception {
FirestoreOptions options =
FirestoreOptions.newBuilder()
.setProjectId("demo")
.setCredentials(NoCredentials.getInstance())
.build();
Firestore db = options.getService();
// 1. An __int__ beyond 32 bits is narrowed silently.
long stored = (1L << 40) + 5;
DocumentSnapshot wide = snapshot(options, reserved("__int__", Value.newBuilder().setIntegerValue(stored).build()));
System.out.println("stored __int__: " + stored);
System.out.println("decoded value: " + wide.get("k"));
Query query = db.collection("c").orderBy("k").startAfter(wide);
System.out.println("cursor value: " + query.toProto().getStructuredQuery().getStartAt().getValues(0).getMapValue());
// 2. An empty __binary__ throws instead of failing with a decode error.
DocumentSnapshot empty = snapshot(options, reserved("__binary__", Value.newBuilder().setBytesValue(ByteString.EMPTY).build()));
try {
System.out.println("decoded value: " + empty.get("k"));
} catch (RuntimeException e) {
System.out.println("empty __binary__ threw: " + e);
}
System.exit(0);
}
static Value reserved(String key, Value value) {
return Value.newBuilder().setMapValue(MapValue.newBuilder().putFields(key, value)).build();
}
static DocumentSnapshot snapshot(FirestoreOptions options, Value value) throws Exception {
Timestamp now = Timestamp.now();
Document document =
Document.newBuilder()
.setName("projects/demo/databases/(default)/documents/c/x")
.setCreateTime(now.toProto())
.setUpdateTime(now.toProto())
.putFields("k", value)
.build();
try (GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(options)) {
return new Internal(options, rpc).snapshotFromProto(now, document);
}
}
}
Only the second case concerns this issue; the first is reported in #14633.
Logs and Stack Trace
stored __int__: 1099511627781
decoded value: Int32Value{value=5}
cursor value: fields {
key: "__int__"
value {
integer_value: 5
}
}
empty __binary__ threw: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
Behavior
Deterministic: any __binary__ whose bytes are empty.
- Langage dominant
- Java
- Étoiles
- 2.1k
- Forks
- 1.2k
- Merge moyen
- 2 j 21 h
- PR mergées (30 j)
- 139
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Aucun 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 googleapis/google-cloud-java
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
googleapis/google-cloud-java#14636 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
googleapis/google-cloud-java#14635 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
googleapis/google-cloud-java#14579 ·
Les mainteneurs répondent en général sous 1 jour
-
[java-firestore] CustomClassMapper.convertBigDecimal calls .abs() on Double, unintentionally flipping negative values to positivePeut-être pris @wu-hui l’a pris il y a 15 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
googleapis/google-cloud-java#14533 · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
Github CI failing when trying to install xmllintPeut-être pris @blakeli0 l’a pris il y a 51 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
googleapis/google-cloud-java#14132 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de googleapis/google-cloud-java
Issues similaires
-
area/plugin good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
kestra-io/plugin-kestra#200 ·
Les mainteneurs répondent en général sous 1 jour
-
bug untriaged
Difficulté 1/5 Moins d'une heure Accessibilité débutants 92/100
opensearch-project/search-relevance#618 ·
Les mainteneurs répondent en général sous 3 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
apache/rocketmq-dashboard#6716 ·
Les mainteneurs répondent en général sous 3 jours
-
DefaultRedisList.get(int) does not reject an index equal to the list sizePeut-être pris @ryujungkyun l’a pris aujourd’hui. Ouvertestatus: waiting-for-triage
Difficulté 1/5 Moins d'une heure Accessibilité débutants 68/100
spring-projects/spring-data-redis#3471 ·
Les mainteneurs répondent en général sous 5 jours
-
Upgrade to Micrometer 1.17.2Ouvertein: build type: dependency-upgrade
Difficulté 1/5 Moins d'une heure Accessibilité débutants 62/100
spring-projects/spring-ldap#1791 ·
Les mainteneurs répondent en général sous 1 jour