Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent integer overflows in bionic power #34684

Merged
merged 1 commit into from
Oct 13, 2019

Conversation

anothersimulacrum
Copy link
Member

@anothersimulacrum anothersimulacrum commented Oct 12, 2019

Summary

SUMMARY: Bugfixes "Fix integer overflows when bionic power is modified and when a value is converted to units::energy"

Purpose of change

Resolves #34665
The value by which power is modified in Character::mod_power_level could overflow when the new power was large enough that when it was added to the player's power_level the value it produced was larger than the value an int could store.
An overflow could also happen in units::from_(kilo)joule when the value provided, when converted to millijoules, was larger than it's type could store.

Describe the solution

Add checks to prevent overflow in all the functions mentioned.

Describe alternatives you've considered

Add a check in units::from_millijoule to prevent overflow, but I couldn't think of a good way to do that without loosing precision.

Testing

Save that I used for testing provided.
overflow.tar.gz
To test for the overflow in Character::mod_power_level, eat the battery with ~650 charges (the character has 1980kJ of power, and their max capacity is the max power). The power will overflow and be clamped to 0kJ.
To test for overflow in units::from_kilojoule, consume one of the batteries with 2500 charges, because this is more than can be stored in an int as a millijoule.

Prevent an integer overflow that can occur if the new power added in
Character::mod_power is greater than the max power level.
This would cause power to be clamped to 0, because the integer overflow
would make the power to be added massively negative, when it should be
positive.
Also prevent an integer overflow that occurs when units::from_joule and
units::from_kilojoule are given a value that, when converted to
millijoules, is larger than it's type can store.
This was another cause of problems in bionic power, because the new
power could overflow, and then not be the correct value. This occurred
in testing when trying to use the battery charger system with a heavy
disposable battery.
@KorGgenT KorGgenT added <Bugfix> This is a fix for a bug (or closes open issue) Bionics CBM (Compact Bionic Modules) labels Oct 12, 2019
@ZhilkinSerg ZhilkinSerg merged commit 0b1ff1d into CleverRaven:master Oct 13, 2019
@anothersimulacrum anothersimulacrum deleted the fix-overflow branch October 13, 2019 14:27
int new_power = units::to_millijoule( power_level ) + units::to_millijoule( npower );
// An integer overflow has occurred - the sum of two positive things (power_level is always positive)
// cannot be negative, so if it is, we know integer overflow has occured
if( npower >= 0_mJ && new_power < 0 ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test is relying on signed integer overflow, which is undefined behaviour, so it could potentially break depending on compiler optimization. Easiest solution is to do the computation in int64_ts instead, then clamp and cast back to int. Or you can do the more roundabout approach of subtracting npower from max_power_level and comparing with power_level (but then you start risking underflow if you're not careful, so it's hard to do correctly).

Copy link
Member Author

Choose a reason for hiding this comment

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

Whoops, thanks #36686!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bionics CBM (Compact Bionic Modules) <Bugfix> This is a fix for a bug (or closes open issue)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bionic power constant int overflow
4 participants