Skip to content

fix(agent): prevent shift-left overflow in EpcNetIpKey::clone_by_masklen#11679

Open
mail2sudheerobbu-oss wants to merge 3 commits intodeepflowio:mainfrom
mail2sudheerobbu-oss:fix/labeler-shift-overflow-ipv6
Open

fix(agent): prevent shift-left overflow in EpcNetIpKey::clone_by_masklen#11679
mail2sudheerobbu-oss wants to merge 3 commits intodeepflowio:mainfrom
mail2sudheerobbu-oss:fix/labeler-shift-overflow-ipv6

Conversation

@mail2sudheerobbu-oss
Copy link
Copy Markdown
Contributor

Summary

Fixes #8700

Root Cause

When a CIDR with prefix length 0 (e.g. ::/0) is registered and an IPv6 lookup is performed, clone_by_masklen(0, false) computes:

u128::MAX << IPV6_BITS.saturating_sub(0)
= u128::MAX << 128

Shifting a u128 by its own bit-width (128) is undefined behaviour in Rust and panics in debug builds with:

panicked at src/policy/labeler.rs:72:27:
attempt to shift left with overflow

Fix

Replace the bare shift with checked_shl, which returns None when the shift amount equals or exceeds the bit-width, and falls back to 0. A mask of 0 is semantically correct for a /0 prefix (no network bits to preserve).

Before:

ip: self.ip & (u128::MAX << max_prefix.saturating_sub(masklen)),

After:

ip: self.ip & u128::MAX.checked_shl(max_prefix.saturating_sub(masklen) as u32).unwrap_or(0),

Testing

A regression test test_ipv6_zero_masklen_no_panic is added that registers a ::/0 CIDR and performs a lookup — previously this panicked in debug builds, now it succeeds and returns the expected EPC ID.

Fixes deepflowio#8700

When a CIDR with prefix length 0 (e.g. ::/0) is registered and an
IPv6 lookup is performed, clone_by_masklen(0, false) computes:

    u128::MAX << IPV6_BITS.saturating_sub(0)
  = u128::MAX << 128

Shifting a u128 by its own bit-width (128) is undefined behaviour and
panics in Rust debug builds with:

    panicked at src/policy/labeler.rs:72:27:
    attempt to shift left with overflow

The fix replaces the bare shift with checked_shl, which returns None
when the shift amount equals or exceeds the bit-width, and falls back
to 0.  A mask of 0 is semantically correct for a /0 prefix (no network
bits to preserve).

    Before: self.ip & (u128::MAX << max_prefix.saturating_sub(masklen))
    After:  self.ip & u128::MAX
                        .checked_shl(max_prefix.saturating_sub(masklen) as u32)
                        .unwrap_or(0)

A regression test test_ipv6_zero_masklen_no_panic is added to cover
the ::/0 case end-to-end through the labeler API.

Signed-off-by: Sudheer Obbu <mail2sudheerobbu@gmail.com>
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 29, 2026

CLA assistant check
All committers have signed the CLA.

@mail2sudheerobbu-oss
Copy link
Copy Markdown
Contributor Author

Hi deepflow team — gentle ping on this PR! It fixes a potential shift-left overflow in EpcNetIpKey::clone_by_masklen where a masklen value ≥ 32 would cause undefined behaviour in Rust debug builds (fixes #8700). The fix adds a bounds check before the shift. CLA is signed. Would appreciate a review when you get a chance. Thanks!

@mail2sudheerobbu-oss
Copy link
Copy Markdown
Contributor Author

Hi team — gentle ping on this PR. It replaces a bare << shift in EpcNetIpKey::clone_by_masklen with checked_shl to prevent a Rust panic on shift-count ≥ 32 (closes #8700). The fix is minimal and includes a unit test covering the overflow case. Branch is synced with main. Would appreciate a review when you get a chance! 🙏

@mail2sudheerobbu-oss
Copy link
Copy Markdown
Contributor Author

Hi team — gentle ping on this PR! It adds a one-line guard to prevent a shift-left overflow panic in EpcNetIpKey::clone_by_masklen when masklen is 0, closing #8700. Happy to adjust if there are any style preferences or if a test is needed. Thanks! 🙏

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.

[BUG] panicked at src/policy/labeler.rs:72:27:\nattempt to shift left with overflow

2 participants