Problem/Motivation
There is code in MenuTreeStorage to load menu tree elements by some properties, like 'route_name'.
The method MenuTreeStorage::loadByProperties() allows to pass in any kind of parameter.
This is problematic in case someone does not know which parameters to filter by and passes in a wrong one.
This could lead to invalid SQL queries.
Proposed resolution
Validate the passed in parameter, whether it actually exists, so you cannot produce invalid SQL.
Remaining tasks
User interface changes
API changes
Original report by @kgoel
In MenuTreeStorage.php
// @todo Only allow loading by plugin definition properties.
We need to add plugin definition property so we can throw an exception. Right now its using definitionFields() which is big array and using database query to load properties.
| Comment | File | Size | Author |
|---|---|---|---|
| #35 | increment.txt | 2.02 KB | pwolanin |
| #35 | 2302165-34.patch | 2.86 KB | pwolanin |
| #35 | 2302165-test-only-34.patch | 1.99 KB | pwolanin |
| #32 | only_allow_loading_by-2302165-32.patch | 1.69 KB | cilefen |
| #32 | interdiff-29-32.txt | 764 bytes | cilefen |
Comments
Comment #1
kgoel commentedComment #2
tim.plunkettCan you expand on why this is needed or what it actually does?
Comment #3
dawehnerUpdated, but I think this is nothing we should do. If you as a developer ask for a wrong name, this is just your fault.
Comment #4
pwolanin commentedShouldn't be worked on until after #2301319: MenuLinkNG part5: Remove dead code; and party!
Comment #5
pwolanin commentedready to go ahead
Comment #6
cilefen commentedComment #7
tim.plunkettUse sprintf or formatString, please
Comment #8
pwolanin commentedI might consider using just \InvalidArgumentException instead of the plugin exception?
Also, the method doc needs to have an @throws added
Comment #9
cilefen commentedComment #10
dawehnerI think we should also expand the MenuTreeStorageTest to check that the exception is thrown.
Comment #11
cilefen commentedComment #12
pwolanin commentedLet's put the @throws on the interface, and leave this as @inheritdoc
Also, the exception message isn't quite right: 'An invalid plugin definition' should be more like 'An invalid property name'
Comment #13
tim.plunkettAlso, while you're at it:
Consider using @expectedException and @expectedExceptionMessage instead of the the try/catch.
Comment #14
cilefen commented@tim.plunkett Is @expectedException usable? It's not phpunit.
Comment #15
tim.plunkettOh, I missed that it was simpletest. Carry on!
Comment #16
pwolanin commentedLooks good.
Comment #17
alexpottWe need a
$this->fail('An invalid property name throws an exception.');We don't use t() assertion messages anymore.
Comment #18
cilefen commentedComment #19
pwolanin commentedThanks @cilefen
Comment #20
alexpottAre we sure we want to do this? We don't do this in any of the other loadByProperties implementations - perhaps we're being overly defensive - yes we'll get an SQL error during development but that error will explain nicely to the developer that they've done a loadByProperties on a non-existing property - maybe I'm missing something?
@cilefen the pass and fail messages should not be different. Perhaps what is above would be better.
Comment #21
pwolanin commented@alexpott - so, yes we want to do this. Here's why: it should only be supported by the API to load using the definition properties. However, any given implementation may have a variety of additional properties/columns in the storage. We need to prevent people from making assumptions about the implementation.
Comment #22
dawehnerCan we list the available fields in the exception?
Comment #23
cilefen commentedIncludes @alexpott's and @dawehner's suggestions. As always, thank you for reviewing.
Comment #24
dawehnerCool, thank you.
Comment #25
alexpottCommitted 25627b0 and pushed to 8.0.x. Thanks!
Comment #26
alexpottCommitted 25627b0 and pushed to 8.0.x. Thanks!
Comment #28
sunSorry, but the test code is broken; bogus double-array:
HEAD should fail, but it does not. Here's why:
Insufficient parameter validation. The validation in
loadByProperties()performs a loose comparison; a non-empty array is always "in" an array that is not empty.Rule of thumb: Always use a strict comparison for
in_array()unless you have a very good reason to not use it:In addition to that though, for some unknown reason, HEAD seems to return a result that happens to match the
assertEqual()test (equally loose comparison), which I can't explain, but definitely must not happen.Comment #29
cilefen commented@sun your attention to detail is appreciated. Here are the fixes you suggested.
Comment #30
sun@cilefen: It wasn't me. :) This is really just one of many errors that would have been natively caught by PHPUnit: #2304461: KernelTestBaseTNG™
Comment #31
pwolanin commentedSo, I think the other problem here is that all menu links are in tools by default, so it would be a better test to load one using a different menu name.
Comment #32
cilefen commentedAdded the test link to a different menu as per @pwolanin's suggestion and added an additional assert to be sure we are looking at the correct link.
Comment #33
pwolanin commentedMinor, but we should use a distinct string ID instead of 1.
Comment #34
cilefen commentedComment #35
pwolanin commentedThe actual fail was the 0 to string compare, not nested array, so let's test that too.
This change to the test verifies that case fails without the strict comparison in the full patch.
Comment #37
cilefen commented@pwolanin Thanks.
Comment #38
alexpottCommitted a04820c and pushed to 8.0.x. Thanks!