Skip to content

fix: add defensive checks for time ranges, pointer queries, and entity fields#1889

Open
LautaroPetaccio wants to merge 3 commits into
mainfrom
fix/misc-code-correctness
Open

fix: add defensive checks for time ranges, pointer queries, and entity fields#1889
LautaroPetaccio wants to merge 3 commits into
mainfrom
fix/misc-code-correctness

Conversation

@LautaroPetaccio
Copy link
Copy Markdown
Contributor

Summary

Three defensive-coding fixes across different modules:

  • isTimeRangeCoveredBy assumed sorted input (logic/time-range.ts): The sweep-line algorithm checked for gaps by comparing each range's start against the running max. If input ranges were unsorted, it could falsely detect a gap and trigger unnecessary snapshot regeneration. Now sorts a copy of the input by initTimestamp before sweeping.

  • Empty pointers array produces invalid SQL (pointers-queries.ts): updateActiveDeployments and removeActiveDeployments built SQL INSERT ... VALUES or DELETE ... IN () clauses from the pointers array without guarding against empty input. While callers currently validate this upstream, the functions themselves now return early on empty arrays.

  • Invalid field names silently become undefined (get-entities-handler.ts): The ?fields= query param mapped field names to EntityField enum values via (<any>EntityField)[f.toUpperCase()]. Unrecognized names produced undefined entries in the array, which were passed through to maskEntity(). Now filters out undefined values after mapping.

Also adds result.set(item, false) in checker.ts for items without a contractAddress, making the rejection explicit instead of relying on the || false fallback at the call site.

Test plan

  • Added 3 unit tests for unsorted time range coverage (reversed, overlapping, with gap)
  • Run: cd content && npx jest test/unit/ --no-coverage

Copy link
Copy Markdown
Collaborator

@decentraland-bot decentraland-bot left a comment

Choose a reason for hiding this comment

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

Review: fix: add defensive checks for time ranges, pointer queries, and entity fields

PR: #1889
Files changed: 5 (+43 -4)


Findings Summary

  • P1 CRITICAL: 1 — blocks merge
  • P2 IMPORTANT: 2 — should fix
  • P3 NICE-TO-HAVE: 2 — enhancements

P1 — Critical (Blocks Merge)

  1. [CI] validations check is failing — prettier formatting error
    • File: content/src/controller/handlers/get-entities-handler.ts:48
    • The chained .filter() makes the line too long for prettier. The lint step wants the chain broken across multiple lines:
      enumFields = fields
        .split(',')
        .map((f) => (<any>EntityField)[f.toUpperCase().trim()])
        .filter((f) => f !== undefined)

P2 — Important

  1. [Correctness] Empty enumFields array when all field names are invalid

    • File: content/src/controller/handlers/get-entities-handler.ts:48
    • If a client sends ?fields=BOGUS, the filter produces enumFields = [] (empty array). Previously this would have been [undefined]. Verify how downstream code (maskEntity) handles an empty array vs undefined — if [] means "return no fields" rather than "return all fields", this silently changes the API behavior for typo'd requests. Consider either returning a 400 for unrecognized field names, or treating [] the same as undefined.
  2. [Testing] Missing test coverage for 3 of the 4 fixes

    • The time-range fix has good tests ✅
    • No test for checker.ts — should assert result.get(item) === false when contractAddress is missing
    • No test for pointers-queries.ts — should verify early return on empty arrays without hitting the DB
    • No test for get-entities-handler.ts — should verify invalid field names are filtered and check the empty-array edge case

P3 — Nice-to-Have

  1. [Type Safety] <any>EntityField bracket-notation lookup with user input

    • File: content/src/controller/handlers/get-entities-handler.ts:48
    • Pre-existing, but worth improving alongside this change. Prototype keys like __proto__, constructor, toString are not undefined and will survive the filter. A whitelist approach is safer:
      const VALID_FIELDS = new Set(Object.values(EntityField))
      enumFields = fields
        .split(',')
        .map((f) => (<any>EntityField)[f.toUpperCase().trim()])
        .filter((f): f is EntityField => VALID_FIELDS.has(f))
  2. [Clarity] time-range.ts loop redundantly processes sorted[0]

    • The first iteration compares sorted[0].initTimestamp > sorted[0].endTimestamp (always false for valid ranges) and the Math.max is a no-op. Starting from index 1 would be slightly cleaner but not functionally necessary.

Security

No new vulnerabilities introduced. The changes are net-positive for security — the empty-array SQL guards prevent malformed queries, and the undefined filter prevents unexpected downstream behavior. The pre-existing <any> enum lookup is flagged above as a P3 improvement.


Verdict

Request changes — the CI formatting failure must be fixed before merge, and the empty enumFields array edge case should be verified.

Requested by Lautaro Petaccio via Slack

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.

2 participants