Skip to content

Commit 41e3834

Browse files
authored
Merge pull request #661 from AronNovak/fix/body-max-nesting-depth
Fix: Body serialization should respect max_nesting_depth config
2 parents 9c28cd7 + d7feef8 commit 41e3834

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/DataBuilder.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class DataBuilder implements DataBuilderInterface
5959
protected $captureEmail;
6060
protected $captureUsername;
6161

62+
protected $maxNestingDepth;
63+
6264
/**
6365
* @var Utilities
6466
*/
@@ -99,6 +101,7 @@ public function __construct(array $config)
99101
$this->setCustom($config);
100102
$this->setFingerprint($config);
101103
$this->setTitle($config);
104+
$this->setMaxNestingDepth($config);
102105
$this->setNotifier($config);
103106
$this->setBaseException($config);
104107
$this->setIncludeCodeContext($config);
@@ -129,6 +132,12 @@ protected function setCaptureUsername($config)
129132
$fromConfig = $config['capture_username'] ?? null;
130133
$this->captureUsername = self::$defaults->captureUsername($fromConfig);
131134
}
135+
136+
protected function setMaxNestingDepth($config)
137+
{
138+
$fromConfig = $config['max_nesting_depth'] ?? null;
139+
$this->maxNestingDepth = self::$defaults->maxNestingDepth($fromConfig);
140+
}
132141

133142
protected function setEnvironment($config)
134143
{
@@ -411,7 +420,7 @@ protected function getBody(Throwable|string|Stringable $toLog, array $context):
411420
} else {
412421
$content = $this->getMessage($toLog);
413422
}
414-
return new Body($content, $context, $this->getTelemetry());
423+
return new Body($content, $context, $this->getTelemetry(), $this->maxNestingDepth);
415424
}
416425

417426
public function getErrorTrace(ErrorWrapper $error)

src/Payload/Body.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ class Body implements SerializerInterface
2323
public function __construct(
2424
private ContentInterface $value,
2525
private array $extra = [],
26-
private ?array $telemetry = null
26+
private ?array $telemetry = null,
27+
private int $maxDepth = -1
2728
) {
2829
}
2930

@@ -122,6 +123,10 @@ public function serialize()
122123
$result['telemetry'] = $this->telemetry;
123124
}
124125

125-
return $this->utilities()->serializeForRollbarInternal($result, array('extra'));
126+
if ($this->maxDepth === -1) {
127+
return $this->utilities()->serializeForRollbarInternal($result, array('extra'));
128+
}
129+
$objectHashes = array();
130+
return $this->utilities()->serializeForRollbar($result, array('extra'), $objectHashes, $this->maxDepth);
126131
}
127132
}

tests/BodyTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,37 @@ public function testSerialize(): void
4646
$encoded
4747
);
4848
}
49+
50+
public function testSerializeWithMaxNestingDepth(): void
51+
{
52+
$value = m::mock(ContentInterface::class)
53+
->shouldReceive("serialize")
54+
->andReturn("{CONTENT}")
55+
->shouldReceive("getKey")
56+
->andReturn("content_interface")
57+
->mock();
58+
59+
// Create deeply nested array that would cause memory issues
60+
$deepArray = array('level1' => array('level2' => array('level3' => array('level4' => 'deep_value'))));
61+
62+
// Test without depth limit - should serialize completely
63+
$bodyNoLimit = new Body($value, array('deep' => $deepArray), null, -1);
64+
$resultNoLimit = $bodyNoLimit->serialize();
65+
66+
// Test with depth limit - should truncate deep nesting
67+
$bodyWithLimit = new Body($value, array('deep' => $deepArray), null, 2);
68+
$resultWithLimit = $bodyWithLimit->serialize();
69+
70+
// Verify basic structure exists
71+
$this->assertArrayHasKey('extra', $resultNoLimit);
72+
$this->assertArrayHasKey('extra', $resultWithLimit);
73+
74+
// Without limit should have all nested levels
75+
$this->assertEquals('deep_value', $resultNoLimit['extra']['deep']['level1']['level2']['level3']['level4']);
76+
77+
// With limit should truncate the 'deep' array due to depth constraint
78+
// At depth 2: root -> extra -> deep (gets truncated to empty array)
79+
$this->assertArrayHasKey('deep', $resultWithLimit['extra']);
80+
$this->assertEmpty($resultWithLimit['extra']['deep']); // Truncated due to depth limit
81+
}
4982
}

0 commit comments

Comments
 (0)