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

Warn on always false integer reads and comparisons. #1919

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

wxsBSD
Copy link
Collaborator

@wxsBSD wxsBSD commented May 7, 2023

When reading an integer of a specific size and comparing it to an integer of a larger size where any of the upper bits are set we will now emit a warning because the comparison is always false.

These will always evaluate to false because the "extra" bytes are non-zero:

uint8(0) == 0x1100
uint16(0) == 0x110000
uint32(0) == 0x1100000000

While I'm here, move a test into a better place for it. I added it in the wrong place in ccbc405.

Fixes #1918.

wxsBSD added 4 commits May 6, 2023 23:09
When reading an integer of a specific size and comparing it to an integer of a
larger size where any of the upper bits are set we will now emit a warning
because the comparison is always false.

These will always evaluate to false because the "extra" bytes are non-zero:

uint8(0) == 0x1100
uint16(0) == 0x110000
uint32(0) == 0x1100000000

While I'm here, move a test into a better place for it. I added it in the wrong
place in ccbc405.

Fixes VirusTotal#1918.
Turns out that my first implementation of this was flawed. Things like
uint8(uint8(0)) would cause an error.

To make this a bit easier to follow I changed the lexer return tokens for each
of the integer functions, instead of a single _INTEGER_FUNCTION_ token with an
index value to use when emiting the opcode. By doing this I can then set the
width of the expression based upon the new token types and use that when doing
the width check (instead of inferring the width from the index).

Once we have reduced the integer_function we can set it to an integer with an
undefined value and it will be treated like a normal integer for all operations,
except for _EQ_, which has special case logic to check the width and any
compile-time values.
@plusvic
Copy link
Member

plusvic commented May 19, 2023

Do we really need EXPRESSION_TYPE_INTEGER_FUNCTION? I mean, as long as every EXPRESSION_TYPE_INTEGER has an associated field width indicating the number of bits in that integer we can check that operations between integers of different widths are ok, no matter if they come from uintXX or from somewhere else. Treating the result of a uintXX function as the rest of integers, instead of having a special case, simplifies things and allows to properly raise warnings in cases like uint8(0) & 1 == 0x1100. The expression uint8(0) & 1 would be EXPRESSION_TYPE_INTEGER as well as uint8(0), but uint8(0) & 1 could retain the with of uint8(0) and propagate it up to uint8(0) & 1 == 0x1100.

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.

Check for impossible conditions when using uint() operators.
2 participants