Skip to content

bgpd: Fix integer truncation of SRLG count when parsing SRLG TLV - #21077

Merged
Jafaral merged 1 commit into
FRRouting:masterfrom
cscarpitta:fix_bgp_ls_integer_truncation_srlg_tlv
Mar 11, 2026
Merged

bgpd: Fix integer truncation of SRLG count when parsing SRLG TLV#21077
Jafaral merged 1 commit into
FRRouting:masterfrom
cscarpitta:fix_bgp_ls_integer_truncation_srlg_tlv

Conversation

@cscarpitta

Copy link
Copy Markdown
Contributor

count is declared as uint8_t but receives length / 4 where length is a uint16_t. For length >= 1024, the division result exceeds 255, which cannot be stored in count since uint8_t holds at most 255, and the value silently truncates. The result is then stored in attr->srlg_count, also uint8_t, which would re-truncate it.

Fix the issue by widening count in parse_srlg() and srlg_count in struct bgp_ls_attr to uint16_t.

`count` is declared as `uint8_t` but receives `length / 4` where
`length` is a `uint16_t`.  For `length >= 1024`, the division result
exceeds 255, which cannot be stored in `count` since `uint8_t` holds
at most 255, and the value silently truncates.  The result is then
stored in `attr->srlg_count`, also `uint8_t`, which would re-truncate
it.

Widen `count` in `parse_srlg()` and `srlg_count` in `struct
bgp_ls_attr` to `uint16_t`.

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
@greptile-apps

greptile-apps Bot commented Mar 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a silent integer truncation bug in parse_srlg() (bgpd/bgp_ls_nlri.c) and struct bgp_ls_attr (bgpd/bgp_ls_nlri.h) by widening count and srlg_count from uint8_t to uint16_t. Because length is a uint16_t, the expression length / 4 can yield values up to 16383 β€” well beyond the 255 maximum of uint8_t β€” causing the result to silently wrap before the BGP_LS_MAX_SRLG guard check can fire.

  • Root cause: With count as uint8_t, any length that is a multiple of 1024 (e.g. 1024, 2048…) produces a length / 4 result that wraps to 0, bypassing the > BGP_LS_MAX_SRLG check entirely and silently discarding all SRLGs in the TLV.
  • Fix: Widening both count (local variable) and srlg_count (struct field) to uint16_t ensures the division result is held without loss before the bounds check, and the correct count propagates to callers.
  • Downstream consumers (bgp_ls_ted.c, comparison, copy, encoding paths in bgp_ls_nlri.c) are all consistent with the wider type β€” loops use int, arithmetic stays within uint16_t bounds given the BGP_LS_MAX_SRLG = 64 cap, and the implicit widening from uint8_t in bgp_ls_ted.c:128 is safe.
  • The change is minimal and correctly scoped; no serialization or ABI concerns exist because bgp_ls_attr is an internal, always-recompiled structure.

Confidence Score: 5/5

  • This PR is safe to merge β€” it is a minimal, well-scoped bug fix with no regressions to downstream consumers.
  • The two-line change is surgical and correct: widening uint8_t to uint16_t in exactly the two places where truncation could occur. All other usages of srlg_count throughout the codebase (comparison, copy, encoding, TED path) handle the wider type without issue. The existing BGP_LS_MAX_SRLG = 64 guard continues to bound the maximum value, so overflow of derived expressions (e.g. srlg_count * 4 into uint16_t) is impossible in practice.
  • No files require special attention.

Important Files Changed

Filename Overview
bgpd/bgp_ls_nlri.c Widens the local count variable in parse_srlg() from uint8_t to uint16_t, preventing silent integer wrap-around when length / 4 exceeds 255; all downstream usages of srlg_count are consistent with the wider type.
bgpd/bgp_ls_nlri.h Widens srlg_count in struct bgp_ls_attr from uint8_t to uint16_t to match the corrected parsing logic; no other struct fields are affected and all consumers compile cleanly with the widened type.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Receive SRLG TLV\n(length: uint16_t)"] --> B{"length % 4 != 0?"}
    B -- Yes --> C["flog_warn + return -1"]
    B -- No --> D["count = length / 4\n(uint16_t β€” fixed from uint8_t)"]
    D --> E{"count > BGP_LS_MAX_SRLG\n(64)?"}
    E -- Yes --> F["flog_warn + return -1"]
    E -- No --> G["XMALLOC count Γ— 4 bytes"]
    G --> H["Loop: read count uint32_t SRLGs\nfrom stream"]
    H --> I["attr->srlg_count = count\n(uint16_t β€” fixed from uint8_t)"]
    I --> J["Set BGP_LS_ATTR_SRLG_BIT\nreturn 0"]

    style D fill:#d4edda,stroke:#28a745
    style I fill:#d4edda,stroke:#28a745
    style C fill:#f8d7da,stroke:#dc3545
    style F fill:#f8d7da,stroke:#dc3545
Loading

Last reviewed commit: ef8a4c6

@Jafaral
Jafaral merged commit 6956874 into FRRouting:master Mar 11, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants