summaryrefslogtreecommitdiff
path: root/includes/database
diff options
context:
space:
mode:
Diffstat (limited to 'includes/database')
-rw-r--r--includes/database/database.inc60
-rw-r--r--includes/database/log.inc1
-rw-r--r--includes/database/mysql/database.inc1
-rw-r--r--includes/database/mysql/install.inc1
-rw-r--r--includes/database/mysql/query.inc9
-rw-r--r--includes/database/mysql/schema.inc1
-rw-r--r--includes/database/pgsql/database.inc10
-rw-r--r--includes/database/pgsql/install.inc1
-rw-r--r--includes/database/pgsql/query.inc5
-rw-r--r--includes/database/pgsql/schema.inc9
-rw-r--r--includes/database/pgsql/select.inc1
-rw-r--r--includes/database/prefetch.inc1
-rw-r--r--includes/database/query.inc23
-rw-r--r--includes/database/schema.inc1
-rw-r--r--includes/database/select.inc6
-rw-r--r--includes/database/sqlite/database.inc1
-rw-r--r--includes/database/sqlite/install.inc1
-rw-r--r--includes/database/sqlite/query.inc11
-rw-r--r--includes/database/sqlite/schema.inc1
-rw-r--r--includes/database/sqlite/select.inc1
20 files changed, 99 insertions, 46 deletions
diff --git a/includes/database/database.inc b/includes/database/database.inc
index b384afe3a..4cc1a33d7 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
@@ -321,7 +320,7 @@ abstract class DatabaseConnection extends PDO {
* PDO::FETCH_OBJ, PDO::FETCH_NUM, or a string representing the name of a
* class. If a string is specified, each record will be fetched into a new
* object of that class. The behavior of all other values is defined by PDO.
- * See http://www.php.net/PDOStatement-fetch
+ * See http://php.net/manual/pdostatement.fetch.php
* - return: Depending on the type of query, different return values may be
* meaningful. This directive instructs the system which type of return
* value is desired. The system will generally set the correct value
@@ -542,6 +541,63 @@ abstract class DatabaseConnection extends PDO {
}
/**
+ * Flatten an array of query comments into a single comment string.
+ *
+ * The comment string will be sanitized to avoid SQL injection attacks.
+ *
+ * @param $comments
+ * An array of query comment strings.
+ *
+ * @return
+ * A sanitized comment string.
+ */
+ public function makeComment($comments) {
+ if (empty($comments))
+ return '';
+
+ // Flatten the array of comments.
+ $comment = implode('; ', $comments);
+
+ // Sanitize the comment string so as to avoid SQL injection attacks.
+ return '/* ' . $this->filterComment($comment) . ' */ ';
+ }
+
+ /**
+ * Sanitize a query comment string.
+ *
+ * Ensure a query comment does not include strings such as "* /" that might
+ * terminate the comment early. This avoids SQL injection attacks via the
+ * query comment. The comment strings in this example are separated by a
+ * space to avoid PHP parse errors.
+ *
+ * For example, the comment:
+ * @code
+ * db_update('example')
+ * ->condition('id', $id)
+ * ->fields(array('field2' => 10))
+ * ->comment('Exploit * / DROP TABLE node; --')
+ * ->execute()
+ * @endcode
+ *
+ * Would result in the following SQL statement being generated:
+ * @code
+ * "/ * Exploit * / DROP TABLE node; -- * / UPDATE example SET field2=..."
+ * @endcode
+ *
+ * Unless the comment is sanitised first, the SQL server would drop the
+ * node table and ignore the rest of the SQL statement.
+ *
+ * @param $comment
+ * A query comment string.
+ *
+ * @return
+ * A sanitized version of the query comment string.
+ */
+ protected function filterComment($comment = '') {
+ return preg_replace('/(\/\*\s*)|(\s*\*\/)/', '', $comment);
+ }
+
+ /**
* Executes a query string against the database.
*
* This method provides a central handler for the actual execution of every
diff --git a/includes/database/log.inc b/includes/database/log.inc
index f28aadb2c..ec27ef8e6 100644
--- a/includes/database/log.inc
+++ b/includes/database/log.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/mysql/database.inc b/includes/database/mysql/database.inc
index a3d711840..262cc6051 100644
--- a/includes/database/mysql/database.inc
+++ b/includes/database/mysql/database.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/mysql/install.inc b/includes/database/mysql/install.inc
index 2f83b2664..75f2ae390 100644
--- a/includes/database/mysql/install.inc
+++ b/includes/database/mysql/install.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/mysql/query.inc b/includes/database/mysql/query.inc
index 584a4a473..888b6a5a4 100644
--- a/includes/database/mysql/query.inc
+++ b/includes/database/mysql/query.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @ingroup database
@@ -43,8 +42,8 @@ class InsertQuery_mysql extends InsertQuery {
}
public function __toString() {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
// Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields);
@@ -93,8 +92,8 @@ class TruncateQuery_mysql extends TruncateQuery {
// not transactional, and result in an implicit COMMIT. When we are in a
// transaction, fallback to the slower, but transactional, DELETE.
if ($this->connection->inTransaction()) {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
}
else {
diff --git a/includes/database/mysql/schema.inc b/includes/database/mysql/schema.inc
index 01933da09..4e88fa169 100644
--- a/includes/database/mysql/schema.inc
+++ b/includes/database/mysql/schema.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/pgsql/database.inc b/includes/database/pgsql/database.inc
index d38b64afe..98b954ffd 100644
--- a/includes/database/pgsql/database.inc
+++ b/includes/database/pgsql/database.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
@@ -35,6 +34,15 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
if (empty($connection_options['password'])) {
$connection_options['password'] = NULL;
}
+ // If the password contains a backslash it is treated as an escape character
+ // http://bugs.php.net/bug.php?id=53217
+ // so backslashes in the password need to be doubled up.
+ // The bug was reported against pdo_pgsql 1.0.2, backslashes in passwords
+ // will break on this doubling up when the bug is fixed, so check the version
+ //elseif (phpversion('pdo_pgsql') < 'version_this_was_fixed_in') {
+ else {
+ $connection_options['password'] = str_replace('\\', '\\\\', $connection_options['password']);
+ }
$this->connectionOptions = $connection_options;
diff --git a/includes/database/pgsql/install.inc b/includes/database/pgsql/install.inc
index 0d446af58..c77f4ea78 100644
--- a/includes/database/pgsql/install.inc
+++ b/includes/database/pgsql/install.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/pgsql/query.inc b/includes/database/pgsql/query.inc
index c475a0011..f3783a9ca 100644
--- a/includes/database/pgsql/query.inc
+++ b/includes/database/pgsql/query.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @ingroup database
@@ -104,8 +103,8 @@ class InsertQuery_pgsql extends InsertQuery {
}
public function __toString() {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
// Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields);
diff --git a/includes/database/pgsql/schema.inc b/includes/database/pgsql/schema.inc
index 30f12ef78..9ed8a2620 100644
--- a/includes/database/pgsql/schema.inc
+++ b/includes/database/pgsql/schema.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
@@ -528,6 +527,9 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
$this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $check . '"');
}
+ // Remove old default.
+ $this->fieldSetNoDefault($table, $field);
+
$this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $typecast . ' USING "' . $field . '"::' . $typecast);
if (isset($spec['not null'])) {
@@ -562,6 +564,11 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
$this->connection->query('ALTER TABLE {' . $table . '} ADD CHECK ("' . $field_new . '" >= 0)');
}
+ // Add default if necessary.
+ if (isset($spec['default'])) {
+ $this->fieldSetDefault($table, $field_new, $spec['default']);
+ }
+
// Change description if necessary.
if (!empty($spec['description'])) {
$this->connection->query('COMMENT ON COLUMN {' . $table . '}."' . $field_new . '" IS ' . $this->prepareComment($spec['description']));
diff --git a/includes/database/pgsql/select.inc b/includes/database/pgsql/select.inc
index 98061c90a..d1d838281 100644
--- a/includes/database/pgsql/select.inc
+++ b/includes/database/pgsql/select.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/prefetch.inc b/includes/database/prefetch.inc
index a81ea10f1..f378d3555 100644
--- a/includes/database/prefetch.inc
+++ b/includes/database/prefetch.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/query.inc b/includes/database/query.inc
index de421b30c..23b652f9b 100644
--- a/includes/database/query.inc
+++ b/includes/database/query.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @ingroup database
@@ -362,6 +361,9 @@ abstract class Query implements QueryPlaceholderInterface {
* for easier debugging and allows you to more easily find where a query
* with a performance problem is being generated.
*
+ * The comment string will be sanitized to remove * / and other characters
+ * that may terminate the string early so as to avoid SQL injection attacks.
+ *
* @param $comment
* The comment string to be inserted into the query.
*
@@ -624,9 +626,8 @@ class InsertQuery extends Query {
* The prepared statement.
*/
public function __toString() {
-
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
// Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields);
@@ -816,9 +817,8 @@ class DeleteQuery extends Query implements QueryConditionInterface {
* The prepared statement.
*/
public function __toString() {
-
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
$query = $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
@@ -885,8 +885,8 @@ class TruncateQuery extends Query {
* The prepared statement.
*/
public function __toString() {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
return $comments . 'TRUNCATE {' . $this->connection->escapeTable($this->table) . '} ';
}
@@ -1112,9 +1112,8 @@ class UpdateQuery extends Query implements QueryConditionInterface {
* The prepared statement.
*/
public function __toString() {
-
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
// Expressions take priority over literal fields, so we process those first
// and remove any literal fields that conflict.
diff --git a/includes/database/schema.inc b/includes/database/schema.inc
index e57c94bfb..de1b2f5b9 100644
--- a/includes/database/schema.inc
+++ b/includes/database/schema.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/select.inc b/includes/database/select.inc
index 43f92671e..716c2fc3d 100644
--- a/includes/database/select.inc
+++ b/includes/database/select.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @ingroup database
@@ -1440,9 +1439,8 @@ class SelectQuery extends Query implements SelectQueryInterface {
}
public function __toString() {
-
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
// SELECT
$query = $comments . 'SELECT ';
diff --git a/includes/database/sqlite/database.inc b/includes/database/sqlite/database.inc
index 651efa26f..cf3b9551f 100644
--- a/includes/database/sqlite/database.inc
+++ b/includes/database/sqlite/database.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/sqlite/install.inc b/includes/database/sqlite/install.inc
index a8a12410d..62cbac381 100644
--- a/includes/database/sqlite/install.inc
+++ b/includes/database/sqlite/install.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/sqlite/query.inc b/includes/database/sqlite/query.inc
index 7b1af8114..6b8a72f2a 100644
--- a/includes/database/sqlite/query.inc
+++ b/includes/database/sqlite/query.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
@@ -33,8 +32,8 @@ class InsertQuery_sqlite extends InsertQuery {
}
public function __toString() {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
// Produce as many generic placeholders as necessary.
$placeholders = array_fill(0, count($this->insertFields), '?');
@@ -102,7 +101,7 @@ class UpdateQuery_sqlite extends UpdateQuery {
}
elseif (!isset($data)) {
// The field will be set to NULL.
- $condition->isNull($field);
+ $condition->isNotNull($field);
}
else {
$condition->condition($field, $data, '<>');
@@ -149,8 +148,8 @@ class DeleteQuery_sqlite extends DeleteQuery {
*/
class TruncateQuery_sqlite extends TruncateQuery {
public function __toString() {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ // Create a sanitized comment string to prepend to the query.
+ $comments = $this->connection->makeComment($this->comments);
return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
}
diff --git a/includes/database/sqlite/schema.inc b/includes/database/sqlite/schema.inc
index 11ecd881a..840ba6b5d 100644
--- a/includes/database/sqlite/schema.inc
+++ b/includes/database/sqlite/schema.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
diff --git a/includes/database/sqlite/select.inc b/includes/database/sqlite/select.inc
index ee3d84dff..fb926ef04 100644
--- a/includes/database/sqlite/select.inc
+++ b/includes/database/sqlite/select.inc
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file