nuwave / nuwave/lighthouse

Malformed UTF-8 characters in PaginatedModelsLoader

Open
#2,789 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
3.5k
Forks
468
Avg merge
3h 9m
Merged PRs (30d)
2

Description

Describe the bug

https://github.com/nuwave/lighthouse/pull/2540 added a json_encode call at https://github.com/SOERF/lighthouse/blob/master/src/Execution/ModelsLoader/PaginatedModelsLoader.php#L89 to compare models rather than toJson, which was changed to encoding the raw original values in https://github.com/nuwave/lighthouse/pull/2550 to avoid some casted values not being able to json_encode. However, some raw values cannot be passed to json_encode either, like binary UUID representations as used by https://github.com/michaeldyrynda/laravel-model-uuid. The raw value is a string in PHP but it is not valid UTF-8, so json_encode fails with the JSON_ERROR_UTF8 error.

I am happy to assist with a PR here though I don't think this has an obvious solution so I wanted to discuss in an Issue before I went down that path.

Expected behavior/Solution

Comparison should complete without error while still comparing all values as needed.

  • This could be worked around simply by passing the JSON_INVALID_UTF8_IGNORE or JSON_INVALID_UTF8_SUBSTITUTE flags to json_encode, but this likely has poor side effects I'm not currently thinking about by effectively hiding these values from the comparison.
  • Ideally the comparison should correctly compare the full attributes as intended without failing on non-encodable values either pre- or post-cast.

Steps to reproduce

  1. Define a has-many relationship between two models with a column using the Laravel Model UUID library (or similar non-UTF8 strings)
  2. Return the relationship in a GraphQL field using the @hasMany(type: PAGINATOR) directive
  3. Attempt to load the field, see the error during the json_encode call

Output/Logs

Safe\Exceptions\JsonException: Malformed UTF-8 characters, possibly incorrectly encoded in /.../vendor/thecodingmachine/safe/lib/Exceptions/JsonException.php:9
Stack trace:
#0 /.../vendor/thecodingmachine/safe/generated/8.1/json.php(20): Safe\Exceptions\JsonException::createFromPhpError()
#1 /.../vendor/nuwave/lighthouse/src/Execution/ModelsLoader/PaginatedModelsLoader.php(89): Safe\json_encode(Array)

Lighthouse Version

v6.70.1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/Execution/ModelsLoader/PaginatedModelsLoader.php around line 89, where Safe\json_encode compares models. Reproduce the failure through a GraphQL field using @hasMany(type: PAGINATOR) with a non-UTF-8 value such as a binary UUID. Done means pagination comparison completes without an encoding error while still comparing the full attributes.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, laravel, php
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.