Skip to content

Commit

Permalink
fix: JSON data may cause "Array to string conversion" error
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjis committed Sep 2, 2022
1 parent 3ba1eb5 commit 8760a49
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
30 changes: 29 additions & 1 deletion system/Validation/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ protected function processRules(
if ($passed === false) {
// if the $value is an array, convert it to as string representation
if (is_array($value)) {
$value = '[' . implode(', ', $value) . ']';
$value = $this->isStringList($value)
? '[' . implode(', ', $value) . ']'
: json_encode($value);
} elseif (is_object($value)) {
$value = json_encode($value);
}
Expand All @@ -351,6 +353,32 @@ protected function processRules(
return true;
}

/**
* Is the array a string list `list<string>`?
*/
private function isStringList(array $array): bool
{
$expectedKey = 0;

foreach ($array as $key => $val) {
// Note: also covers PHP array key conversion, e.g. '5' and 5.1 both become 5
if (! is_int($key)) {
return false;
}

if ($key !== $expectedKey) {
return false;
}
$expectedKey++;

if (! is_string($val)) {
return false;
}
}

return true;
}

/**
* Takes a Request object and grabs the input data to use from its
* array values.
Expand Down
5 changes: 5 additions & 0 deletions tests/_support/Validation/TestRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ public function check_object_rule(object $value, ?string $fields, array $data =

return $find;
}

public function array_count($value, $count): bool
{
return is_array($value) && count($value) === (int) $count;
}
}
36 changes: 36 additions & 0 deletions tests/system/Validation/ValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,42 @@ public function testJsonInput(): void
unset($_SERVER['CONTENT_TYPE']);
}

/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/6466
*/
public function testJsonInputObjectArray(): void
{
$json = <<<'EOL'
{
"p": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
]
}
EOL;

$_SERVER['CONTENT_TYPE'] = 'application/json';

$config = new App();
$config->baseURL = 'http://example.com/';

$request = new IncomingRequest($config, new URI(), $json, new UserAgent());

$rules = [
'p' => 'required|array_count[2]',
];
$validated = $this->validation
->withRequest($request->withMethod('patch'))
->setRules($rules)
->run();

$this->assertFalse($validated);
$this->assertSame(['p' => 'Validation.array_count'], $this->validation->getErrors());

unset($_SERVER['CONTENT_TYPE']);
}

public function testHasRule(): void
{
$this->validation->setRuleGroup('groupA');
Expand Down

0 comments on commit 8760a49

Please sign in to comment.