zjw1111 commented on code in PR #260:
URL: https://github.com/apache/paimon-cpp/pull/260#discussion_r3893468302


##########
src/paimon/format/mosaic/mosaic_reader_builder.h:
##########
@@ -30,10 +31,13 @@ namespace paimon::mosaic {
 class MosaicReaderBuilder : public ReaderBuilder {
  public:
     explicit MosaicReaderBuilder(int32_t batch_size)
-        : batch_size_(batch_size), pool_(GetDefaultPool()) {}
+        : batch_size_(batch_size),
+          pool_(GetDefaultPool()),
+          arrow_pool_(GetSharedArrowPool(pool_)) {}
 
     ReaderBuilder* WithMemoryPool(const std::shared_ptr<MemoryPool>& pool) 
override {
         pool_ = pool;
+        arrow_pool_ = GetSharedArrowPool(pool);

Review Comment:
   `WithMemoryPool(nullptr)` now calls `GetSharedArrowPool(nullptr)`, whose 
adaptor dereferences the shared pointer in its initializer. This crashes before 
`Build()` can return its existing `Invalid` status. The same eager-construction 
path exists in `OrcReaderBuilder` through `OrcReadMemory`.



##########
src/paimon/common/reader/reader_utils_test.cpp:
##########
@@ -59,15 +85,32 @@ TEST(ReaderUtilsTest, TestAddAllValidBitmap) {
     check_result("[10, 20, 30]");
     check_result("");
 }
+
+TEST(ReaderUtilsTest, TestCollectResultReleasesBufferedBatchesOnError) {
+    auto array = arrow::ipc::internal::json::ArrayFromJSON(arrow::int32(), 
"[1]").ValueOrDie();
+    ASSERT_OK_AND_ASSIGN(BatchReader::ReadBatch batch, 
ReadResultCollector::GetReadBatch(array));
+
+    std::shared_ptr<int> lifetime = std::make_shared<int>(1);

Review Comment:
   This new test uses plain `int` for the lifetime state. The project 
code-style rule requires fixed-width integer types and explicitly disallows 
plain `int`, including in tests.



##########
src/paimon/common/reader/reader_utils.cpp:
##########
@@ -92,12 +94,13 @@ Result<BatchReader::ReadBatch> 
ReaderUtils::ApplyBitmapToReadBatch(
     PAIMON_ASSIGN_OR_RAISE(arrow::ArrayVector array_vec,
                            GenerateFilteredArrayVector(arrow_array, bitmap));
     PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(std::shared_ptr<arrow::Array> result,
-                                      arrow::Concatenate(array_vec, 
arrow_pool));
+                                      arrow::Concatenate(array_vec, 
arrow_pool.get()));
     assert(result && result->length() > 0);
     std::unique_ptr<ArrowArray> result_c_array = 
std::make_unique<ArrowArray>();
     std::unique_ptr<ArrowSchema> result_c_schema = 
std::make_unique<ArrowSchema>();
     PAIMON_RETURN_NOT_OK_FROM_ARROW(
         arrow::ExportArray(*result, result_c_array.get(), 
result_c_schema.get()));
+    PAIMON_RETURN_NOT_OK(AddArrowArrayLifetime(result_c_array.get(), 
arrow_pool));

Review Comment:
   When `AddArrowArrayLifetime` fails because the lifetime is empty or its 
allocation throws `std::bad_alloc`, it releases only `result_c_array`. This 
return path then destroys `result_c_schema` as a plain `unique_ptr` without 
invoking `ArrowSchemaRelease`, leaking the schema private data exported above. 
The same pattern appears at the other `ExportArray` plus 
`AddArrowArrayLifetime` call sites.



-- 
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]

Reply via email to