Skip to content

qdlt: fix correctness and safety bugs in argument and segmented-msg p…#804

Open
SoundMatt wants to merge 1 commit into
COVESA:masterfrom
SoundMatt:fix/qdlt-argument-double-and-segmented-overflow
Open

qdlt: fix correctness and safety bugs in argument and segmented-msg p…#804
SoundMatt wants to merge 1 commit into
COVESA:masterfrom
SoundMatt:fix/qdlt-argument-double-and-segmented-overflow

Conversation

@SoundMatt

Copy link
Copy Markdown

Problem

Two unrelated but small bugs in qdlt/, both real and reachable:

1. QDltArgument::setValuetoInt() instead of toDouble()

qdlt/qdltargument.cpp:699–705:

case QVariant::Double:
    {
    double bvalue = value.toInt();          // ← bug
    data = QByteArray((const char*)&bvalue, sizeof(double));
    typeInfo = QDltArgument::DltTypeInfoFloa;
    return true;
    }

When a QVariant::Double is passed to setValue(), the code reads
its integer value and stores that as a double. Effects:

  • setValue(QVariant(3.14)) → stores 3.0 (fractional part lost).
  • setValue(QVariant(NaN)) → stores 0.0 (toInt() returns 0).
  • setValue(QVariant(1.5e15)) → silently clamped to int range.

Anywhere DLT messages are constructed programmatically with floating-
point arguments via this overload, the wire output is wrong.

Fix: value.toInt()value.toDouble(). One-character change.

2. QDltSegmentedMsg::addsequence * chunkSize overflow

qdlt/qdltsegmentedmsg.cpp:141–154:

uint32_t sequence = argument.getValue().toUInt();
if(sequence>=chunks) {
    error = ...;
    return -1;
}
...
payload.replace(sequence*chunkSize, chunkSize, argument.getData());

Both sequence (chunk segment) and chunkSize (start segment) come
from the wire. The check sequence < chunks only validates the
chunk index; the multiplication sequence * chunkSize is performed
in uint32_t and can wrap. With a crafted start segment declaring a
large chunkSize and a chunk-segment message with a small but
non-zero sequence, the product wraps to a value smaller than
payload.size(), so payload.replace() succeeds but writes the
chunk into the wrong region of the buffer.

Fix: compute the offset in quint64 so the multiplication can't
wrap, then reject any chunk whose end (chunk_offset + chunkSize)
would extend past the resized payload size before calling
replace().

Verification

  • Read both functions in full; existing checks before each fix do
    not cover the cases above.
  • payload is resized to the start-segment-declared size at
    line 112, which the new bound-check uses as the upper limit.
  • Cast back to int for the replace() call is safe after the
    bound check has guaranteed the offset fits.

Notes

  • No new tests added; happy to add qdlt/tests/-style coverage if
    maintainers point me at the right harness shape.
  • Defensive bounds-checks on mid() calls in qdltargument.cpp:174,178
    and qdltimporter.cpp:942 are real but milder (Qt's mid()
    truncates gracefully rather than reading OOB), and I'll send
    those as a separate PR rather than bundle here.

…arsing

Two unrelated bugs in qdlt/, both real and reachable, both small fixes:

1. qdlt/qdltargument.cpp:701 — QDltArgument::setValue, QVariant::Double
   branch: `double bvalue = value.toInt();` instead of `value.toDouble()`.
   Fractional part is silently truncated; large floats are clamped to
   integer range. Single-character correctness fix.

2. qdlt/qdltsegmentedmsg.cpp:154 — QDltSegmentedMsg::add: the chunk
   offset is computed as `sequence * chunkSize` in uint32_t. Both
   `sequence` and `chunkSize` come from the wire (start-segment and
   chunk-segment messages respectively); a crafted pair where
   `sequence < chunks` is satisfied but the product wraps gives
   payload.replace() a small offset and corrupts the wrong region of
   the resized payload buffer.

   Compute the offset in quint64 to avoid the wrap, and reject any
   chunk whose end (chunk_offset + chunkSize) would extend past the
   resized payload size. Cast back to int for the replace() call after
   the bound check has guaranteed it fits.

No behaviour change for well-formed messages.

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
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.

1 participant