| 2845 | } |
| 2846 | |
| 2847 | Status FuzzIpcFile(const uint8_t* data, int64_t size) { |
| 2848 | auto buffer = std::make_shared<Buffer>(data, size); |
| 2849 | |
| 2850 | Status final_status; |
| 2851 | |
| 2852 | struct IpcReadResult { |
| 2853 | std::shared_ptr<Schema> schema; |
| 2854 | std::vector<RecordBatchWithMetadata> batches = {}; |
| 2855 | ReadStats stats = {}; |
| 2856 | }; |
| 2857 | |
| 2858 | // Try to read the IPC file as a stream to compare the results (differential fuzzing) |
| 2859 | auto do_stream_read = [&]() -> Result<IpcReadResult> { |
| 2860 | io::BufferReader buffer_reader(buffer); |
| 2861 | // Skip magic bytes at the beginning |
| 2862 | RETURN_NOT_OK( |
| 2863 | buffer_reader.Advance(bit_util::RoundUpToMultipleOf8(kArrowMagicBytes.length()))); |
| 2864 | ARROW_ASSIGN_OR_RAISE(auto batch_reader, RecordBatchStreamReader::Open( |
| 2865 | &buffer_reader, FuzzingOptions())); |
| 2866 | |
| 2867 | std::vector<RecordBatchWithMetadata> batches; |
| 2868 | while (true) { |
| 2869 | ARROW_ASSIGN_OR_RAISE(auto batch, batch_reader->ReadNext()); |
| 2870 | if (!batch.batch && !batch.custom_metadata) { |
| 2871 | // EOS |
| 2872 | break; |
| 2873 | } |
| 2874 | RETURN_NOT_OK(ValidateFuzzBatch(batch)); |
| 2875 | batches.push_back(batch); |
| 2876 | } |
| 2877 | return IpcReadResult{batch_reader->schema(), batches, batch_reader->stats()}; |
| 2878 | }; |
| 2879 | |
| 2880 | auto do_file_read = [&](bool pre_buffer) -> Result<IpcReadResult> { |
| 2881 | io::BufferReader buffer_reader(buffer); |
| 2882 | ARROW_ASSIGN_OR_RAISE(auto batch_reader, |
| 2883 | RecordBatchFileReader::Open(&buffer_reader, FuzzingOptions())); |
| 2884 | if (pre_buffer) { |
| 2885 | // Pre-buffer all record batches |
| 2886 | RETURN_NOT_OK(batch_reader->PreBufferMetadata(/*indices=*/{})); |
| 2887 | } |
| 2888 | |
| 2889 | IpcReadResult result = {.schema = batch_reader->schema()}; |
| 2890 | const int n_batches = batch_reader->num_record_batches(); |
| 2891 | // Delay error return until the end, as we want to access all record batches |
| 2892 | Status st; |
| 2893 | for (int i = 0; i < n_batches; ++i) { |
| 2894 | RecordBatchWithMetadata batch; |
| 2895 | st &= batch_reader->ReadRecordBatchWithCustomMetadata(i).Value(&batch); |
| 2896 | st &= ValidateFuzzBatch(batch); |
| 2897 | result.batches.push_back(batch); |
| 2898 | } |
| 2899 | RETURN_NOT_OK(st); |
| 2900 | result.stats = batch_reader->stats(); |
| 2901 | return result; |
| 2902 | }; |
| 2903 | |
| 2904 | // Persistent read result for differential fuzzing. |
no test coverage detected