github-actions[bot] commented on code in PR #67204:
URL: https://github.com/apache/doris/pull/67204#discussion_r3870460184


##########
be/src/load/group_commit/wal/wal_file_reader.cpp:
##########
@@ -92,18 +99,34 @@ Status WalFileReader::read_block(PBlock& block) {
     if (block_len == 0) {
         return Status::DataQualityError("fail to read wal {} ,block is empty", 
_file_name);
     }
-    if (_offset == file_reader->size()) {
-        LOG(WARNING) << "need read block with length=" << block_len << ", but 
offset=" << _offset
-                     << " reached end of WAL (path=" << _file_name
-                     << ", size=" << file_reader->size() << ")";
+    const size_t remaining_bytes = file_size - _offset;
+    if (block_len > remaining_bytes) {
+        LOG(WARNING) << "ignore incomplete wal tail, path=" << _file_name
+                     << ", file_size=" << file_size << ", read_offset=" << 
_offset
+                     << ", block_bytes=" << block_len << ", available_bytes=" 
<< remaining_bytes;
         return Status::EndOfFile("end of wal file");
     }
     // read block
     std::string block_buf;
     block_buf.resize(block_len);
     RETURN_IF_ERROR(file_reader->read_at(_offset, {block_buf.c_str(), 
block_len}, &bytes_read));
+    if (bytes_read != block_len) {
+        LOG(WARNING) << "ignore incomplete wal tail, path=" << _file_name
+                     << ", file_size=" << file_size << ", read_offset=" << 
_offset
+                     << ", block_bytes=" << block_len << ", read_block_bytes=" 
<< bytes_read;
+        return Status::EndOfFile("end of wal file");
+    }
     RETURN_IF_ERROR(_deserialize(block, block_buf, block_len, bytes_read));
     _offset += block_len;
+    const size_t checksum_bytes = file_size - _offset;
+    if (checksum_bytes < WalWriter::CHECKSUM_SIZE) {

Review Comment:
   **[P1] Do not publish a record whose checksum append never completed**
   
   `append_blocks` writes length, payload, and CRC in separate appends, so a 
crash—or a partial/error return while writing the CRC—can leave exactly 
`block_len` payload bytes plus 0-3 checksum bytes. In that case `write_wal` 
never returned success, but this branch still returns the parsed block as `OK`; 
replay can commit those unaccepted, unchecked rows and then delete the WAL. 
Please treat `block_len + CHECKSUM_SIZE` as the record boundary: return EOF 
without publishing when the full CRC is absent, and verify the CRC before 
returning the block.



##########
be/src/load/group_commit/wal/wal_file_reader.cpp:
##########
@@ -83,6 +83,13 @@ Status WalFileReader::read_block(PBlock& block) {
     if (_offset >= file_reader->size()) {
         return Status::EndOfFile("end of wal file");
     }
+    const size_t file_size = file_reader->size();
+    if (file_size - _offset < WalWriter::LENGTH_SIZE) {

Review Comment:
   **[P1] Handle a torn WAL header at startup too**
   
   This guards partial block framing, but the WAL header has the same crash 
boundary: `VWalWriter::init` creates the file before `append_header`, which 
writes magic, version, length, and column IDs separately. After a crash on one 
of those appends, startup scans the residual file; `read_header` only handles 
size 0 and can decode a zero-byte/uninitialized version or length buffer, then 
return a non-terminal error that is retried forever. Please bounds-check the 
complete header before each fixed-width decode and classify a truncated header 
as a discardable incomplete WAL (with prefix-boundary tests).



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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to