Skip to content

GH-49966: [C++] Detect different endianness between IPC file and stream in IPC file fuzzer - #49968

Merged
pitrou merged 2 commits into
apache:mainfrom
pitrou:gh49966-fuzz-ipc-file-endianness
Jun 4, 2026
Merged

GH-49966: [C++] Detect different endianness between IPC file and stream in IPC file fuzzer#49968
pitrou merged 2 commits into
apache:mainfrom
pitrou:gh49966-fuzz-ipc-file-endianness

Conversation

@pitrou

@pitrou pitrou commented May 12, 2026

Copy link
Copy Markdown
Member

Rationale for this change

In the IPC file format, the IPC file footer has a copy of the embedded IPC stream's schema. However, the two copies may be different in case of an invalid/corrupted IPC file. The fuzzer would then fail with differing contents between IPC file and stream, as only one of them would have undergone endianness swapping.

Issue found by OSS-Fuzz: https://issues.oss-fuzz.com/issues/506111650

What changes are included in this PR?

  1. Add a member variable in ipc::ReadStats that reflects the original endianness of the IPC schema (before the endianness was normalized to native)
  2. Compare the original endianness of the IPC stream and file schemas in the IPC file fuzzer, and skip comparing the contents if the endianness differs
  3. Add unit tests for endianness detection and conversion based on the corresponding "golden" integration files

Are these changes tested?

Yes, by additional unit tests and additional fuzz regression file.

Are there any user-facing changes?

No.

@pitrou

pitrou commented May 12, 2026

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit -g cpp

@pitrou

pitrou commented May 12, 2026

Copy link
Copy Markdown
Member Author

@kiszk Is it possible for you to run the new unit test arrow-ipc-endianness-test on a big endian machine?

@github-actions

This comment was marked as outdated.

@kiszk

kiszk commented May 12, 2026

Copy link
Copy Markdown
Member

Thank you. I will do it next week since I am taking a vacation this week.

@pitrou

pitrou commented May 12, 2026

Copy link
Copy Markdown
Member Author

Also @paleolimbot FYI

@pitrou
pitrou marked this pull request as ready for review May 12, 2026 16:38
@pitrou
pitrou requested a review from lidavidm as a code owner May 12, 2026 16:38
@pitrou
pitrou force-pushed the gh49966-fuzz-ipc-file-endianness branch from 7dbefac to b26a93d Compare May 12, 2026 16:40
@pitrou

pitrou commented May 12, 2026

Copy link
Copy Markdown
Member Author

It looks like the Valgrind errors are related, I'll take a look.

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! These changes seem reasonable pending CI.

I'm wondering if I need to update anything in nanoarrow's reader to cover this case. I don't think so because we always byte swap to native endian on read (i.e., no option to skip this) but I may be misunderstanding the failure.

@github-actions github-actions Bot added awaiting merge Awaiting merge and removed awaiting review Awaiting review labels May 12, 2026
@pitrou

pitrou commented May 13, 2026

Copy link
Copy Markdown
Member Author

I'm wondering if I need to update anything in nanoarrow's reader to cover this case. I don't think so because we always byte swap to native endian on read (i.e., no option to skip this) but I may be misunderstanding the failure.

I don't think there's anything to do, because the problem was in the fuzz target, not in the IPC reader itself. Valid IPC files should have the same schema in the file footer and in the embedded IPC stream.

@pitrou
pitrou force-pushed the gh49966-fuzz-ipc-file-endianness branch from b26a93d to 86203c1 Compare June 3, 2026 13:44
@pitrou

pitrou commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

Thank you. I will do it next week since I am taking a vacation this week.

@kiszk Ping :)

@pitrou

pitrou commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit -g cpp

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Revision: 86203c1

Submitted crossbow builds: ursacomputing/crossbow @ actions-8f178ec382

Task Status
example-cpp-minimal-build-static GitHub Actions
example-cpp-minimal-build-static-system-dependency GitHub Actions
example-cpp-tutorial GitHub Actions
test-build-cpp-fuzz GitHub Actions
test-conda-cpp GitHub Actions
test-conda-cpp-valgrind GitHub Actions
test-debian-13-cpp-amd64 GitHub Actions
test-debian-13-cpp-i386 GitHub Actions
test-debian-experimental-cpp-gcc-15 GitHub Actions
test-fedora-42-cpp GitHub Actions
test-ubuntu-22.04-cpp GitHub Actions
test-ubuntu-22.04-cpp-bundled GitHub Actions
test-ubuntu-22.04-cpp-emscripten GitHub Actions
test-ubuntu-22.04-cpp-no-threading GitHub Actions
test-ubuntu-24.04-cpp GitHub Actions
test-ubuntu-24.04-cpp-bundled-offline GitHub Actions
test-ubuntu-24.04-cpp-gcc-13-bundled GitHub Actions
test-ubuntu-24.04-cpp-gcc-14 GitHub Actions
test-ubuntu-24.04-cpp-minimal-with-formats GitHub Actions
test-ubuntu-24.04-cpp-thread-sanitizer GitHub Actions

@pitrou
pitrou force-pushed the gh49966-fuzz-ipc-file-endianness branch from 8ba9a96 to 4c61110 Compare June 3, 2026 14:52
@pitrou

pitrou commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit test-conda-cpp-valgrind

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Revision: 4c61110

Submitted crossbow builds: ursacomputing/crossbow @ actions-5600ef63e7

Task Status
test-conda-cpp-valgrind GitHub Actions

@pitrou

pitrou commented Jun 4, 2026

Copy link
Copy Markdown
Member Author

I managed to cross-compile Arrow for s390x and then run the unit tests under emulation. The new arrow-ipc-endianness-test passed successfully.

@pitrou
pitrou merged commit de5b933 into apache:main Jun 4, 2026
55 checks passed
@pitrou pitrou removed the awaiting merge Awaiting merge label Jun 4, 2026
@pitrou
pitrou deleted the gh49966-fuzz-ipc-file-endianness branch June 4, 2026 16:43
@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 2 benchmarking runs that have been run so far on merge-commit de5b933.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details.

@kiszk

kiszk commented Jun 13, 2026

Copy link
Copy Markdown
Member

@pitrou Sorry, I was busy after a vacation. While it was merged, I will check it this weekend.

@kiszk

kiszk commented Jun 13, 2026

Copy link
Copy Markdown
Member

@pitrou It works well on big-endian machine 🎉 Thank you very much for taking care of big-endian.

% git clone git@github.com:apache/arrow
% cd arrow
% git submodule update --init --recursive
...
% mkdir build && cd build
% cmake .. --preset ninja-debug-flight
...
% cmake --build .
...
% export ARROW_TEST_DATA=/home/ishizaki/arrow/testing/data
% debug/arrow-ipc-endianness-test 
Running main() from gmock_main.cc
[==========] Running 38 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 38 tests from TestEndianness/TestEndianness
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_datetime
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_datetime (3 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_decimal
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_decimal (35 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_decimal256
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_decimal256 (28 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_dictionary
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_dictionary (1 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_dictionary_unsigned
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_dictionary_unsigned (1 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_extension
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_extension (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_interval
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_interval (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_map
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_map (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_nested
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_nested (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_nested_dictionary
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_nested_dictionary (1 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_nested_large_offsets
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_nested_large_offsets (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_null
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_null (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_null_trivial
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_null_trivial (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_primitive
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_primitive (2 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_primitive_large_offsets
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_primitive_large_offsets (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_primitive_no_batches
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_primitive_no_batches (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_primitive_zerolength
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_primitive_zerolength (2 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_recursive_nested
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_recursive_nested (0 ms)
[ RUN      ] TestEndianness/TestEndianness.StreamReader/generated_union
[       OK ] TestEndianness/TestEndianness.StreamReader/generated_union (1 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_datetime
[       OK ] TestEndianness/TestEndianness.FileReader/generated_datetime (2 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_decimal
[       OK ] TestEndianness/TestEndianness.FileReader/generated_decimal (31 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_decimal256
[       OK ] TestEndianness/TestEndianness.FileReader/generated_decimal256 (27 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_dictionary
[       OK ] TestEndianness/TestEndianness.FileReader/generated_dictionary (1 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_dictionary_unsigned
[       OK ] TestEndianness/TestEndianness.FileReader/generated_dictionary_unsigned (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_extension
[       OK ] TestEndianness/TestEndianness.FileReader/generated_extension (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_interval
[       OK ] TestEndianness/TestEndianness.FileReader/generated_interval (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_map
[       OK ] TestEndianness/TestEndianness.FileReader/generated_map (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_nested
[       OK ] TestEndianness/TestEndianness.FileReader/generated_nested (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_nested_dictionary
[       OK ] TestEndianness/TestEndianness.FileReader/generated_nested_dictionary (1 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_nested_large_offsets
[       OK ] TestEndianness/TestEndianness.FileReader/generated_nested_large_offsets (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_null
[       OK ] TestEndianness/TestEndianness.FileReader/generated_null (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_null_trivial
[       OK ] TestEndianness/TestEndianness.FileReader/generated_null_trivial (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_primitive
[       OK ] TestEndianness/TestEndianness.FileReader/generated_primitive (2 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_primitive_large_offsets
[       OK ] TestEndianness/TestEndianness.FileReader/generated_primitive_large_offsets (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_primitive_no_batches
[       OK ] TestEndianness/TestEndianness.FileReader/generated_primitive_no_batches (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_primitive_zerolength
[       OK ] TestEndianness/TestEndianness.FileReader/generated_primitive_zerolength (2 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_recursive_nested
[       OK ] TestEndianness/TestEndianness.FileReader/generated_recursive_nested (0 ms)
[ RUN      ] TestEndianness/TestEndianness.FileReader/generated_union
[       OK ] TestEndianness/TestEndianness.FileReader/generated_union (1 ms)
[----------] 38 tests from TestEndianness/TestEndianness (159 ms total)

[----------] Global test environment tear-down
[==========] 38 tests from 1 test suite ran. (159 ms total)
[  PASSED  ] 38 tests.

%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants