From d7590a6190cba237455b3e2b254b6bf0b8386855 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Tue, 16 Feb 2021 10:23:59 +0000 Subject: [PATCH] Add expression taint source and sanitizer Signed-off-by: Lukas Reschke --- .../DB/QueryBuilder/IExpressionBuilder.php | 75 ++++++++++++++++++ lib/public/DB/QueryBuilder/IQueryBuilder.php | 77 +++++++++++++++++++ lib/public/IDBConnection.php | 10 +++ 3 files changed, 162 insertions(+) diff --git a/lib/public/DB/QueryBuilder/IExpressionBuilder.php b/lib/public/DB/QueryBuilder/IExpressionBuilder.php index c62221305d5..aebc4bde9cd 100644 --- a/lib/public/DB/QueryBuilder/IExpressionBuilder.php +++ b/lib/public/DB/QueryBuilder/IExpressionBuilder.php @@ -32,6 +32,8 @@ use Doctrine\DBAL\Query\Expression\ExpressionBuilder; /** * This class provides a wrapper around Doctrine's ExpressionBuilder * @since 8.2.0 + * + * @psalm-taint-specialize */ interface IExpressionBuilder { /** @@ -73,6 +75,8 @@ interface IExpressionBuilder { * * @return \OCP\DB\QueryBuilder\ICompositeExpression * @since 8.2.0 + * + * @psalm-taint-sink sql $x */ public function andX(...$x); @@ -90,6 +94,8 @@ interface IExpressionBuilder { * * @return \OCP\DB\QueryBuilder\ICompositeExpression * @since 8.2.0 + * + * @psalm-taint-sink sql $x */ public function orX(...$x); @@ -104,6 +110,11 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $operator + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function comparison($x, $operator, $y, $type = null); @@ -124,6 +135,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function eq($x, $y, $type = null); @@ -143,6 +158,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function neq($x, $y, $type = null); @@ -162,6 +181,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function lt($x, $y, $type = null); @@ -181,6 +204,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function lte($x, $y, $type = null); @@ -200,6 +227,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function gt($x, $y, $type = null); @@ -219,6 +250,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function gte($x, $y, $type = null); @@ -229,6 +264,8 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 + * + * @psalm-taint-sink sql $x */ public function isNull($x); @@ -239,6 +276,8 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 + * + * @psalm-taint-sink sql $x */ public function isNotNull($x); @@ -252,6 +291,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function like($x, $y, $type = null); @@ -265,6 +308,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function notLike($x, $y, $type = null); @@ -278,6 +325,10 @@ interface IExpressionBuilder { * * @return string * @since 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function iLike($x, $y, $type = null); @@ -291,6 +342,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function in($x, $y, $type = null); @@ -304,6 +359,10 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ public function notIn($x, $y, $type = null); @@ -313,6 +372,8 @@ interface IExpressionBuilder { * @param string $x The field in string format to be inspected by the comparison. * @return string * @since 13.0.0 + * + * @psalm-taint-sink sql $x */ public function emptyString($x); @@ -322,6 +383,8 @@ interface IExpressionBuilder { * @param string $x The field in string format to be inspected by the comparison. * @return string * @since 13.0.0 + * + * @psalm-taint-sink sql $x */ public function nonEmptyString($x); @@ -333,6 +396,9 @@ interface IExpressionBuilder { * @param int $y Bitmap that must be set * @return IQueryFunction * @since 12.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y */ public function bitwiseAnd($x, $y); @@ -343,6 +409,9 @@ interface IExpressionBuilder { * @param int $y Bitmap that must be set * @return IQueryFunction * @since 12.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y */ public function bitwiseOr($x, $y); @@ -354,6 +423,9 @@ interface IExpressionBuilder { * * @return string * @since 8.2.0 + * + * @psalm-taint-sink sql $input + * @psalm-taint-sink sql $type */ public function literal($input, $type = null); @@ -364,6 +436,9 @@ interface IExpressionBuilder { * @param mixed $type One of IQueryBuilder::PARAM_* * @return string * @since 9.0.0 + * + * @psalm-taint-sink sql $column + * @psalm-taint-sink sql $type */ public function castColumn($column, $type); } diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php index 24de7b4ce60..e63df8a9024 100644 --- a/lib/public/DB/QueryBuilder/IQueryBuilder.php +++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php @@ -35,6 +35,8 @@ use OCP\DB\IResult; /** * This class provides a wrapper around Doctrine's QueryBuilder * @since 8.2.0 + * + * @psalm-taint-specialize */ interface IQueryBuilder { @@ -306,6 +308,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $selects */ public function select(...$selects); @@ -324,6 +328,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.1 + * + * @psalm-taint-sink sql $select + * @psalm-taint-sink sql $alias */ public function selectAlias($select, $alias); @@ -340,6 +347,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 9.0.0 + * + * @psalm-taint-sink sql $select */ public function selectDistinct($select); @@ -358,6 +367,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $select */ public function addSelect(...$select); @@ -377,6 +388,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $delete */ public function delete($delete = null, $alias = null); @@ -396,6 +409,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $update */ public function update($update = null, $alias = null); @@ -418,6 +433,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $insert */ public function insert($insert = null); @@ -436,6 +453,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $from */ public function from($from, $alias = null); @@ -456,6 +475,11 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function join($fromAlias, $join, $alias, $condition = null); @@ -476,6 +500,11 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function innerJoin($fromAlias, $join, $alias, $condition = null); @@ -496,6 +525,11 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function leftJoin($fromAlias, $join, $alias, $condition = null); @@ -516,6 +550,11 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function rightJoin($fromAlias, $join, $alias, $condition = null); @@ -534,6 +573,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $key + * @psalm-taint-sink sql $value */ public function set($key, $value); @@ -563,6 +605,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $predicates */ public function where(...$predicates); @@ -584,6 +628,8 @@ interface IQueryBuilder { * * @see where() * @since 8.2.0 + * + * @psalm-taint-sink sql $where */ public function andWhere(...$where); @@ -605,6 +651,8 @@ interface IQueryBuilder { * * @see where() * @since 8.2.0 + * + * @psalm-taint-sink sql $where */ public function orWhere(...$where); @@ -623,6 +671,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $groupBys */ public function groupBy(...$groupBys); @@ -641,6 +691,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $groupby */ public function addGroupBy(...$groupBy); @@ -663,6 +715,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $column + * @psalm-taint-sink sql $value */ public function setValue($column, $value); @@ -685,6 +740,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $values */ public function values(array $values); @@ -696,6 +753,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $having */ public function having(...$having); @@ -707,6 +766,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $andHaving */ public function andHaving(...$having); @@ -718,6 +779,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $having */ public function orHaving(...$having); @@ -730,6 +793,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $sort + * @psalm-taint-sink sql $order */ public function orderBy($sort, $order = null); @@ -741,6 +807,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $sort + * @psalm-taint-sink sql $order */ public function addOrderBy($sort, $order = null); @@ -811,6 +880,8 @@ interface IQueryBuilder { * * @return IParameter * @since 8.2.0 + * + * @psalm-taint-escape sql */ public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null); @@ -836,6 +907,8 @@ interface IQueryBuilder { * * @return IParameter * @since 8.2.0 + * + * @psalm-taint-escape sql */ public function createPositionalParameter($value, $type = self::PARAM_STR); @@ -855,6 +928,8 @@ interface IQueryBuilder { * * @return IParameter * @since 8.2.0 + * + * @psalm-taint-escape sql */ public function createParameter($name); @@ -881,6 +956,8 @@ interface IQueryBuilder { * * @return IQueryFunction * @since 8.2.0 + * + * @psalm-taint-sink sql */ public function createFunction($call); diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index 943ad1b8601..3d2d83aa828 100644 --- a/lib/public/IDBConnection.php +++ b/lib/public/IDBConnection.php @@ -97,6 +97,8 @@ interface IDBConnection { * @return IPreparedStatement The prepared statement. * @since 6.0.0 * @throws Exception since 21.0.0 + * + * @psalm-taint-sink sql $sql */ public function prepare($sql, $limit = null, $offset = null): IPreparedStatement; @@ -112,6 +114,8 @@ interface IDBConnection { * @return IResult The executed statement. * @since 8.0.0 * @throws Exception since 21.0.0 + * + * @psalm-taint-sink sql $sql */ public function executeQuery(string $sql, array $params = [], $types = []): IResult; @@ -129,6 +133,8 @@ interface IDBConnection { * @throws Exception since 21.0.0 * * @deprecated 21.0.0 use executeStatement + * + * @psalm-taint-sink sql $sql */ public function executeUpdate(string $sql, array $params = [], array $types = []): int; @@ -144,6 +150,8 @@ interface IDBConnection { * @return int The number of affected rows. * @since 21.0.0 * @throws Exception since 21.0.0 + * + * @psalm-taint-sink sql $sql */ public function executeStatement($sql, array $params = [], array $types = []): int; @@ -318,6 +326,8 @@ interface IDBConnection { * @param string $table table name without the prefix * @throws Exception since 21.0.0 * @since 8.0.0 + * + * @psalm-taint-sink sql $table */ public function dropTable(string $table): void; -- 2.39.5