Page MenuHomePhabricator

D19781.diff
No OneTemporary

D19781.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -372,6 +372,7 @@
'PhutilPygmentsSyntaxHighlighter' => 'markup/syntax/highlighter/PhutilPygmentsSyntaxHighlighter.php',
'PhutilPythonFragmentLexer' => 'lexer/PhutilPythonFragmentLexer.php',
'PhutilQsprintfInterface' => 'xsprintf/PhutilQsprintfInterface.php',
+ 'PhutilQueryString' => 'xsprintf/PhutilQueryString.php',
'PhutilQueryStringParser' => 'parser/PhutilQueryStringParser.php',
'PhutilQueryStringParserTestCase' => 'parser/__tests__/PhutilQueryStringParserTestCase.php',
'PhutilRainbowSyntaxHighlighter' => 'markup/syntax/highlighter/PhutilRainbowSyntaxHighlighter.php',
@@ -1023,6 +1024,7 @@
'PhutilPygmentizeParserTestCase' => 'PhutilTestCase',
'PhutilPygmentsSyntaxHighlighter' => 'Phobject',
'PhutilPythonFragmentLexer' => 'PhutilLexer',
+ 'PhutilQueryString' => 'Phobject',
'PhutilQueryStringParser' => 'Phobject',
'PhutilQueryStringParserTestCase' => 'PhutilTestCase',
'PhutilRainbowSyntaxHighlighter' => 'Phobject',
diff --git a/src/xsprintf/PhutilQueryString.php b/src/xsprintf/PhutilQueryString.php
new file mode 100644
--- /dev/null
+++ b/src/xsprintf/PhutilQueryString.php
@@ -0,0 +1,39 @@
+<?php
+
+final class PhutilQueryString extends Phobject {
+
+ private $escaper;
+ private $argv;
+
+ public function __construct(PhutilQsprintfInterface $escaper, array $argv) {
+ $this->escaper = $escaper;
+ $this->argv = $argv;
+
+ // This makes sure we throw immediately if there are errors in the
+ // parameters.
+ $this->getMaskedString();
+ }
+
+ public function __toString() {
+ return $this->getMaskedString();
+ }
+
+ public function getUnmaskedString() {
+ return $this->renderString(true);
+ }
+
+ public function getMaskedString() {
+ return $this->renderString(false);
+ }
+
+ private function renderString($unmasked) {
+ return xsprintf(
+ 'xsprintf_query',
+ array(
+ 'escaper' => $this->escaper,
+ 'unmasked' => $unmasked,
+ ),
+ $this->argv);
+ }
+
+}
diff --git a/src/xsprintf/qsprintf.php b/src/xsprintf/qsprintf.php
--- a/src/xsprintf/qsprintf.php
+++ b/src/xsprintf/qsprintf.php
@@ -61,12 +61,12 @@
function qsprintf(PhutilQsprintfInterface $escaper, $pattern /* , ... */) {
$args = func_get_args();
array_shift($args);
- return xsprintf('xsprintf_query', $escaper, $args);
+ return new PhutilQueryString($escaper, $args);
}
function vqsprintf(PhutilQsprintfInterface $escaper, $pattern, array $argv) {
array_unshift($argv, $pattern);
- return xsprintf('xsprintf_query', $escaper, $argv);
+ return new PhutilQueryString($escaper, $argv);
}
/**
@@ -74,12 +74,19 @@
* @{function:qsprintf}.
*/
function xsprintf_query($userdata, &$pattern, &$pos, &$value, &$length) {
- $type = $pattern[$pos];
- $escaper = $userdata;
- $next = (strlen($pattern) > $pos + 1) ? $pattern[$pos + 1] : null;
+ $type = $pattern[$pos];
+ if (is_array($userdata)) {
+ $escaper = $userdata['escaper'];
+ $unmasked = $userdata['unmasked'];
+ } else {
+ $escaper = $userdata;
+ $unmasked = false;
+ }
+
+ $next = (strlen($pattern) > $pos + 1) ? $pattern[$pos + 1] : null;
$nullable = false;
- $done = false;
+ $done = false;
$prefix = '';
@@ -190,6 +197,9 @@
break;
case 'Q': // Query Fragment
+ if ($value instanceof PhutilQueryString) {
+ $value = $value->getUnmaskedString();
+ }
$type = 's';
break;
@@ -287,6 +297,24 @@
function qsprintf_check_scalar_type($value, $type, $query) {
switch ($type) {
case 'Q':
+ // TODO: See T13217. Remove this eventually.
+ if (is_string($value)) {
+ phlog(
+ pht(
+ 'UNSAFE: Raw string ("%s") passed to query ("%s") for "%%Q" '.
+ 'conversion. %%Q should be passed a query string.',
+ $value,
+ $query));
+ break;
+ }
+
+ if (!($value instanceof PhutilQueryString)) {
+ throw new AphrontParameterQueryException(
+ $query,
+ pht('Expected a PhutilQueryString for %%%s conversion.', $type));
+ }
+ break;
+
case 'LC':
case 'T':
case 'C':
diff --git a/src/xsprintf/queryfx.php b/src/xsprintf/queryfx.php
--- a/src/xsprintf/queryfx.php
+++ b/src/xsprintf/queryfx.php
@@ -4,6 +4,8 @@
$argv = func_get_args();
$query = call_user_func_array('qsprintf', $argv);
+ $query = $query->getUnmaskedString();
+
$conn->setLastActiveEpoch(time());
$conn->executeRawQuery($query);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 31, 10:10 AM (12 h, 6 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7078139
Default Alt Text
D19781.diff (4 KB)

Event Timeline