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: [Script] ScriptBase::Rand() return value was between -MIN(int32) and MAX(int32) #10443

Merged
merged 1 commit into from Feb 10, 2023

Conversation

glx22
Copy link
Contributor

@glx22 glx22 commented Feb 2, 2023

Also ensure the parameters for ScriptBase::RandRange() and ScriptBase::Chance() are in [0-MAX(uint32)] range

Motivation / Problem

Documentation says ScriptBase::Rand() return a random value between 0 and MAX(uint32), but the actually returned value is between -MIN(int32) and MAX(int32).
ScriptBase::RandRange() has the same issue with values above MAX(int32) becoming negative.

Description

Use SQInteger as return type, so uint32 values are casted to int64 instead of int32.
Also use SQInteger for parameters, allowing to check them to be in the uint32 range.

Limitations

No compatibility scripts as the documentation was always correct.

Checklist for review

Some things are not automated, and forgotten often. This list is a reminder for the reviewers.

  • The bug fix is important enough to be backported? (label: 'backport requested')
  • This PR touches english.txt or translations? Check the guidelines
  • This PR affects the save game format? (label 'savegame upgrade')
  • This PR affects the GS/AI API? (label 'needs review: Script API')
    • ai_changelog.hpp, gs_changelog.hpp need updating.
    • The compatibility wrappers (compat_*.nut) need updating.
  • This PR affects the NewGRF API? (label 'needs review: NewGRF')

Copy link
Contributor

@SamuXarick SamuXarick left a comment

Choose a reason for hiding this comment

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

Mind if I submit general feedback?


#include "../../safeguards.h"

/* static */ uint32 ScriptBase::Rand()
/* static */ SQInteger ScriptBase::Rand()
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it better to use int64 than SQInteger? I always thought SQInteger was specifically used outside the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SQInteger is the type used in every squirrel internal functions (especially sq_pushinteger() to pass a number to the squirrel VM and sq_getinteger() to get a number from the VM). It is indeed an int64, but I think using SQInteger is better as it hides implementation details from the API.

{
return ScriptObject::GetRandomizer().Next();
}

/* static */ uint32 ScriptBase::RandItem(int unused_param)
/* static */ SQInteger ScriptBase::RandItem(SQInteger unused_param)
Copy link
Contributor

Choose a reason for hiding this comment

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

unused_param doesn't really need to change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, but my idea would be to use SQInteger everywhere in the API for generic numbers.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then, as a reminder for a later (cleanup) story: remove the casts from squirrel_helper_type.hpp:49-51 as well as 57.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah you mean squirrel_helper.hpp

{
if (max < 0 || max > UINT32_MAX) {
ScriptLog::Warning("Clamping RandRange() parameter to 0..MAX(uint32)");
Copy link
Contributor

Choose a reason for hiding this comment

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

ScriptLog::Warning is a bit too intrusive, better just tell a clamping may happen in the description, rather than outputing it into the log.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, will update.

@glx22 glx22 force-pushed the random branch 2 times, most recently from 0a342b7 to 19130eb Compare February 3, 2023 18:27
… and MAX(int32)

Also ensure the parameters for ScriptBase::RandRange() and ScriptBase::Chance() are in [0-MAX(uint32)] range
Copy link
Contributor

@rubidium42 rubidium42 left a comment

Choose a reason for hiding this comment

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

Should we add a note to the changelogs about the behavior being incorrect based on the specification in everything before OpenTTD 14? And that there is no compatibility layer that reintroduces this buggy behavior to scripts requesting an older API version?
I'm not sure though, as this is just fixing the behavior to be like it's specified. Though it might also break some expectations.

{
return ScriptObject::GetRandomizer().Next();
}

/* static */ uint32 ScriptBase::RandItem(int unused_param)
/* static */ SQInteger ScriptBase::RandItem(SQInteger unused_param)
Copy link
Contributor

Choose a reason for hiding this comment

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

Then, as a reminder for a later (cleanup) story: remove the casts from squirrel_helper_type.hpp:49-51 as well as 57.

@glx22 glx22 merged commit 6b99b66 into OpenTTD:master Feb 10, 2023
@glx22 glx22 deleted the random branch February 10, 2023 18:56
serg-bloim pushed a commit to serg-bloim/OpenTTD that referenced this pull request Feb 10, 2023
… and MAX(int32) (OpenTTD#10443)

Also ensure the parameters for ScriptBase::RandRange() and ScriptBase::Chance() are in [0-MAX(uint32)] range
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.

None yet

3 participants