Skip to content

Conversation

@jalil-salame
Copy link
Contributor

There was a bug in the impl EncodeGaugeValue for u64 implementation due to the as i64 cast.

The implementation only checked if self == u64::MAX, this is wrong since u64::MAX is not the only value that cannot be represented by an i64.

The range of values is actually self > i64::MAX. u64::MAX == 2^64 - 1 whereas i64::MAX == 2^63 - 1, this means there are 2^63 u64 values that are not representable by an i64, not just i64::MAX. Delegating the checks to i64::try_from(self) ensures the logic is right. For this reason I also switched the rest of the implementations to use N::from instead of as N since the N::from function is only implemented for types whose conversion is infallible, this guarantees no such issues will ever happen.

The only as cast left is u64 as f64 in EncodeExemplarValue, this is not possible to remove since there is no impl TryFrom<u64> for f64.

@jalil-salame jalil-salame force-pushed the fix-u64-as-i64-bug branch 2 times, most recently from 92911cf to 5d7b90b Compare August 30, 2025 21:19
@jalil-salame
Copy link
Contributor Author

Also created jalil-salame#1 as a follow up (adding EncodeGaugeValue and EncodeCounterValue impls for usize and isize).

Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

Thanks for the fix! Good work.

Mind adding a changelog entry in CHANGELOG.md? If it doesn't exist yet, you can add [0.24.1] section.

There was a bug in the `impl EncodeGaugeValue for u64` implementation
due to the `as i64` cast.

The implementation only checked if `self == u64::MAX`, this is wrong
since `u64::MAX` is not the only value that cannot be represented by an
`i64`.

The range of values is actually `self > i64::MAX`. `u64::MAX == 2^64 -
1` whereas `i64::MAX == 2^63 - 1`, this means there are `2^63` `u64`
values that are not representable by an `i64`, not just `i64::MAX`.
Delegating the checks to `i64::try_from(self)` ensures the logic is
right. For this reason I also switched the rest of the implementations
to use `N::from` instead of `as N` since the `N::from` function is only
implemented for types whose conversion is infallible, this guarantees no
such issues will ever happen.

The only `as` cast left is `u64 as f64` in `EncodeExemplarValue`, this
is not possible to remove since there is no `impl TryFrom<u64> for f64`.

Signed-off-by: Jalil David Salamé Messina <jalil.salame@gmail.com>
@jalil-salame
Copy link
Contributor Author

Thanks for the fix! Good work.

Mind adding a changelog entry in CHANGELOG.md? If it doesn't exist yet, you can add [0.24.1] section.

Done!

@jalil-salame jalil-salame requested a review from mxinden September 2, 2025 11:33
@mxinden mxinden changed the title refactor(encoding): remove as many as casts as possible refactor(encoding): remove as as casts Sep 2, 2025
@mxinden mxinden changed the title refactor(encoding): remove as as casts refactor(encoding): remove as casts Sep 2, 2025
@mxinden mxinden merged commit 6bb0b10 into prometheus:master Sep 2, 2025
10 checks passed
@jalil-salame jalil-salame deleted the fix-u64-as-i64-bug branch September 2, 2025 13:15
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.

2 participants