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

Fix potential integer underflow in rounded up divisions #80390

Merged
merged 1 commit into from
Jan 2, 2024

Conversation

EddieBreeg
Copy link
Contributor

@EddieBreeg EddieBreeg commented Aug 7, 2023

A new division_round_up function was added in the Math class, allowing for easy and correct computation of integer divisions when the result needs to be rounded up.
https://github.com/EddieBreeg/godot/blob/8349f16f316b90f705da1219f52828a0af889907/core/math/math_funcs.h#L190-L201

@EddieBreeg EddieBreeg requested review from a team as code owners August 7, 2023 19:33
@Sauermann Sauermann added this to the 4.x milestone Aug 8, 2023
@AThousandShips
Copy link
Member

AThousandShips commented Aug 8, 2023

To link it use just "fixes", also don't write "bugsquad", that means it was added by one of the members of that team

@AThousandShips
Copy link
Member

Please squash your commits into one, see here

@EddieBreeg
Copy link
Contributor Author

Done

@miv391
Copy link
Contributor

miv391 commented Aug 8, 2023

How about adding comments about the parameter limits/requirements? For example the first function requires that the sum of num and den must be between min_int and max_int (otherwise there in an overflow).

@EddieBreeg
Copy link
Contributor Author

Would there be any benefit to marking the function as constexpr?

@AThousandShips
Copy link
Member

AThousandShips commented Aug 8, 2023

No I'd say, none of the contexts where it is used are constexpr compatible, all uses are runtime, and since it's always inlined it wouldn't change anything anyway

@EddieBreeg
Copy link
Contributor Author

EddieBreeg commented Aug 8, 2023

Well right now they're not used in a constexpr context but do we know that's not going to change? And adding it wouldn't change a thing if it has to be evaluated at runtime anyway

@EddieBreeg EddieBreeg closed this Aug 8, 2023
@EddieBreeg
Copy link
Contributor Author

Ok what the hell, I didn't close this

@AThousandShips
Copy link
Member

AThousandShips commented Aug 8, 2023

But if you're doing things at compile time then you should probably not be depending on this right?

constexpr should only be added if you know it'll help:

Any feature not listed below is allowed. Using features like constexpr variables and nullptr is encouraged when possible. Still, try to keep your use of modern C++ features conservative. Their use needs to serve a real purpose, such as improving code readability or performance.

@AThousandShips
Copy link
Member

You closed this, you probably clicked the wrong button when commenting

@AThousandShips AThousandShips reopened this Aug 8, 2023
@EddieBreeg
Copy link
Contributor Author

You closed this, you probably clicked the wrong button when commenting

Well that's great, thanks github...

But if you're doing things at compile time then you should probably not be depending on this right?

In theory no, but then why does anyone use constexpr right? Arguably, for code readability so that it's still obvious what you're doing. I agree it's unlikely it will actually get used, I just think it doesn't hurt

@miv391
Copy link
Contributor

miv391 commented Aug 8, 2023

As this PR is being made because previous implementation bugged when num was 0, I would suggest making unit tests to prove that now this works.

@AThousandShips
Copy link
Member

AThousandShips commented Aug 8, 2023

Except it's inlined so it will have no effect what so ever, and it doesn't help readability either, and no other function in this header has constexpr, for the same reason

@EddieBreeg
Copy link
Contributor Author

As this PR is being made because previous implementation bugged when num was 0, I would suggest making unit tests to prove that now this works.

Will do

@lawnjelly
Copy link
Member

Regarding overflow, we often just don't handle it (for instance even the simplest expression x + y can overflow), and leave it to client code to check if this seems a possibility. That would probably be fine.

But if you wanted some cheap checks, if you look at error_macros.h in 3.x, we have DEV_CHECK_ONCE(), which I never added to master but can be used for some very basic error detection in DEV builds.

#ifdef DEV_ENABLED
#define DEV_CHECK_ONCE(m_cond)                                                   \
	if (unlikely(!(m_cond))) {                                                   \
		ERR_PRINT_ONCE("DEV_CHECK_ONCE failed  \"" _STR(m_cond) "\" is false."); \
	} else                                                                       \
		((void)0)
#else
#define DEV_CHECK_ONCE(m_cond)
#endif

So you could have e.g. DEV_CHECK_ONCE(((int64_t) pnum + (int64_t) pden) < INT32_MAX); type checks for overflow.

This will print a one time error (so as not to spam) if overflow is detected, but is compiled out in release builds so is free.

@EddieBreeg
Copy link
Contributor Author

So you'd suggest not adding comments and adding the cheap tests instead?

@AThousandShips
Copy link
Member

AThousandShips commented Aug 8, 2023

To ensure the correct behaviour of these I'd say test cases should be added to tests/core/math/test_math_funcs.h

@EddieBreeg
Copy link
Contributor Author

As I said, I will. In fact I have, the changes just aren't pushed yet.

@AThousandShips
Copy link
Member

Wanted to make sure as there was talk of different tests going on

@AThousandShips
Copy link
Member

Potential case for this:

Copy link
Member

@akien-mga akien-mga left a comment

Choose a reason for hiding this comment

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

Looks good to me from a cursory look. Sorry for the delay reviewing.

core/math/math_funcs.h Outdated Show resolved Hide resolved
@YuriSizov
Copy link
Contributor

@EddieBreeg Will you be available to address the feedback? This PR also needs a rebase.

@EddieBreeg EddieBreeg requested a review from a team as a code owner January 2, 2024 12:37
@akien-mga
Copy link
Member

I rebased the PR myself, solving the conflicts, adding the change I suggested, and handling a few other occurrences which I found with this regex:

rg "\- 1\) /.*\+ 1" -g'!thirdparty'

There might be more when they're multiline of with either operand being a local variable, but this should be a good start.

@akien-mga akien-mga added the cherrypick:4.2 Considered for cherry-picking into a future 4.2.x release label Jan 2, 2024
@akien-mga akien-mga force-pushed the issue_80358 branch 2 times, most recently from 08d169f to 38dc4a9 Compare January 2, 2024 12:55
A new `Math::division_round_up()` function was added, allowing for easy
and correct computation of integer divisions when the result needs to
be rounded up.

Fixes godotengine#80358.

Co-authored-by: Rémi Verschelde <[email protected]>
@akien-mga akien-mga merged commit ac83ad1 into godotengine:master Jan 2, 2024
15 checks passed
@akien-mga
Copy link
Member

akien-mga commented Jan 2, 2024

Thanks! And congrats for your first merged Godot contribution 🎉

Copy link
Member

@reduz reduz left a comment

Choose a reason for hiding this comment

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

This PR was merged without even being tested. I am not happy about it.

@@ -1033,7 +1033,7 @@ void main() {

if (local == ivec3(0) && store_position_count > 0) {
store_from_index = atomicAdd(dispatch_data.total_count, store_position_count);
uint group_count = (store_from_index + store_position_count - 1) / 64 + 1;
uint group_count = Math::division_round_up(store_from_index + store_position_count, 64);
Copy link
Member

Choose a reason for hiding this comment

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

This should not have been merged, the shader does not even compile.
Was this PR even tested?

Copy link
Member

@akien-mga akien-mga Jan 3, 2024

Choose a reason for hiding this comment

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

My mistake, I added this yesterday and didn't notice it was touching a .glsl file.

Copy link
Member

Choose a reason for hiding this comment

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

Fixed by 7abaac6.

akien-mga added a commit that referenced this pull request Jan 3, 2024
My mistake, I added this when rebasing and didn't notice that it was a
.glsl file and thus the availability of Math was not confirmed by the
C++ compiler.
@akien-mga
Copy link
Member

This PR was merged without even being tested. I am not happy about it.

I tested, but didn't notice the error. My test project was likely not using SDFGI.
It does show a shader compilation error when running Godot from terminal, but none in the editor itself, so I missed it when doing a quick check after finalizing the PR.

Anyway, this was my bad, I added this change yesterday after rebasing and noticing a few new cases of (x + 1) / y - 1 that should be refactored. I've undone the .glsl change in 7abaac6.

GuybrushThreepwood-GitHub pushed a commit to GuybrushThreepwood-GitHub/godot that referenced this pull request Jan 27, 2024
My mistake, I added this when rebasing and didn't notice that it was a
.glsl file and thus the availability of Math was not confirmed by the
C++ compiler.
@clayjohn clayjohn removed the cherrypick:4.2 Considered for cherry-picking into a future 4.2.x release label Mar 11, 2024
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.

Integer underflows throughout the code when trying to round up
9 participants