From 143df3117d3009db25c3bcee69dec0ada2b60da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Auswo=CC=88ger?= Date: Mon, 25 Sep 2017 21:29:57 +0200 Subject: [PATCH] Escape reserved words in database queries --- src/Resources/contao/drivers/DC_Table.php | 6 ++-- .../contao/library/Contao/Database.php | 30 +++++++++++++++++++ .../library/Contao/Database/Statement.php | 4 +-- .../library/Contao/Model/QueryBuilder.php | 2 +- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/Resources/contao/drivers/DC_Table.php b/src/Resources/contao/drivers/DC_Table.php index 38374f49dd..1576b4fa0e 100644 --- a/src/Resources/contao/drivers/DC_Table.php +++ b/src/Resources/contao/drivers/DC_Table.php @@ -3143,12 +3143,12 @@ protected function save($varValue) { if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4) { - $this->Database->prepare("UPDATE " . $this->strTable . " SET " . $this->strField . "='' WHERE pid=?") + $this->Database->prepare("UPDATE " . $this->strTable . " SET " . \Database::escapeColumnName($this->strField) . "='' WHERE pid=?") ->execute($this->activeRecord->pid); } else { - $this->Database->execute("UPDATE " . $this->strTable . " SET " . $this->strField . "=''"); + $this->Database->execute("UPDATE " . $this->strTable . " SET " . \Database::escapeColumnName($this->strField) . "=''"); } } @@ -3161,7 +3161,7 @@ protected function save($varValue) $arrValues = $this->values; array_unshift($arrValues, $varValue); - $objUpdateStmt = $this->Database->prepare("UPDATE " . $this->strTable . " SET " . $this->strField . "=? WHERE " . implode(' AND ', $this->procedure)) + $objUpdateStmt = $this->Database->prepare("UPDATE " . $this->strTable . " SET " . \Database::escapeColumnName($this->strField) . "=? WHERE " . implode(' AND ', $this->procedure)) ->execute($arrValues); if ($objUpdateStmt->affectedRows) diff --git a/src/Resources/contao/library/Contao/Database.php b/src/Resources/contao/library/Contao/Database.php index c51ddb6445..f7407160d8 100644 --- a/src/Resources/contao/library/Contao/Database.php +++ b/src/Resources/contao/library/Contao/Database.php @@ -706,6 +706,36 @@ public function getUuid() } + /** + * Escape the column name if it a reserved word + * + * @param string $name + * + * @return string + */ + public static function escapeColumnName($name) + { + if (in_array($name, ['rows'], true)) { + $name = '`'.$name.'`'; + } + + return $name; + } + + + /** + * Escape a list of column names + * + * @param string[] $names + * + * @return string[] + */ + public static function escapeColumnNames(array $names) + { + return array_map([static::class, 'escapeColumnName'], $names); + } + + /** * Execute a query and do not cache the result * diff --git a/src/Resources/contao/library/Contao/Database/Statement.php b/src/Resources/contao/library/Contao/Database/Statement.php index 5f153e0bfa..cdfc4aa97d 100644 --- a/src/Resources/contao/library/Contao/Database/Statement.php +++ b/src/Resources/contao/library/Contao/Database/Statement.php @@ -182,7 +182,7 @@ public function set($arrParams) if (strncasecmp($this->strQuery, 'INSERT', 6) === 0) { $strQuery = sprintf('(%s) VALUES (%s)', - implode(', ', array_keys($arrParams)), + implode(', ', \Database::escapeColumnNames(array_keys($arrParams))), str_replace('%', '%%', implode(', ', array_values($arrParams)))); } @@ -193,7 +193,7 @@ public function set($arrParams) foreach ($arrParams as $k=>$v) { - $arrSet[] = $k . '=' . $v; + $arrSet[] = \Database::escapeColumnName($k) . '=' . $v; } $strQuery = 'SET ' . str_replace('%', '%%', implode(', ', $arrSet)); diff --git a/src/Resources/contao/library/Contao/Model/QueryBuilder.php b/src/Resources/contao/library/Contao/Model/QueryBuilder.php index b0daee852a..d30c4e6970 100644 --- a/src/Resources/contao/library/Contao/Model/QueryBuilder.php +++ b/src/Resources/contao/library/Contao/Model/QueryBuilder.php @@ -68,7 +68,7 @@ public static function find(array $arrOptions) // Where condition if ($arrOptions['column'] !== null) { - $strQuery .= " WHERE " . (is_array($arrOptions['column']) ? implode(" AND ", $arrOptions['column']) : $arrOptions['table'] . '.' . $arrOptions['column'] . "=?"); + $strQuery .= " WHERE " . (is_array($arrOptions['column']) ? implode(" AND ", $arrOptions['column']) : $arrOptions['table'] . '.' . \Database::escapeColumnName($arrOptions['column']) . "=?"); } // Group by