Guard expression resolver against malformed-UTF-8 json_encode

resolveVariable() declares a string return type, but json_encode returns
false on malformed UTF-8 (plausible for scraped feed/HTTP payloads),
which throws a TypeError under strict_types and fails the node. Encode
with JSON_PARTIAL_OUTPUT_ON_ERROR and fall back to an empty string.
This commit is contained in:
Paulo Castellano 2026-06-13 10:25:25 -03:00
parent fe8cd8a970
commit 1b2ff23dff
2 changed files with 17 additions and 1 deletions

View file

@ -58,6 +58,8 @@ private function resolveVariable(string $path, array $context): string
return (string) $value;
}
return json_encode($value);
// json_encode returns false on malformed UTF-8 (plausible for scraped
// feed/HTTP payloads); the method must still return a string.
return json_encode($value, JSON_PARTIAL_OUTPUT_ON_ERROR) ?: '';
}
}

View file

@ -50,3 +50,17 @@
it('passes through templates with no variables', function () {
expect($this->resolver->resolve('plain text', []))->toBe('plain text');
});
it('json-encodes array values', function () {
$context = ['fetched' => ['tags' => ['a', 'b']]];
expect($this->resolver->resolve('{{ fetched.tags }}', $context))->toBe('["a","b"]');
});
it('does not throw when an array value contains malformed UTF-8', function () {
// Scraped feed/HTTP payloads can carry invalid UTF-8; json_encode returns
// false for it, but the resolver must still yield a string.
$context = ['fetched' => ['body' => ["bad\xB1utf8"]]];
expect($this->resolver->resolve('{{ fetched.body }}', $context))->toBeString();
});