#34150·ardupilot

Spec mismatch in NovAtel parser

Author: Arslan8Created Aug 22, 2026Updated Sep 12, 2026

Bug Report

Issue details

The NovAtel binary GPS parser applies its payload-buffer limit to the total number of bytes read, including the message header, even though the destination buffer contains only payload data.

The payload buffer has a capacity of 256 bytes:

cpp
union PACKED msgbuffer {
    bestvel bestvelu;
    bestpos bestposu;
    psrdop psrdopu;
    uint8_t bytes[256];
};

During the DATA state, the parser performs the following check:

cpp
if (nova_msg.read >= sizeof(nova_msg.data)) {
    Debug("parse data overflow length=%u msglength=%u\n",
          (unsigned)nova_msg.read,
          nova_msg.header.nova_headeru.messagelength);
    nova_msg.nova_state = nova_msg_parser::PREAMBLE1;
    break;
}

nova_msg.data.bytes[
    nova_msg.read -
    nova_msg.header.nova_headeru.headerlength] = temp;

nova_msg.read counts both header and payload bytes. With the normal 28-byte NovAtel binary header, the check therefore limits the effective payload capacity to:

256 - 28 = 228 bytes

A 228-byte payload is accepted. When the parser receives byte 229 of a longer payload, nova_msg.read is already 256, so it resets before copying the byte. The message never reaches CRC validation or process_message().

This does not appear likely to affect ArduPilot’s normal NovAtel configuration. The driver executes unlogall and requests only:

BESTPOSB
BESTVELB
PSRDOPB

BESTPOSB has a 72-byte payload and BESTVELB has a 44-byte payload, so neither approaches the defective boundary.

PSRDOPB has a variable payload length:

28 + (4 × number of PRNs)

It would exceed 228 bytes only when listing at least 51 PRNs. We have not demonstrated that a currently supported NovAtel, Tersus, or ComNav receiver emits such a PSRDOPB message during ordinary ArduPilot operation.

Nevertheless, this is a specification and implementation mismatch. The NovAtel protocol supports valid messages larger than 228 bytes. For example, a binary RANGE payload contains four initial bytes followed by 44 bytes per observation, so a valid message with six observations already has a 268-byte payload. ArduPilot does not normally request or process RANGE, but it demonstrates that 228 bytes is not a protocol-wide payload limit.

Accordingly, this report is not claiming a currently observed operational failure or security vulnerability. It identifies a defensive parser bug that unnecessarily reduces the declared payload-buffer capacity from 256 bytes to 228 bytes. It could become visible if a future supported message is larger, if PSRDOPB contains enough PRNs, or if the receiver is configured independently to emit additional binary logs.

The boundary check should use the payload offset:

cpp
const uint16_t payload_offset =
    nova_msg.read -
    nova_msg.header.nova_headeru.headerlength;

if (payload_offset >= sizeof(nova_msg.data.bytes)) {
    Debug("parse data overflow offset=%u msglength=%u\n",
          (unsigned)payload_offset,
          nova_msg.header.nova_headeru.messagelength);
    nova_msg.nova_state = nova_msg_parser::PREAMBLE1;
    break;
}

nova_msg.data.bytes[payload_offset] = temp;

The parser could also reject messagelength > sizeof(nova_msg.data.bytes) immediately after reading the header.

Version

ArduPilot revision 4fe7ad4fab8c1bf4ade7cbc7ae85a73c81d73e05.

The same comparison is also present on the current master branch as of August 22, 2026.

Platform

  • All
  • AntennaTracker
  • Copter
  • Plane
  • Rover
  • Submarine

The code is part of the shared GPS backend and is not specific to a vehicle type.

Airframe type

Not airframe-specific.

Hardware type

Any autopilot using the AP_GPS_NOVA backend with a NovAtel-compatible GPS receiver. No currently affected hardware configuration has been demonstrated.

Logs

No flight logs are available. This report concerns a code-level parser/specification mismatch and is not based on an observed flight failure.