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
Warning for negative string offset (< PHP 7.1) #1791
Warning for negative string offset (< PHP 7.1) #1791
Conversation
src/Phan/Parse/ParseVisitor.php
Outdated
@@ -1014,6 +1014,21 @@ public function visitDim(Node $node) : Context | |||
return $this->context; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Config::get_backward_compatibility_checks() is usually false. The new code should be added before this check.
src/Phan/Parse/ParseVisitor.php
Outdated
@@ -1014,6 +1014,21 @@ public function visitDim(Node $node) : Context | |||
return $this->context; | |||
} | |||
|
|||
// check for $str{-3} for PHP < 7.1 | |||
if (Config::get_closest_target_php_version_id() < 70100 | |||
&& $node->children['expr'] instanceof Node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code that performs the check can go into its own helper method
src/Phan/Parse/ParseVisitor.php
Outdated
if (Config::get_closest_target_php_version_id() < 70100 | ||
&& $node->children['expr'] instanceof Node | ||
&& $node->children['expr']->kind == \ast\AST_VAR | ||
&& ($node->children['dim'] ?? null) instanceof Node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$union_type = UnionTypeVisitor::unionTypeFromNode($code_base, $context, $node->children['expr'])
is recommended for checking if something is a string (e.g. $union_type->isNonNullStringType()
is similar to what you want as a check).
The code you have here would also warn about accessing negative indices of arrays, which is a false positive.
$str = "abcdef"; | ||
|
||
$char = $str{-1}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test that this doesn't warn about negative offsets of arrays.
It's run by invoking At the time it was originally written, it seemed impossible to change certain config settings and plugins from the config that was originally loaded.
|
- separated the check into its own method - using type check for strings, so we don't catch arrays - renamed the issue - it's not specific to PHP 7.0 - updated .gitignore to exclude .idea/ - updated config finder so it doesn't break when realpath() returns false
Thanks for the feedback. I did come back to rearrange and improve the code. Also managed to run the tests for PHP 7.0 after fixing the
However, I'm having issues with determining the node type with
or:
It just emits the I suspect that something could be wrong with the "context" for the Edit: note that static class properties or class constants aren't triggering the |
also, expected values aren't real (yet)
src/Phan/Parse/ParseVisitor.php
Outdated
) | ||
// $str{"-1"}|["-1"] | ||
|| ( | ||
\is_string($node->children['dim']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this, using a non-integer as a string literal as a string offset is already a separate issue type and doesn't need to be checked for.
src/008_negative_string_offset.php:17 PhanTypeMismatchDimFetch When fetching an array index from a value of type string, found an array index of type '-1', but expected the index to be of type int
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've noticed that, and I was in doubt whether to dismiss this case or to take it into account (so both warnings get emitted by default).
However, one could suppress/exclude PhanTypeMismatchDimFetch
so this would go unnoticed, but... you are probably aware of that. My gut feeling is that we shouldn't do this, too. Will remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty much.
This code can be moved to the same place as PhanTypeMismatchDimFetch, since Phan is already checking the fetched offsets there
src/Phan/Parse/ParseVisitor.php
Outdated
@@ -1010,6 +1011,10 @@ public function visitAssign(Node $node) : Context | |||
|
|||
public function visitDim(Node $node) : Context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this the first time I looked at this code because I didn't expect it:
All of your changes to ParseVisitor need to be moved to visitDim in PostOrderAnalysisVisitor.
That's why you're seeing the strange undefined variables and undefined $this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UnionTypeVisitor::visitDim might be more appropriate, actually.
That already has checks if code is reading to or writing to that offset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, sorry. Thought I've made myself sound like a total noob when opening the PR :)
I knew that it must be something like that, but I couldn't figure it out myself. It's a bit overwhelming experience to dive into the internals of Phan, still struggling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/phan/phan/wiki/Developer%27s-Guide-To-Phan might be of help if you haven't seen it yet.
e.g. https://github.com/phan/phan/wiki/Developer%27s-Guide-To-Phan#ast-node-visitors
- moved the check to the place where we're pretty sure it could be a string - test file simplified - cleaned up the check from ParseVisitor
55e4d6e
to
4d241ef
Compare
Build finally passing 😌 Added the check to I've also simplified the test file. All those cases from the previous version aren't really required now that the check is where it really should be. Note that I did some minor changes along the way:
I'm not emotionally attached to these small touches listed above, but I'd appreciate if they're not dismissed 🍺 |
This is my first attempt to do something related to Phan's true job - it took a while to figure things out enough for a small task like fixing #1778
Now, there are tree things that could/should be improved:
if
statement is rather big, but that's the pattern I found to be reliable. Since it's all new to me, I didn't want to go to far with shortening it. However, maybe I went too far in the opposite direction.