Skip to content

Conversation

@zhexuany
Copy link
Contributor

@zhexuany zhexuany commented Feb 1, 2026

Summary

Fixes #26 - BAG decoder was failing to handle kuavo_msgs/sensorsData messages with error:

Array length 656114711 exceeds maximum allowed 10000000

Root Cause

The BAG parser's read_record function extracts just the CDR-encoded message data from BAG records, without any wrapper headers. However, decode_ros1 was designed to expect a 16-byte header (12-byte ROS record header + 4-byte CDR header) and skips those bytes.

When decode_ros1 skips 16 bytes of actual message data, it causes misalignment during decoding. This leads to corrupted values being read as array lengths (e.g., 656114711 instead of a valid array size).

Fix

Changed BagDecodedMessageStream::next() to use decode_headerless() instead of decode_ros1(). The decode_headerless() method processes the message data from byte 0 without skipping any header bytes, which is correct for the data format returned by the BAG parser.

Test Plan

  • All existing tests pass (cargo test)
  • Format and lint checks pass (make check)
  • Verified against problematic BAG file that previously failed

The BAG parser's `read_record` function extracts just the CDR-encoded
message data from BAG records, without any wrapper headers. However,
`decode_ros1` was designed to expect a 16-byte header (12-byte ROS
record header + 4-byte CDR header) and skips those bytes.

When `decode_ros1` skips 16 bytes of actual message data, it causes
misalignment during decoding. This leads to corrupted values being read
as array lengths, triggering errors like "Array length 656114711 exceeds
maximum allowed 10000000".

The fix is to use `decode_headerless` instead, which processes the
message data from byte 0 without skipping any header bytes.

Fixes #26
@codecov
Copy link

codecov bot commented Feb 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps
Copy link

greptile-apps bot commented Feb 1, 2026

Greptile Overview

Greptile Summary

Fixed BAG message decoding by switching from decode_ros1() to decode_headerless() in BagDecodedMessageStream::next().

Root Cause Analysis

The BAG parser's read_record() function (in src/io/formats/bag/parser.rs:251) extracts the pure CDR-encoded message data from BAG records. This data does not include any wrapper headers - it's just the raw message bytes stored in the BAG file's data section.

However, decode_ros1() was designed for a different use case: it expects data with a 16-byte prefix (12-byte ROS record header + 4-byte CDR header) and explicitly skips those bytes before decoding (see src/encoding/cdr/decoder.rs:128). When applied to headerless BAG data, this caused the decoder to skip 16 bytes of actual message content, leading to:

  • Misaligned field reads
  • Corrupted values interpreted as array lengths
  • The specific error: "Array length 656114711 exceeds maximum allowed 10000000"

The Fix

Replaced decode_ros1() with decode_headerless(), which correctly processes CDR data starting at byte 0 without skipping any header bytes. This matches the actual format of data returned by the BAG parser.

Testing

Confidence Score: 5/5

  • This PR is safe to merge - it fixes a critical bug with a minimal, well-justified change
  • The fix is correct, well-documented, and addresses the root cause. The change is minimal (1 method call replaced), the implementation matches the actual data format, existing tests pass, and the fix was verified against the problematic file.
  • No files require special attention

Important Files Changed

Filename Overview
src/io/formats/bag/parallel.rs Changed decode_ros1 to decode_headerless to correctly handle BAG message data that lacks wrapper headers

Sequence Diagram

sequenceDiagram
    participant Client
    participant BagDecodedMessageStream
    participant BagParser
    participant CdrDecoder
    participant CdrCursor

    Client->>BagDecodedMessageStream: next()
    BagDecodedMessageStream->>BagParser: read_record()
    Note over BagParser: Extracts BAG record structure<br/>header + raw CDR data
    BagParser-->>BagDecodedMessageStream: (header, raw_data)
    Note over BagDecodedMessageStream: raw_data contains pure CDR bytes<br/>without ROS or CDR headers
    BagDecodedMessageStream->>CdrDecoder: decode_headerless(schema, raw_data)
    Note over CdrDecoder: Changed from decode_ros1()<br/>which incorrectly skipped 16 bytes
    CdrDecoder->>CdrCursor: new_headerless(data, little_endian)
    Note over CdrCursor: Starts at byte 0<br/>No header skip
    CdrDecoder->>CdrCursor: Read message fields
    CdrCursor-->>CdrDecoder: Decoded values
    CdrDecoder-->>BagDecodedMessageStream: DecodedMessage
    BagDecodedMessageStream-->>Client: Ok((message, channel_info))
Loading

@zhexuany zhexuany merged commit f026560 into main Feb 1, 2026
30 checks passed
@zhexuany zhexuany deleted the fix/issue-26-bag-decode-headerless branch February 1, 2026 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bag decoder fails to handle corrupted messages with invalid array lengths

1 participant