Skip to content

Commit

Permalink
Release v3.29.1
Browse files Browse the repository at this point in the history
  • Loading branch information
imjoehaines authored May 10, 2023
2 parents 35f0f4c + 18b7a60 commit 7fff851
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Changelog
=========

## 3.29.1 (2023-05-10)

### Fixes

* Avoid deprecated `utf8_encode` function
[gabrielrbarbosa](https://github.com/gabrielrbarbosa)
[#661](https://github.com/bugsnag/bugsnag-php/pull/661)
[#662](https://github.com/bugsnag/bugsnag-php/pull/662)

## 3.29.0 (2022-10-19)

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Configuration implements FeatureDataStore
*/
protected $notifier = [
'name' => 'Bugsnag PHP (Official)',
'version' => '3.29.0',
'version' => '3.29.1',
'url' => 'https://bugsnag.com',
];

Expand Down
16 changes: 14 additions & 2 deletions src/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ class HttpClient
*/
protected $queue = [];

/**
* Flags to pass to 'json_encode'.
*
* @var int
*/
private $jsonEncodeFlags = 0;

/**
* The maximum payload size. A whole megabyte (1024 * 1024).
*
Expand Down Expand Up @@ -59,6 +66,11 @@ public function __construct(Configuration $config, ClientInterface $guzzle)
{
$this->config = $config;
$this->guzzle = $guzzle;

// substitute invalid UTF-8 characters when possible (PHP 7.2+)
if (defined('JSON_INVALID_UTF8_SUBSTITUTE')) {
$this->jsonEncodeFlags |= JSON_INVALID_UTF8_SUBSTITUTE;
}
}

/**
Expand Down Expand Up @@ -347,15 +359,15 @@ protected function deliverEvents($uri, array $data)
*/
protected function normalize(array $data)
{
$body = json_encode($data);
$body = json_encode($data, $this->jsonEncodeFlags);

if ($this->length($body) <= static::MAX_SIZE) {
return $body;
}

unset($data['events'][0]['metaData']);

$body = json_encode($data);
$body = json_encode($data, $this->jsonEncodeFlags);

if ($this->length($body) > static::MAX_SIZE) {
throw new RuntimeException('Payload too large');
Expand Down
20 changes: 19 additions & 1 deletion src/Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,25 @@ protected function cleanupObj($obj, $isMetaData)
}

if (is_string($obj)) {
return (function_exists('mb_detect_encoding') && !mb_detect_encoding($obj, 'UTF-8', true)) ? utf8_encode($obj) : $obj;
// on PHP 7.2+ we can use the 'JSON_INVALID_UTF8_SUBSTITUTE' flag to
// substitute invalid UTF-8 characters when encoding so can return
// strings as-is and let PHP handle invalid UTF-8
// note: we check PHP 7.2+ specifically rather than if the flag
// exists because some code defines the flag as '0' when it doesn't
// exist to avoid having to check for it existing. This completely
// breaks the flag as it will not function, so we can't know if the
// flag can be used just from it being defined
if (version_compare(PHP_VERSION, '7.2', '>=')) {
return $obj;
}

// if we have the mbstring extension available, use that to detect
// encodings and handle conversions to UTF-8
if (function_exists('mb_check_encoding') && !mb_check_encoding($obj, 'UTF-8')) {
return mb_convert_encoding($obj, 'UTF-8', mb_list_encodings());
}

return $obj;
}

if (is_object($obj)) {
Expand Down
37 changes: 37 additions & 0 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1412,4 +1412,41 @@ function ($options) use ($called) {

$this->client->flush();
}

public function testCanHandleInvalidUtf8InMetadata()
{
if (version_compare(PHP_VERSION, '7.2', '>=')) {
// U+FFFD (REPLACEMENT CHARACTER)
$expectedReplacement = "\xef\xbf\xbd";
} else {
$expectedReplacement = '';
}

$this->expectGuzzlePostWithCallback(
$this->client->getNotifyEndpoint(),
function ($options) use ($expectedReplacement) {
$payload = $this->getPayloadFromGuzzleOptions($options);

$expected = [
'invalid UTF-8' => [
'c0 is not valid as the first byte' => $expectedReplacement.'AAA',
],
];

$this->assertSame($expected, $payload['events'][0]['metaData']);

return true;
}
);

$this->client->notifyException(new Exception('Something broke'), function ($report) {
$report->setMetaData([
'invalid UTF-8' => [
'c0 is not valid as the first byte' => "\xc0AAA",
],
]);
});

$this->client->flush();
}
}

0 comments on commit 7fff851

Please sign in to comment.