diff --git a/.editorconfig b/.editorconfig --- a/.editorconfig +++ b/.editorconfig @@ -10,44 +10,44 @@ max_line_length = 80 [src/lint/linter/**/__tests__/**.lint-test] -indent_style = -end_of_line = -max_line_length = +indent_style = unset +end_of_line = unset +max_line_length = unset trim_trailing_whitespace = false [src/parser/__tests__/bundle/*] insert_final_newline = false [src/parser/__tests__/diff/*.{git,hg,rcs,svn,u}diff] -indent_style = +indent_style = unset trim_trailing_whitespace = false insert_final_newline = false -max_line_length = +max_line_length = unset [src/parser/__tests__/patches/*.{git,hg,rcs,svn,u}patch] -indent_style = +indent_style = unset trim_trailing_whitespace = false -max_line_length = +max_line_length = unset [src/parser/__tests__/patches/*.gitpatch] -end_of_line = +end_of_line = unset [src/parser/__tests__/**/*.txt] -max_line_length = +max_line_length = unset [src/repository/parser/__tests__/mercurial/*.txt] trim_trailing_whitespace = false insert_final_newline = false -max_line_length = +max_line_length = unset [src/unit/parser/__tests__/testresults/go.*] -indent_style = +indent_style = unset [src/unit/parser/__tests__/testresults/xunit.*] -max_line_length = +max_line_length = unset [externals/**] -indent_style = -indent_size = +indent_style = unset +indent_size = unset trim_trailing_whitespace = false insert_final_newline = false diff --git a/src/error/PhutilOpaqueEnvelope.php b/src/error/PhutilOpaqueEnvelope.php --- a/src/error/PhutilOpaqueEnvelope.php +++ b/src/error/PhutilOpaqueEnvelope.php @@ -60,6 +60,9 @@ */ private function mask($string, $noise) { $result = ''; + if ($string === null) { + return $result; + } for ($ii = 0; $ii < strlen($string); $ii++) { $s = $string[$ii]; $n = $noise[$ii % strlen($noise)]; diff --git a/src/future/http/status/HTTPFutureHTTPResponseStatus.php b/src/future/http/status/HTTPFutureHTTPResponseStatus.php --- a/src/future/http/status/HTTPFutureHTTPResponseStatus.php +++ b/src/future/http/status/HTTPFutureHTTPResponseStatus.php @@ -13,7 +13,7 @@ // NOTE: Avoiding PhutilUTF8StringTruncator here because this isn't lazy // and responses may be large. - if (strlen($body) > 512) { + if ($body !== null && strlen($body) > 512) { $excerpt = substr($body, 0, 512).'...'; } else { $excerpt = $body; @@ -21,7 +21,8 @@ $content_type = BaseHTTPFuture::getHeader($headers, 'Content-Type'); $match = null; - if (preg_match('/;\s*charset=([^;]+)/', $content_type, $match)) { + if ($content_type !== null && strlen($content_type) + && preg_match('/;\s*charset=([^;]+)/', $content_type, $match)) { $encoding = trim($match[1], "\"'"); try { $excerpt = phutil_utf8_convert($excerpt, 'UTF-8', $encoding); diff --git a/src/future/oauth/PhutilOAuth1Future.php b/src/future/oauth/PhutilOAuth1Future.php --- a/src/future/oauth/PhutilOAuth1Future.php +++ b/src/future/oauth/PhutilOAuth1Future.php @@ -229,7 +229,9 @@ $consumer_secret = $this->consumerSecret->openEnvelope(); } - $key = urlencode($consumer_secret).'&'.urlencode($this->tokenSecret); + $consumer_secret = coalesce($consumer_secret, ''); + $token_secret = coalesce($this->tokenSecret, ''); + $key = urlencode($consumer_secret).'&'.urlencode($token_secret); switch ($this->signatureMethod) { case 'HMAC-SHA1': diff --git a/src/parser/ArcanistBundle.php b/src/parser/ArcanistBundle.php --- a/src/parser/ArcanistBundle.php +++ b/src/parser/ArcanistBundle.php @@ -762,26 +762,25 @@ $old_data = $this->getBlob($old_phid, $name); } - $old_length = strlen($old_data); - - // Here, and below, the binary will be emitted with base85 encoding. This - // encoding encodes each 4 bytes of input in 5 bytes of output, so we may - // need up to 5/4ths as many bytes to represent it. - - // We reserve space up front because base85 encoding isn't super cheap. If - // the blob is enormous, we'd rather just bail out now before doing a ton - // of work and then throwing it away anyway. - - // However, the data is compressed before it is emitted so we may actually - // end up using fewer bytes. For now, the allocator just assumes the worst - // case since it isn't important to be precise, but we could do a more - // exact job of this. - $this->reserveBytes($old_length * 5 / 4); - if ($old_data === null) { + $old_length = 0; $old_data = ''; $old_sha1 = str_repeat('0', 40); } else { + // Here, and below, the binary will be emitted with base85 encoding. This + // encoding encodes each 4 bytes of input in 5 bytes of output, so we may + // need up to 5/4ths as many bytes to represent it. + + // We reserve space up front because base85 encoding isn't super cheap. If + // the blob is enormous, we'd rather just bail out now before doing a ton + // of work and then throwing it away anyway. + + // However, the data is compressed before it is emitted so we may actually + // end up using fewer bytes. For now, the allocator just assumes the worst + // case since it isn't important to be precise, but we could do a more + // exact job of this. + $old_length = strlen($old_data); + $this->reserveBytes($old_length * 5 / 4); $old_sha1 = sha1("blob {$old_length}\0{$old_data}"); } @@ -795,13 +794,13 @@ $new_data = $this->getBlob($new_phid, $name); } - $new_length = strlen($new_data); - $this->reserveBytes($new_length * 5 / 4); - if ($new_data === null) { + $new_length = 0; $new_data = ''; $new_sha1 = str_repeat('0', 40); } else { + $new_length = strlen($new_data); + $this->reserveBytes($new_length * 5 / 4); $new_sha1 = sha1("blob {$new_length}\0{$new_data}"); } diff --git a/src/parser/ArcanistDiffParser.php b/src/parser/ArcanistDiffParser.php --- a/src/parser/ArcanistDiffParser.php +++ b/src/parser/ArcanistDiffParser.php @@ -263,7 +263,9 @@ // searching for "diff -r" or "diff --git" in the text. $this->saveLine(); $line = $this->nextLineThatLooksLikeDiffStart(); - if (!$this->tryMatchHeader($patterns, $line, $match)) { + if ($line === null + || !$this->tryMatchHeader($patterns, $line, $match)) { + // Restore line before guessing to display correct error. $this->restoreLine(); $failed_parse = true; diff --git a/src/parser/xhpast/__tests__/PHPASTParserTestCase.php b/src/parser/xhpast/__tests__/PHPASTParserTestCase.php --- a/src/parser/xhpast/__tests__/PHPASTParserTestCase.php +++ b/src/parser/xhpast/__tests__/PHPASTParserTestCase.php @@ -82,7 +82,7 @@ case 'pass': $this->assertEqual(0, $err, pht('Exit code for "%s".', $name)); - if (!strlen($expect)) { + if ($expect === null || !strlen($expect)) { // If there's no "expect" data in the test case, that's OK. break; } diff --git a/src/parser/xhpast/api/XHPASTNode.php b/src/parser/xhpast/api/XHPASTNode.php --- a/src/parser/xhpast/api/XHPASTNode.php +++ b/src/parser/xhpast/api/XHPASTNode.php @@ -239,7 +239,7 @@ $esc = false; switch ($c) { case 'x': - $u = isset($value[$ii + 1]) ? $value[$ii + 1] : null; + $u = isset($value[$ii + 1]) ? $value[$ii + 1] : ''; if (!preg_match('/^[a-f0-9]/i', $u)) { // PHP treats \x followed by anything which is not a hex digit // as a literal \x. diff --git a/src/utils/utils.php b/src/utils/utils.php --- a/src/utils/utils.php +++ b/src/utils/utils.php @@ -1305,8 +1305,12 @@ * @return mixed Decoded list/dictionary. */ function phutil_json_decode($string) { - $result = @json_decode($string, true); + if ($string === null) { + throw new PhutilJSONParserException(pht('Value "null" is not a valid JSON '. + 'encoded object.')); + } + $result = @json_decode($string, true); if (!is_array($result)) { // Failed to decode the JSON. Try to use @{class:PhutilJSONParser} instead. // This will probably fail, but will throw a useful exception.