Skip to content

Commit def79d1

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into 4.4
Conflicts: system/Debug/Exceptions.php
2 parents 988906c + 48d5ded commit def79d1

5 files changed

Lines changed: 125 additions & 20 deletions

File tree

phpstan-baseline.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -921,11 +921,6 @@
921921
'count' => 1,
922922
'path' => __DIR__ . '/system/Debug/Exceptions.php',
923923
];
924-
$ignoreErrors[] = [
925-
'message' => '#^Method CodeIgniter\\\\Debug\\\\Exceptions\\:\\:maskSensitiveData\\(\\) has no return type specified\\.$#',
926-
'count' => 1,
927-
'path' => __DIR__ . '/system/Debug/Exceptions.php',
928-
];
929924
$ignoreErrors[] = [
930925
'message' => '#^Method CodeIgniter\\\\Debug\\\\Exceptions\\:\\:render\\(\\) has no return type specified\\.$#',
931926
'count' => 1,

system/Debug/Exceptions.php

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ protected function collectVars(Throwable $exception, int $statusCode): array
317317
$trace = $exception->getTrace();
318318

319319
if ($this->config->sensitiveDataInTrace !== []) {
320-
$this->maskSensitiveData($trace, $this->config->sensitiveDataInTrace);
320+
$trace = $this->maskSensitiveData($trace, $this->config->sensitiveDataInTrace);
321321
}
322322

323323
return [
@@ -336,32 +336,53 @@ protected function collectVars(Throwable $exception, int $statusCode): array
336336
*
337337
* @param array|object $trace
338338
*
339+
* @return array|object
340+
*
339341
* @deprecated No longer used. Moved to BaseExceptionHandler.
340342
*/
341-
protected function maskSensitiveData(&$trace, array $keysToMask, string $path = '')
343+
protected function maskSensitiveData($trace, array $keysToMask, string $path = '')
344+
{
345+
foreach ($trace as $i => $line) {
346+
$trace[$i]['args'] = $this->maskData($line['args'], $keysToMask);
347+
}
348+
349+
return $trace;
350+
}
351+
352+
/**
353+
* @param array|object $args
354+
*
355+
* @return array|object
356+
*/
357+
private function maskData($args, array $keysToMask, string $path = '')
342358
{
343359
foreach ($keysToMask as $keyToMask) {
344360
$explode = explode('/', $keyToMask);
345361
$index = end($explode);
346362

347363
if (strpos(strrev($path . '/' . $index), strrev($keyToMask)) === 0) {
348-
if (is_array($trace) && array_key_exists($index, $trace)) {
349-
$trace[$index] = '******************';
350-
} elseif (is_object($trace) && property_exists($trace, $index) && isset($trace->{$index})) {
351-
$trace->{$index} = '******************';
364+
if (is_array($args) && array_key_exists($index, $args)) {
365+
$args[$index] = '******************';
366+
} elseif (
367+
is_object($args) && property_exists($args, $index)
368+
&& isset($args->{$index}) && is_scalar($args->{$index})
369+
) {
370+
$args->{$index} = '******************';
352371
}
353372
}
354373
}
355374

356-
if (is_object($trace)) {
357-
$trace = get_object_vars($trace);
358-
}
359-
360-
if (is_array($trace)) {
361-
foreach ($trace as $pathKey => $subarray) {
362-
$this->maskSensitiveData($subarray, $keysToMask, $path . '/' . $pathKey);
375+
if (is_array($args)) {
376+
foreach ($args as $pathKey => $subarray) {
377+
$args[$pathKey] = $this->maskData($subarray, $keysToMask, $path . '/' . $pathKey);
378+
}
379+
} elseif (is_object($args)) {
380+
foreach ($args as $pathKey => $subarray) {
381+
$args->{$pathKey} = $this->maskData($subarray, $keysToMask, $path . '/' . $pathKey);
363382
}
364383
}
384+
385+
return $args;
365386
}
366387

367388
/**

tests/system/Commands/RoutesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ protected function tearDown(): void
3939

4040
protected function getBuffer()
4141
{
42-
return $this->getStreamFilterBuffer();
42+
return str_replace(PHP_EOL, "\n", $this->getStreamFilterBuffer());
4343
}
4444

4545
private function getCleanRoutes(): RouteCollection

tests/system/Commands/Utilities/NamespacesTest.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,16 @@ protected function tearDown(): void
3535
$this->resetServices();
3636
}
3737

38+
/**
39+
* @see https://regex101.com/r/l3lHfR/1
40+
*/
3841
protected function getBuffer()
3942
{
40-
return $this->getStreamFilterBuffer();
43+
return preg_replace_callback('/(\|\s*[^|]+\s*\|\s*)(.*?)(\s*\|\s*[^|]+\s*\|)/', static function (array $matches) {
44+
$matches[2] = str_replace(DIRECTORY_SEPARATOR, '/', $matches[2]);
45+
46+
return $matches[1] . $matches[2] . $matches[3];
47+
}, str_replace(PHP_EOL, "\n", $this->getStreamFilterBuffer()));
4148
}
4249

4350
public function testNamespacesCommandCodeIgniterOnly()

tests/system/Debug/ExceptionsTest.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace CodeIgniter\Debug;
1313

14+
use App\Controllers\Home;
1415
use CodeIgniter\Database\Exceptions\DatabaseException;
1516
use CodeIgniter\Entity\Exceptions\CastException;
1617
use CodeIgniter\Exceptions\ConfigException;
@@ -147,4 +148,85 @@ public function testRenderBacktrace(): void
147148
);
148149
}
149150
}
151+
152+
public function testMaskSensitiveData(): void
153+
{
154+
$maskSensitiveData = $this->getPrivateMethodInvoker($this->exception, 'maskSensitiveData');
155+
156+
$trace = [
157+
0 => [
158+
'file' => '/var/www/CodeIgniter4/app/Controllers/Home.php',
159+
'line' => 15,
160+
'function' => 'f',
161+
'class' => Home::class,
162+
'type' => '->',
163+
'args' => [
164+
0 => (object) [
165+
'password' => 'secret1',
166+
],
167+
1 => (object) [
168+
'default' => [
169+
'password' => 'secret2',
170+
],
171+
],
172+
2 => [
173+
'password' => 'secret3',
174+
],
175+
3 => [
176+
'default' => ['password' => 'secret4'],
177+
],
178+
],
179+
],
180+
1 => [
181+
'file' => '/var/www/CodeIgniter4/system/CodeIgniter.php',
182+
'line' => 932,
183+
'function' => 'index',
184+
'class' => Home::class,
185+
'type' => '->',
186+
'args' => [
187+
],
188+
],
189+
];
190+
$keysToMask = ['password'];
191+
$path = '';
192+
193+
$newTrace = $maskSensitiveData($trace, $keysToMask, $path);
194+
195+
$this->assertSame(['password' => '******************'], (array) $newTrace[0]['args'][0]);
196+
$this->assertSame(['password' => '******************'], $newTrace[0]['args'][1]->default);
197+
$this->assertSame(['password' => '******************'], $newTrace[0]['args'][2]);
198+
$this->assertSame(['password' => '******************'], $newTrace[0]['args'][3]['default']);
199+
}
200+
201+
public function testMaskSensitiveDataTraceDataKey(): void
202+
{
203+
$maskSensitiveData = $this->getPrivateMethodInvoker($this->exception, 'maskSensitiveData');
204+
205+
$trace = [
206+
0 => [
207+
'file' => '/var/www/CodeIgniter4/app/Controllers/Home.php',
208+
'line' => 15,
209+
'function' => 'f',
210+
'class' => Home::class,
211+
'type' => '->',
212+
'args' => [
213+
],
214+
],
215+
1 => [
216+
'file' => '/var/www/CodeIgniter4/system/CodeIgniter.php',
217+
'line' => 932,
218+
'function' => 'index',
219+
'class' => Home::class,
220+
'type' => '->',
221+
'args' => [
222+
],
223+
],
224+
];
225+
$keysToMask = ['file'];
226+
$path = '';
227+
228+
$newTrace = $maskSensitiveData($trace, $keysToMask, $path);
229+
230+
$this->assertSame('/var/www/CodeIgniter4/app/Controllers/Home.php', $newTrace[0]['file']);
231+
}
150232
}

0 commit comments

Comments
 (0)