[!!!][BUGFIX] Check for existing index column in exec_SELECTgetRows() 07/39807/7
authorMarkus Klein <markus.klein@typo3.org>
Fri, 29 May 2015 21:18:40 +0000 (23:18 +0200)
committerFrank Nägler <typo3@naegler.net>
Fri, 5 Jun 2015 08:44:14 +0000 (10:44 +0200)
In case the specified $uidIndexField does not exist in the result,
throw an exception.

Do not call debug() again since it has already been called in
exec_SELECTquery().

Resolves: #67204
Releases: master
Change-Id: I3b0a49a24da50b8ee5390f0619bf78e2e3fe772d
Reviewed-on: http://review.typo3.org/39807
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Frank Nägler <typo3@naegler.net>
Tested-by: Frank Nägler <typo3@naegler.net>
typo3/sysext/core/Classes/Database/DatabaseConnection.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-67204-DatabaseConnectionexec_SELECTgetRowsMayThrowException.rst [new file with mode: 0644]

index e5eb5b2..f721a61 100644 (file)
@@ -361,36 +361,40 @@ class DatabaseConnection {
        /**
         * Creates and executes a SELECT SQL-statement AND traverse result set and returns array with records in.
         *
-        * @param string $select_fields See exec_SELECTquery()
-        * @param string $from_table See exec_SELECTquery()
-        * @param string $where_clause See exec_SELECTquery()
-        * @param string $groupBy See exec_SELECTquery()
-        * @param string $orderBy See exec_SELECTquery()
-        * @param string $limit See exec_SELECTquery()
+        * @param string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
+        * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
+        * @param string $where_clause Additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
+        * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
+        * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
+        * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
         * @param string $uidIndexField If set, the result array will carry this field names value as index. Requires that field to be selected of course!
         * @return array|NULL Array of rows, or NULL in case of SQL error
+        * @see exec_SELECTquery()
+        * @throws \InvalidArgumentException
         */
        public function exec_SELECTgetRows($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', $uidIndexField = '') {
                $res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
-               if ($this->debugOutput) {
-                       $this->debug('exec_SELECTquery');
+               if ($this->sql_error()) {
+                       $this->sql_free_result($res);
+                       return NULL;
                }
-               if (!$this->sql_error()) {
-                       $output = array();
+               $output = array();
+               $firstRecord = TRUE;
+               while ($record = $this->sql_fetch_assoc($res)) {
                        if ($uidIndexField) {
-                               while ($tempRow = $this->sql_fetch_assoc($res)) {
-                                       $output[$tempRow[$uidIndexField]] = $tempRow;
+                               if ($firstRecord) {
+                                       $firstRecord = FALSE;
+                                       if (!array_key_exists($uidIndexField, $record)) {
+                                               $this->sql_free_result($res);
+                                               throw new \InvalidArgumentException('The given $uidIndexField "' . $uidIndexField . '" is not available in the result.', 1432933855);
+                                       }
                                }
+                               $output[$record[$uidIndexField]] = $record;
                        } else {
-                               while ($output[] = $this->sql_fetch_assoc($res)) {
-
-                               }
-                               array_pop($output);
+                               $output[] = $record;
                        }
-                       $this->sql_free_result($res);
-               } else {
-                       $output = NULL;
                }
+               $this->sql_free_result($res);
                return $output;
        }
 
@@ -408,9 +412,6 @@ class DatabaseConnection {
         */
        public function exec_SELECTgetSingleRow($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $numIndex = FALSE) {
                $res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, '1');
-               if ($this->debugOutput) {
-                       $this->debug('exec_SELECTquery');
-               }
                $output = NULL;
                if ($res !== FALSE) {
                        if ($numIndex) {
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-67204-DatabaseConnectionexec_SELECTgetRowsMayThrowException.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-67204-DatabaseConnectionexec_SELECTgetRowsMayThrowException.rst
new file mode 100644 (file)
index 0000000..b04ccd2
--- /dev/null
@@ -0,0 +1,29 @@
+===============================================================================
+Breaking: #67204 - DatabaseConnection::exec_SELECTgetRows() may throw exception
+===============================================================================
+
+Description
+===========
+
+``DatabaseConnection::exec_SELECTgetRows()`` validates ``$uidIndexField`` parameter now.
+If the specified field is not present in the database result an ``InvalidArgumentException`` is thrown.
+
+
+Impact
+======
+
+This change will affect only broken usages of ``DatabaseConnection::exec_SELECTgetRows()`` with an invalid last parameter.
+
+It is very unlikely that existing code affected by this change, since using the method in a wrong way had the consequence that it only returned the last row from the result.
+
+
+Affected Installations
+======================
+
+Any code using the ``DatabaseConnection::exec_SELECTgetRows()`` method with ``$uidIndexField`` being set to a field name not present in the queried result set.
+
+
+Migration
+=========
+
+Fix your call to the method and correct the ``$uidIndexField`` parameter.