fix: treat a negative page size as an empty page, not a syntax error - #827
Merged
Conversation
How far into a list to start, and how much of it to take, both come from the
query string, and nothing narrowed them on the way to the database:
?count=-1 -> Filter::getInt('-1') = -1 -> no clamp -> LIMIT -1
?start=-5 -> OFFSET -5
which MariaDB answers with `ERROR 1064 ... syntax error near '-1'`. Asking for a
page came back as a database failure. Nothing was disclosed and nothing was
harmed, but a value an ordinary request can carry should not reach the server as
unparseable SQL.
There are two ways in, so there are two places to clamp. The item grids and
every API search build an `ItemSearchDto`; the account search reads `start` and
`rpp` straight from the request into `AccountSearchFilterDto`. Clamping only the
first would have left the search people actually use still broken.
The third test asserts the generated statement carries no negative LIMIT or
OFFSET, because the getters were never the problem — the string that reached
MariaDB was.
The upper end is deliberately left alone: `count` has no maximum, but a large
one is authenticated, returns only rows the caller may already see, and capping
it would change behaviour for legitimate large queries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
How far into a list to start, and how much of it to take, both come from the query string, and nothing narrowed them on the way to the database. Traced end to end:
So asking for a page came back as a database failure. Nothing is disclosed and nothing is harmed — but a value an ordinary query string can carry should not reach the server as unparseable SQL.
Two ways in, so two places to clamp
ItemSearchDto;startandrppstraight from the request intoAccountSearchFilterDto, never touching that DTO.Clamping only the first would have left the search people actually use still broken. Both are clamped, and the tests cover both paths through one data provider.
The third test
It asserts the generated statement carries no negative
LIMITorOFFSET, because the getters were never the problem — the string that reached MariaDB was. Removing either clamp fails five cases across the three tests.Deliberately not changed
counthas no upper bound, so an authenticated caller can ask for a million rows. Left alone: it is authenticated, it returns only rows the caller may already see, and capping it would change behaviour for legitimate large queries. Speculative hardening without evidence of harm is how theConfigBackupdeserialization change went wrong earlier in this series.3988 unit tests pass; PHPStan level 6 on
srcand PHPCS clean; integration running.