Skip to content

bugfix - Search feature not finding special characters like '%'#75

Merged
sam1am merged 1 commit intosam1am:mainfrom
davidp57:bug-fix-search-for-special-characters
Feb 28, 2026
Merged

bugfix - Search feature not finding special characters like '%'#75
sam1am merged 1 commit intosam1am:mainfrom
davidp57:bug-fix-search-for-special-characters

Conversation

@davidp57
Copy link
Contributor

Fixes issue #74: escape SQL LIKE special characters in search queries

Problem

Searching for % or _ in the library search box produced wrong results:

  • % → matched all games (SQL LIKE interprets % as "any sequence of characters")
  • _ → matched any single character instead of a literal underscore

Additionally, the genres filter had the same issue, and the search parameter had no length limit, leaving a potential DoS vector.

Changes

web/utils/helpers.py

  • New escape_like(value: str) -> str utility function that escapes \, %, and _ before injecting a value into a LIKE pattern.

web/routes/library.py

  • Applied escape_like() + ESCAPE '\\' on all three name LIKE ? queries: /library, /hidden, /removed.
  • Applied escape_like() + ESCAPE '\\' on the genres LIKE filter as well.
  • Added max_length=200 via Query(...) on the search parameter in all three routes to prevent oversized inputs.

tests/test_search.py (new file)

  • Unit tests for escape_like covering %, _, \, and combinations.
  • Integration tests against /library verifying that % only matches games whose name contains a literal %, that _ is not treated as a wildcard, and that searches longer than 200 characters return HTTP 422.

Notes

  • No SQL injection risk was found: all user inputs are already passed as bound parameters (?). The only values interpolated directly into SQL (sort, order, playtime_label) are validated against whitelists before use.
  • The fix is purely defensive: correct LIKE escaping + input size cap.

Copilot AI review requested due to automatic review settings February 28, 2026 11:15
@davidp57
Copy link
Contributor Author

Here you go @sam1am; that's a simple bugfix PR.
I tested - it works fine, and I couldn't find any regression.
I had Claude check for SQL injection risks too, while I was at it.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes SQLite LIKE wildcard handling in library search and genre filters so user-supplied % and _ are treated as literals, and adds a query-length cap to reduce oversized-input risk.

Changes:

  • Added escape_like() helper to escape \, %, and _ for SQL LIKE patterns.
  • Updated /library, /hidden, and /removed routes to use ESCAPE '\\' and apply escaping to both name search and genre filters.
  • Added tests for escape_like and integration tests for /library search behavior and the max_length=200 validation.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
web/utils/helpers.py Introduces escape_like() utility for safe literal matching in LIKE queries.
web/routes/library.py Applies escape_like() and ESCAPE '\\' to name/genre LIKE filters and adds search max length.
tests/test_search.py Adds unit + integration coverage for escaping behavior and request validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +78 to +86
def test_underscore_search_returns_only_matching_game(self, client_with_special_games):
"""Searching for _ should not act as a wildcard; only exact matches are returned."""
resp = client_with_special_games.get("/library?search=Pro_game")
assert resp.status_code == 200
text = resp.text
assert "Pro_game" in text
# Normal Game has no underscore – should not match
assert "Normal Game" not in text

Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

test_underscore_search_returns_only_matching_game doesn’t actually prove that _ is no longer treated as a LIKE wildcard: the pattern %Pro_game% wouldn’t match Normal Game even in the buggy (unescaped) implementation. Add a counterexample row (e.g. ProXgame) that would match if _ were a wildcard, or add a test that searches for _ alone and asserts only names containing a literal underscore are returned.

Copilot uses AI. Check for mistakes.
@sam1am sam1am linked an issue Feb 28, 2026 that may be closed by this pull request
@sam1am sam1am merged commit a66aa71 into sam1am:main Feb 28, 2026
4 of 5 checks passed
@sam1am
Copy link
Owner

sam1am commented Feb 28, 2026

Looks good, thanks! Merging.

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.

Search feature not finding special characters like '%'

3 participants