ArrowArrayConcatenator throws on a zero-length string/binary array with an empty offsets buffer
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 90/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- csharp
- Ambito
- data-engineering
Direzione di ricerca
Inizia da src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs, leggendo ConcatenateVariableBinaryValueBuffer() e ConcatenateLargeVariableBinaryValueBuffer() insieme ai percorsi vicini che ignorano gli input di lunghezza zero. Verifica che la concatenazione di una stringa vuota o di un array binario vuoto con un buffer di offset vuoto non generi più un’eccezione e che i valori dell’altro input siano preservati.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
ArrowArrayConcatenator.Concatenate throws ArgumentOutOfRangeException when one of the inputs is a zero-length string, binary, large_string or large_binary array whose offsets buffer is empty (0 bytes).
That input is valid, and it arrives through IPC. For a length-0 variable-size array, Arrow C++ accepts an absent or empty offsets buffer (ARROW-544, ValidateOffsetsAndSizes in cpp/src/arrow/array/validate.cc: "For length 0, an empty offsets buffer is accepted"). Its IPC writer emits that buffer as it is (GetZeroBasedValueOffsets returns array.value_offsets() unchanged when length() == 0). nanoarrow's IPC writer does the same. Apache.Arrow's ArrowStreamReader reads such a batch fine. Only concatenating it fails.
Seen on Apache.Arrow 23.0.0 (.NET 10, Linux arm64). The code is unchanged on main as of 117da35.
Cause
ConcatenateVariableBinaryValueBuffer() (src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs:972) and ConcatenateLargeVariableBinaryValueBuffer() (:869) slice Length + 1 offsets from every input:
var offsets = arrayData.Buffers[1].Span.CastTo<int>().Slice(arrayData.Offset, arrayData.Length + 1);
For a length-0 input with an empty offsets buffer, that slices one element out of an empty span and throws. The neighbouring list paths (:758) and the offset-buffer concatenators ConcatenateOffsetBuffer() (:995) and ConcatenateLargeOffsetBuffer() already skip such inputs with if (arrayData.Length == 0) continue;. Those two functions are missing the same guard. A length-0 input contributes no value bytes, so skipping it is correct.
Repro (pure C#)
using Apache.Arrow;
using Apache.Arrow.Types;
// A zero-length string array with an empty (0-byte) offsets buffer, as read from IPC
var empty = new StringArray(new ArrayData(StringType.Default, length: 0, nullCount: 0, offset: 0,
new[] { ArrowBuffer.Empty, ArrowBuffer.Empty, ArrowBuffer.Empty }));
var other = new StringArray.Builder().Append("a").Build();
Console.WriteLine(ArrowArrayConcatenator.Concatenate(new IArrowArray[] { empty, other }).Length);
Unhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
at Apache.Arrow.ArrayDataConcatenator.ArrayDataConcatenationVisitor.ConcatenateVariableBinaryValueBuffer()
at Apache.Arrow.ArrayDataConcatenator.ArrayDataConcatenationVisitor.ConcatenateVariableBinaryArrayData(IArrowType type)
at Apache.Arrow.ArrayDataConcatenator.ArrayDataConcatenationVisitor.Visit(StringType type)
Repro (IPC from pyarrow)
This writes a stream whose string, large_string and list<int32> columns have 0-byte offsets buffers. pyarrow 26.0.0 validates it with validate(full=True) before writing and after reading it back:
import pyarrow as pa, pyarrow.ipc as ipc
cols = {
"s": pa.Array.from_buffers(pa.string(), 0, [None, None, pa.py_buffer(b"")]),
"ls": pa.Array.from_buffers(pa.large_string(), 0, [None, None, pa.py_buffer(b"")]),
"l": pa.Array.from_buffers(pa.list_(pa.int32()), 0, [None, None],
children=[pa.array([], pa.int32())]),
}
batch = pa.record_batch(list(cols.values()), names=list(cols))
with ipc.new_stream("empty_offsets.arrows", batch.schema) as w:
w.write_batch(batch)
Reading it with ArrowStreamReader and calling ArrowArrayConcatenator.Concatenate(new[] { col, col }) on each column gives:
column 0 utf8 length=0
ArgumentOutOfRangeException at ...ConcatenateVariableBinaryValueBuffer()
column 1 large_utf8 length=0
ArgumentOutOfRangeException at ...ConcatenateLargeVariableBinaryValueBuffer()
column 2 list length=0
Concatenate([col, col]) length=0 <- lists already skip empty inputs
Expected: the empty input contributes nothing, and the concatenation succeeds.
Suggested fix: add if (arrayData.Length == 0) continue; to the loops in ConcatenateVariableBinaryValueBuffer() and ConcatenateLargeVariableBinaryValueBuffer(), as the other offset-reading paths in the file already do.
Context
I hit this when a DuckDB extension started writing Arrow IPC with nanoarrow, and a .NET worker using Apache.Arrow concatenated the incoming batches. The value array of an empty MAP arrived as a zero-length string with an empty offsets buffer.
- Lingua principale
- C#
- Stelle
- 42
- Fork
- 31
- Merge medio
- 1g 3h
- PR unite (30g)
- 21
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di apache/arrow-dotnet
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
apache/arrow-dotnet#410 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Support the proposed DictionaryEncoding.custom_metadata (format 1.6) for dictionaries of extension types in IPCForse già presa @CurtHagenlocher l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 42/100
apache/arrow-dotnet#475 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 38/100
apache/arrow-dotnet#464 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 38/100
apache/arrow-dotnet#409 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
apache/arrow-dotnet#397 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di apache/arrow-dotnet
Issue simili
-
status:waiting-for-triage type:bug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 84/100
microsoftgraph/msgraph-sdk-dotnet#3194 ·
I maintainer di solito rispondono entro 1 giorno
-
Backend enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
I maintainer di solito rispondono entro 1 giorno
-
UI: money shows the minus sign next to the number, not before the currency (IL -3.0m, not -IL 3.0m)Apertaarea: sim area: unity enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
eyalgolan/statecraft-israel#1107 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
dimitar-radenkov/Pointframe#271 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
qew21/Genshin-Subtitles#45 ·