bgpd: Fix wrong union member access in bgp_ls_nlri_display() - #21453
Conversation
BGP-LS NLRIs carry different data depending on their type (Node, Link, or Prefix). Internally the data is stored in a C union, where only the member matching the active NLRI type is valid to read. bgp_ls_nlri_display() always reads the protocol_id and identifier fields through the node union member, even when the NLRI is actually a Link or Prefix. Reading the wrong union member is undefined behavior in C; it works by coincidence because the fields happen to sit at the same memory offset in all three variants today, but would silently break if the structs were ever reordered or padded differently. Fix by adding an upfront switch on nlri->nlri_type that reads protocol_id and identifier from whichever union member is actually active, storing them in local variables used for the rest of the function. This matches the pattern already used in the same function for the local_node field. Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
Greptile SummaryThis PR fixes undefined behavior in Key changes:
Confidence Score: 5/5Safe to merge β the change is a correct, well-scoped UB fix with no functional regression risk The fix is minimal, targets only the display function, covers all union/enum cases exhaustively, uses safe defaults for the reserved case, and matches the existing pattern used for No files require special attention Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[bgp_ls_nlri_display called] --> B{nlri == NULL?}
B -- yes --> C[return]
B -- no --> D{switch nlri_type\nExtract protocol_id & identifier}
D -- NODE --> E[read from nlri_data.node]
D -- LINK --> F[read from nlri_data.link]
D -- IPV4/IPV6 PREFIX --> G[read from nlri_data.prefix]
D -- RESERVED --> H[keep defaults\nBGP_LS_PROTO_RESERVED / 0]
E & F & G & H --> I{switch nlri_type\nDetermine nlri_type_str}
I --> J{switch protocol_id\nDetermine protocol_str}
J --> K[vty_out: NLRI Type, Protocol, Identifier]
K --> L{switch nlri_type\nDetermine local_node ptr}
L --> M[Display Local Node Descriptor fields]
M --> N[Display NLRI-type-specific fields]
Reviews (1): Last reviewed commit: "bgpd: Fix wrong union member access in b..." | Re-trigger Greptile |
BGP-LS NLRIs carry different data depending on their type (Node, Link, or Prefix). Internally the data is stored in a C union, where only the member matching the active NLRI type is valid to read.
bgp_ls_nlri_display()always reads theprotocol_idandidentifierfields through the node union member, even when the NLRI is actually a Link or Prefix. Reading the wrong union member is undefined behavior in C; it works by coincidence because the fields happen to sit at the same memory offset in all three variants today, but would silently break if the structs were ever reordered or padded differently.Fix by adding an upfront switch on
nlri->nlri_typethat readsprotocol_idandidentifierfrom whichever union member is actually active, storing them in local variables used for the rest of the function. This matches the pattern already used in the same function for thelocal_nodefield.