[java-firestore] UserDataConverter throws IndexOutOfBoundsException on an empty __binary__ value
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 74/100
Rechercherichtung
Lies java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UserDataConverter.java im Bereich von decodeBsonBinary in den Zeilen 414–425, wo der Issue-Aufruf bytes.byteAt(0) als ungeprüft bezeichnet. Füge einen Regressionstest für einen leeren __binary__-Wert hinzu und führe die relevanten Firestore-Unit-Tests aus. Die Aufgabe ist abgeschlossen, wenn das Decodieren einen feldspezifischen Decodierungsfehler statt IndexOutOfBoundsException meldet.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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.
- Vorherrschende Sprache
- Java
- Sterne
- 2.1k
- Forks
- 1.2k
- Ø Merge
- 2 T. 21 Std.
- Gemergte PRs (30 T.)
- 139
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus googleapis/google-cloud-java
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
googleapis/google-cloud-java#14636 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
googleapis/google-cloud-java#14635 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
googleapis/google-cloud-java#14579 ·
Maintainer antworten meist innerhalb von 1 Tag
-
[java-firestore] CustomClassMapper.convertBigDecimal calls .abs() on Double, unintentionally flipping negative values to positiveEvtl. vergeben @wu-hui hat das vor 16 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
googleapis/google-cloud-java#14533 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
Github CI failing when trying to install xmllintEvtl. vergeben @blakeli0 hat das vor 52 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
googleapis/google-cloud-java#14132 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in googleapis/google-cloud-java
Ähnliche Issues
-
approved bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
checkstyle/checkstyle#21981 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
beehive-lab/TornadoVM#1248 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug jdbc-v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
ClickHouse/clickhouse-java#3214 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Java and Kotlin (JVM): parse gradle/wrapper/gradle-wrapper.properties with exact line locationsOffenarea: detector eco: java help wanted lane: free-agent roadmap size: S type: parser
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
arminazimi/evergreen#355 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
micronaut-projects/micronaut-data#4134 ·
Maintainer antworten meist innerhalb von 1 Tag