CurtHagenlocher opened a new pull request, #470: URL: https://github.com/apache/arrow-dotnet/pull/470
## What's Changed A zero-length `string`, `binary`, `large_string`, `large_binary`, `list`, `large_list` or `map` array may have an empty (0-byte) offsets buffer. Arrow C++ and nanoarrow write such arrays to IPC, and `ArrowStreamReader` reads them. #462 reported that concatenating them fails, and #465 fixes that. Auditing the rest of the library for the same input found three more failures, which this PR fixes. - **C Data export.** `CArrowArrayExporter` exported the empty offsets buffer as a null pointer. The spec allows a null pointer only where the buffer's size "would be 0". Arrow C++ computes the size of an offsets buffer as `offset + length + 1` offsets, so pyarrow rejects the export: `ArrowArrayStruct contains null data pointer for a buffer with non-zero computed size`. The exporter now exports `offset + 1` zeroed offsets in its place. - **C Data import.** `CArrowArrayImporter` read `offsets[length]` without checking for null. That hit a `Debug.Assert` in Debug builds and threw `NullReferenceException` in Release, including on a .NET → .NET round trip of an array read from IPC. For lists, it wrapped the null pointer in a non-empty buffer. The importer now accepts a null offsets buffer for a zero-length array, since older versions of this library produce one. For a non-empty array it throws `InvalidOperationException`. - **`ValueOffsets`.** The public accessor on `BinaryArray`, `LargeBinaryArray`, `ListArray` and `LargeListArray`, and so on string and map arrays, threw `ArgumentOutOfRangeException`. It now returns a single zero offset, keeping the `Length + 1` invariant. Internal callers already checked for zero length first. ### Tests The tests use zero-length arrays of each affected type with empty offsets buffers, including nested children (`list<string>`, `map<string, int32>`): - `ValueOffsetsOfZeroLengthArrayWithEmptyOffsets` - `ExportZeroLengthArrayWithEmptyOffsets`: the exported offsets are non-null and zero, and the array imports back. - `ImportZeroLengthArrayWithNullOffsets` and `ImportNonEmptyArrayWithNullOffsetsThrows` - A Python interop test, `ExportZeroLengthArrayWithEmptyOffsets`: pyarrow imports each exported array and validates it with `validate(full=True)`. It fails without this change with the C++ error quoted above. I also ran a wider check outside the test suite. pyarrow wrote zero-length arrays with minimal buffers for 26 types to IPC. .NET read them, round-tripped each through the C Data interface, and concatenated it with normal data, and pyarrow validated the results. With this change all types pass except `null`, which fails for an unrelated reason fixed in #469. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <[email protected]> -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
