Skip to content

isisd: consume leftover bytes after FAD sub-sub-TLV loop - #21544

Merged
donaldsharp merged 1 commit into
FRRouting:masterfrom
TristanInSec:fix/isis-fad-leftover-bytes
Apr 17, 2026
Merged

isisd: consume leftover bytes after FAD sub-sub-TLV loop#21544
donaldsharp merged 1 commit into
FRRouting:masterfrom
TristanInSec:fix/isis-fad-leftover-bytes

Conversation

@TristanInSec

Copy link
Copy Markdown

The Flex-Algorithm sub-sub-TLV loop condition is while (subsubtlvs_len > 2), so when 1 or 2 bytes remain after the last iteration, they are not consumed. The stream position then falls behind the declared subtlv length, desynchronizing subsequent subtlv parsing in the outer loop.

Skip any leftover bytes after the while loop exits.

Signed-off-by: Tristan Madani tristan@live.fr

@greptile-apps

greptile-apps Bot commented Apr 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a post-loop stream_forward_getp to consume 1–2 leftover bytes that the while (subsubtlvs_len > 2) condition cannot drain, fixing a stream-position desync in the FAD sub-sub-TLV parser. The fix is correct for the normal loop-exit path but introduces a double-advance bug on the error-break path.

  • When the inner length-validation check (line 5168) fires, the error handler already consumes all remaining bytes via stream_forward_getp(s, subsubtlvs_len - 2) and then breaks β€” but subsubtlvs_len is never decremented before the break, so the new if (subsubtlvs_len > 0) guard is true and a second stream_forward_getp(s, subsubtlvs_len) advances the stream far past the sub-TLV boundary. Changing the guard to subsubtlvs_len > 0 && subsubtlvs_len <= 2 limits the skip to the intended normal-exit case.

Confidence Score: 3/5

Not safe to merge as-is: the fix introduces a double-advance on the existing error-break path that can desync stream parsing.

The intended fix (draining 1–2 leftover bytes) is correct, but the guard condition subsubtlvs_len > 0 also fires when the loop exits via break after the invalid-length error handler, causing a second skip of up to subsubtlvs_len bytes and worsening the very desync it aims to prevent.

isisd/isis_tlvs.c β€” specifically the post-loop skip guard and its interaction with the error-break at line 5173.

Important Files Changed

Filename Overview
isisd/isis_tlvs.c Adds a post-loop skip for leftover sub-sub-TLV bytes, but the guard condition > 0 also triggers on the error-break path where bytes were already consumed, causing a double-advance.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["subsubtlvs_len = length - 4"] --> B{"subsubtlvs_len > 2?"}
    B -- Yes --> C["read type + len (2 bytes)"]
    C --> D{"subsubtlv_len >\nsubsubtlvs_len - 2?"}
    D -- Yes --> E["stream_forward_getp(s, subsubtlvs_len - 2)\nlog error"]
    E --> F["break\n(subsubtlvs_len unchanged, still > 2)"]
    D -- No --> G["process sub-sub-TLV\nstream_forward_getp for payload"]
    G --> H["subsubtlvs_len -= 2 + subsubtlv_len"]
    H --> B
    B -- No --> I{"subsubtlvs_len > 0?"}
    F --> I
    I -- "No (== 0)" --> K["done βœ“"]
    I -- "Yes (1 or 2)\nnormal exit" --> J["stream_forward_getp(s, subsubtlvs_len) βœ“"]
    I -- "Yes (> 2)\nerror-break path - BUG" --> L["stream_forward_getp(s, subsubtlvs_len)\ndouble-advance! βœ—"]
    J --> K
    L --> M["stream desync - worse than original bug"]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: isisd/isis_tlvs.c
Line: 5251-5252

Comment:
**Double-advance on error-break path**

When the inner validation check at line 5168 fires (`subsubtlv_len > subsubtlvs_len - 2`), the error handler reads 2 bytes (type + length) and then calls `stream_forward_getp(s, subsubtlvs_len - 2)`, consuming all remaining bytes of this sub-TLV. It then `break`s out of the while loop with `subsubtlvs_len` still holding its pre-break value (always > 2). The new guard `subsubtlvs_len > 0` is true, so `stream_forward_getp(s, subsubtlvs_len)` is called a second time, advancing the stream far past the sub-TLV boundary and causing exactly the kind of desync the fix intends to cure.

The skip should only apply when the loop exited normally (i.e. `subsubtlvs_len` drained to ≀ 2), not when it `break`ed early:

```suggestion
			if (subsubtlvs_len > 0 && subsubtlvs_len <= 2)
				stream_forward_getp(s, subsubtlvs_len);
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "isisd: consume leftover bytes after FAD ..." | Re-trigger Greptile

Comment thread isisd/isis_tlvs.c Outdated
Comment on lines +5251 to +5252
if (subsubtlvs_len > 0)
stream_forward_getp(s, subsubtlvs_len);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Double-advance on error-break path

When the inner validation check at line 5168 fires (subsubtlv_len > subsubtlvs_len - 2), the error handler reads 2 bytes (type + length) and then calls stream_forward_getp(s, subsubtlvs_len - 2), consuming all remaining bytes of this sub-TLV. It then breaks out of the while loop with subsubtlvs_len still holding its pre-break value (always > 2). The new guard subsubtlvs_len > 0 is true, so stream_forward_getp(s, subsubtlvs_len) is called a second time, advancing the stream far past the sub-TLV boundary and causing exactly the kind of desync the fix intends to cure.

The skip should only apply when the loop exited normally (i.e. subsubtlvs_len drained to ≀ 2), not when it breaked early:

Suggested change
if (subsubtlvs_len > 0)
stream_forward_getp(s, subsubtlvs_len);
if (subsubtlvs_len > 0 && subsubtlvs_len <= 2)
stream_forward_getp(s, subsubtlvs_len);
Prompt To Fix With AI
This is a comment left during a code review.
Path: isisd/isis_tlvs.c
Line: 5251-5252

Comment:
**Double-advance on error-break path**

When the inner validation check at line 5168 fires (`subsubtlv_len > subsubtlvs_len - 2`), the error handler reads 2 bytes (type + length) and then calls `stream_forward_getp(s, subsubtlvs_len - 2)`, consuming all remaining bytes of this sub-TLV. It then `break`s out of the while loop with `subsubtlvs_len` still holding its pre-break value (always > 2). The new guard `subsubtlvs_len > 0` is true, so `stream_forward_getp(s, subsubtlvs_len)` is called a second time, advancing the stream far past the sub-TLV boundary and causing exactly the kind of desync the fix intends to cure.

The skip should only apply when the loop exited normally (i.e. `subsubtlvs_len` drained to ≀ 2), not when it `break`ed early:

```suggestion
			if (subsubtlvs_len > 0 && subsubtlvs_len <= 2)
				stream_forward_getp(s, subsubtlvs_len);
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment looks valid to me

@TristanInSec

Copy link
Copy Markdown
Author

Valid finding. Fixed the guard to only fire on normal loop exit (1-2 leftover bytes), not on the error-break path where bytes were already consumed.

@mjstapp

mjstapp commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

same commit issue here - please squash into the first, properly-formatted commit

When the FAD sub-sub-TLV loop exits normally with 1-2 bytes remaining
(too small for another header), the stream position falls out of sync
with the declared subtlv length. Add a post-loop forward to consume
the leftover bytes on normal exit only, not on the error-break path
where the bytes were already consumed.

Signed-off-by: Tristan Madani <tristan@live.fr>
@TristanInSec
TristanInSec force-pushed the fix/isis-fad-leftover-bytes branch from 6dd381c to fbb31ae Compare April 16, 2026 16:32
@mjstapp

mjstapp commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

CI:rerun

@donaldsharp

Copy link
Copy Markdown
Member

@Mergifyio backport stable/10.6 stable/10.5 stable/10.4 stable/10.3 stable/10.2 stable/10.1 stable/10.0

@donaldsharp
donaldsharp merged commit b821a78 into FRRouting:master Apr 17, 2026
45 of 50 checks passed
@mergify

mergify Bot commented Apr 17, 2026

Copy link
Copy Markdown

backport stable/10.6 stable/10.5 stable/10.4 stable/10.3 stable/10.2 stable/10.1 stable/10.0

βœ… Backports have been created

Details

donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
donaldsharp added a commit that referenced this pull request Apr 18, 2026
isisd: consume leftover bytes after FAD sub-sub-TLV loop (backport #21544)
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.

3 participants