Skip to content

Integer overflow in Dcm_Dsp.c DTC response handlers on 16-bit MCUs #67

Description

@vitorallo

Security vulnerability report: AUTOSAR Dcm_Dsp integer overflow in DTC response handlers

Identification

  • Product: autoas/as — open source AUTOSAR Basic Software implementation
  • Repository: https://github.com/autoas/as
  • Component: infras/diagnostic/Dcm/Dcm_Dsp.c, DTC reporting functions
  • Reporter: Vito Rallo, Peach Studio (me@vitorallo.com)
  • Discovery method: Automated security review using foil with securereview-systems-v2 model
  • Date discovered: 2026-05-03

Summary

Three functions in the AUTOSAR Diagnostic Communication Manager
(DCM) compute response buffer sizes using the expression
NumberOfFilteredDTC * 4 + 2 (or * 4 + 1) where
NumberOfFilteredDTC is uint16_t. On 16-bit microcontrollers
(where int is 16 bits), this multiplication overflows when the
DTC count reaches 16384, wrapping the computed size to a small
value. The subsequent bounds check passes with the wrapped value,
and a loop writes NumberOfFilteredDTC * 4 bytes into the response
buffer — a stack or heap buffer overflow.

Severity

  • CVSS v3.1 Base Score: 7.5 (High) on 16-bit MCU targets
  • Vector: AV:A/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
  • Attack Vector: Adjacent (CAN bus / OBD-II port)
  • Attack Complexity: High (requires DTC count >= 16384)

Not affected: 32-bit MCUs (ARM Cortex-M, RH850, AURIX) where
int is 32 bits. C99 integer promotion widens uint16_t to int
before the multiplication, and 65535 * 4 + 2 = 262142 fits in
32-bit int.

Affected: 16-bit MCUs where int is 16 bits:

  • Renesas RL78 (body controllers, seat modules, climate control)
  • NXP/Freescale S12X (instrument clusters, body control modules)
  • Infineon C166 (older ECUs)
  • Microchip PIC24 (sensor modules)

Affected code (3 instances)

Instance 1: Dem_DspReportDTCByStatusMask (line 1186)

uint16_t NumberOfFilteredDTC = 0;
// ...
r = Dem_GetNumberOfFilteredDTC(0, &NumberOfFilteredDTC);
// ...
if ((NumberOfFilteredDTC * 4 + 2) <= msgContext->resMaxDataLen) {
    // Bounds check PASSES with overflowed value
    for (i = 0; (i < NumberOfFilteredDTC) && (E_OK == r); i++) {
        // Loop iterates NumberOfFilteredDTC times
        msgContext->resData[2 + 4 * i] = ...;  // OVERFLOW
        msgContext->resData[3 + 4 * i] = ...;
        msgContext->resData[4 + 4 * i] = ...;
        msgContext->resData[5 + 4 * i] = ...;
    }
}

UDS Service 0x19, SubFunction 0x02 (ReportDTCByStatusMask).

Instance 2: Dem_DspReportDTCSnapshotIdentification (line 1245)

if ((NumberOfFilteredRecords * 4 + 1) <= msgContext->resMaxDataLen) {
    for (i = 0; (i < NumberOfFilteredRecords) && (E_OK == r); i++) {
        msgContext->resData[1 + 4 * i] = ...;  // OVERFLOW

UDS Service 0x19, SubFunction 0x03 (ReportDTCSnapshotIdentification).

Instance 3: Line 1401

Same pattern, different DTC reporting sub-service.

Integer overflow mechanics

On a 16-bit MCU, uint16_t * 4 is computed in 16-bit unsigned
arithmetic. The multiplication wraps at 65536:

NumberOfFilteredDTC n * 4 + 2 (uint16) Passes check? Bytes written
100 402 Depends on resMaxDataLen 400
1000 4002 Depends 4000
16383 65534 No (too big)
16384 2 Yes 65536
16385 6 Yes 65540
32768 2 Yes 131072

When NumberOfFilteredDTC = 16384:

  1. 16384 * 4 + 2 = 65538 wraps to 2 in uint16
  2. Check: 2 <= resMaxDataLenpasses (resMaxDataLen is typically 4095)
  3. Loop iterates 16384 times, writing 16384 * 4 = 65536 bytes
  4. resData buffer is typically 4095 bytes → 61441 bytes overflow

Exploitability analysis

Can NumberOfFilteredDTC reach 16384?

Dem_GetNumberOfFilteredDTC() returns the count of DTCs matching a
status filter from the DTC storage (flash/EEPROM). Typical production
ECUs have 256-4096 DTC entries — too few to trigger the overflow.

However:

  • Development/calibration builds may have larger DTC tables
  • DTC storage corruption (e.g., from voltage glitch or flash
    wear) could cause Dem_GetNumberOfFilteredDTC to return an
    incorrect high value
  • Dem implementation bugs in the count calculation could return
    values > 16384 even with fewer actual entries
  • The autoas/as Dem implementation (infras/diagnostic/Dem/) may
    not cap the returned count

Attack scenario

  1. Attacker connects to OBD-II port (physical access required:
    mechanic, parking valet, rental car, stolen vehicle, charging
    station for EVs)
  2. Attacker sends UDS requests to manipulate DTC storage (if write
    access is available without security authentication)
  3. Attacker sends UDS 0x19/0x02 (ReadDTCByStatusMask) with
    statusMask = 0xFF (match all)
  4. If DTC count >= 16384, the response calculation overflows
  5. The response write loop overwrites the stack past resData
  6. On 16-bit MCU without stack protection: attacker controls the
    return address → code execution on the ECU
  7. Compromised ECU sends arbitrary CAN messages to other ECUs on
    the bus (braking, steering, engine, transmission)

Why this is still reportable despite limited triggering

  1. The code pattern is wrong regardless of triggering. The
    multiplication can overflow and the bounds check is defeated.
    MISRA-C Rule 12.11 requires checking for overflow before
    arithmetic operations. This is a MISRA violation.

  2. The same pattern likely exists in commercial AUTOSAR stacks.
    The AUTOSAR specification defines the DTC response format, and
    many implementations follow the same nDTC * 4 + header size
    calculation. If a commercial stack (Vector, ETAS, EB) uses the
    same code pattern on 16-bit MCUs, the impact is much larger.

  3. Defense in depth. Even if the DTC count can't reach 16384
    today, a future configuration change, Dem bug, or storage
    corruption could expose the overflow. The fix is simple and
    eliminates the risk.

Suggested fix

Add overflow check before the bounds comparison:

uint32_t responseSize = (uint32_t)NumberOfFilteredDTC * 4u + 2u;
if (responseSize <= msgContext->resMaxDataLen) {
    // ... safe to proceed
}

Casting to uint32_t before the multiplication ensures the
arithmetic is done in 32 bits regardless of MCU word size.

Alternatively, cap NumberOfFilteredDTC to a safe maximum:

#define DCM_MAX_REPORTABLE_DTCS  ((resMaxDataLen - 2) / 4)
if (NumberOfFilteredDTC > DCM_MAX_REPORTABLE_DTCS) {
    *nrc = DCM_E_RESPONSE_TOO_LONG;
    return E_NOT_OK;
}

Proof of concept

A traditional PoC is not feasible because:

  • AUTOSAR runs on bare-metal MCUs, not under Linux/QEMU
  • The overflow requires a 16-bit MCU target (RL78, S12X)
  • NumberOfFilteredDTC must reach 16384 (requires DTC storage
    manipulation or Dem bug)

Static analysis confirmation: The vulnerability is confirmed by
source code analysis. The uint16_t type of NumberOfFilteredDTC
and the 16-bit multiplication overflow are verifiable from the
source without runtime testing.

MISRA-C compliance check: The code violates MISRA-C:2012
Rule 12.11 (evaluation of constant unsigned integer expressions
should not lead to wrap-around). Any MISRA-compliant static
analysis tool (Polyspace, LDRA, Parasoft) would flag this pattern.

Credit

Discovered by Vito Rallo (Peach Studio) using foil, an AI-powered
security code scanner, with the securereview-systems-v2 model
trained on C/C++ vulnerability patterns which I am not yet making
available to the community (foil.peachstudio.be). I am assessing the
potential and impact of such model public available.
If you need to get access in preliminary, controlled group, let me know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions