The driver does not properly delimited all the uids for the db_update statement in system_status function in system.admin.inc.

  db_update('users')
    ->expression('uid', 'uid - uid')
    ->condition('name', '')
    ->condition('pass', '')
    ->condition('status', 0)
    ->execute();

Part of the SQL generated from the db_update is uid=uid - uid. This is escaped by the driver as "UID"=uid - "UID". This effectively toggles the uid for anonymous between zero and the Oracle UID on each call to system_status.

Comments

aaaristo’s picture

Status: Active » Needs work

going to fix it

aaaristo’s picture

Status: Needs work » Fixed

fixed in 1.10

Richard.Li’s picture

Version: 7.x-1.9 » 7.x-1.10

I try install the driver in Win7x64, IIS7.5 with zendce pdo-oci extension, the driver seems worked OK, but dashboard display have a issue seems some things related to this problem. I am new to drupal.org, I reported problem here.

The Error is :

PDOException: SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start AND :oracle_rwn_end (prepared: SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u.\"UID\", u.name, MAX(s.timestamp) max_timestamp FROM "USERS" u INNER JOIN "SESSIONS" s ON u."UID" = s."UID" WHERE s.timestamp >= :interval AND s."UID" > 0 GROUP BY u."UID", u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start AND :oracle_rwn_end ) e: SQLSTATE[HY000]: General error: 911 OCIStmtExecute: ORA-00911: 无效字符 (ext\pdo_oci\oci_statement.c:148) args: Array ( [:interval] => 1328351703 [oracle_rwn_start] => 1 [oracle_rwn_end] => 10 ) in user_block_view() (line 1420 of E:\WWW\drupal\modules\user\user.module).

I have rechecked Error, SELECT u.\"UID\" Escaping of uid is not handled properly obviously. so please fix it.

aaaristo’s picture

Status: Fixed » Closed (won't fix)

looks like you have a problem in your php intallation, run this:


  function escapeReserved($query)
  {
        $ddl= !((boolean)preg_match('/^(select|insert|update|delete)/i',$query));
        $search = array ("/({)(\w+)(})/e", // escapes all table names
                         "/({L#)([0-9]+)(})/e", // escapes long id
                         "/(\:)(uid|session|file|access|mode|comment|desc|size|start|end)/e",
                         "/(<uid>|<session>|<file>|<access>|<mode>|<comment>|<desc>|<size>".($ddl?'':'|<date>').")/e",
                         '/([\(\.\s,\=])(uid|session|file|access|mode|comment|desc|size'.($ddl?'':'|date').')([,\s\=)])/e',
                         '/([\(\.\s,])(uid|session|file|access|mode|comment|desc|size'.($ddl?'':'|date').')$/e');

        $replace = array ("'\"\\1'.strtoupper('\\2').'\\3\"'",
                          "'\"\\1'.strtoupper('\\2').'\\3\"'",
                          "'\\1'.'db_'.'\\2'.'\\3'",
                          "strtoupper('\"\\1\"')",
                          "'\\1'.strtoupper('\"\\2\"').'\\3'",
                          "'\\1'.strtoupper('\"\\2\"')");

        return preg_replace($search, $replace, $query);
  }


   echo escapeReserved('SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start AND :oracle_rwn_end');

i get:

SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u."UID", u.name, MAX(s.timestamp) AS max_timestamp FROM "{USERS}" u INNER JOIN "{SESSIONS}" s ON u."UID" = s."UID" WHERE s.timestamp >= :interval AND s."UID" > 0 GROUP BY u."UID", u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start

Richard.Li’s picture

I tested this function, that is no problem, both your code and my system code in database.inc. but Error still there. may be somewhere else.

minoroffense’s picture

We're getting the same error as described above when trying to upgrade from 1.9 to 1.10.

I tried running that function and got the following output:

SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u."UID", u.name, MAX(s.timestamp) AS max_timestamp FROM "{USERS}" u INNER JOIN "{SESSIONS}" s ON u."UID" = s."UID" WHERE s.timestamp >= :interval AND s."UID" > 0 GROUP BY u."UID", u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start AND :oracle_rwn_end
aaaristo’s picture

Status: Closed (won't fix) » Postponed (maintainer needs more info)

can you please tell me on which url? doing what? how can i reproduce it

minoroffense’s picture

Sure thing.

We're hdt getting access to the oracle query log. Onc I have that I'll supply a full list of proper debug info.

minoroffense’s picture

PDOException: SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start AND :oracle_rwn_end (prepared: SELECT * FROM (SELECT TAB.*, ROWNUM RWN_TO_REMOVE FROM (SELECT u.\"UID\", u.name, MAX(s.timestamp) max_timestamp FROM "USERS" u INNER JOIN "SESSIONS" s ON u."UID" = s."UID" WHERE s.timestamp >= :interval AND s."UID" > 0 GROUP BY u."UID", u.name ORDER BY max_timestamp DESC) TAB) WHERE RWN_TO_REMOVE BETWEEN :oracle_rwn_start AND :oracle_rwn_end ) e: SQLSTATE[HY000]: General error: 911 OCIStmtExecute: ORA-00911: invalid character (ext\pdo_oci\oci_statement.c:148) args: Array ( [:interval] => 1328638530 [oracle_rwn_start] => 1 [oracle_rwn_end] => 10 ) in user_block_view() (line 1420 of D:\wwwroot\mytc\modules\user\user.module).

- This only appears when the user is authenticated.
- This occurs on any page I visit on our site as an authenticated user
- Waiting on the DBA to get me the logs from their end.

Driver/Environment Info

- PDO_OCI
- PDO Driver for OCI 8 and later
- Window Server 2008 R2 Standard SP1 (64bit)
- PHP 5.3.8

- Windows NT NCRWS377 6.1 build 7601 (Windows Server 2008 R2 Standard Edition Service Pack 1) i586
- Architecture x86
- Configure Command cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--disable-zts" "--disable-isapi" "--disable-nsapi" "--without-mssql" "--without-pdo-mssql" "--without-pi3web" "--with-pdo-oci=D:\php-sdk\oracle\instantclient10\sdk,shared" "--with-oci8=D:\php-sdk\oracle\instantclient10\sdk,shared" "--with-oci8-11g=D:\php-sdk\oracle\instantclient11\sdk,shared" "--with-enchant=shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet" "--with-mcrypt=static" "--disable-static-analyze"
- Server API CGI/FastCGI
- Loaded Configuration File C:\Program Files (x86)\PHP\v5.3\php.ini

minoroffense’s picture

If I comment out this query in the user.module (see line 1420), the site works once again:

        // Display a list of currently online users.
        $max_users = variable_get('user_block_max_list_count', 10);
        if ($authenticated_count && $max_users) {
          $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', 0, $max_users, array(':interval' => $interval))->fetchAll();
          $output .= theme('user_list', array('users' => $items));
        }

Disabling the "Who's Online" block on all displays also works (and is the way I've fixed our sites for the moment).

aaaristo’s picture

Priority: Normal » Critical
Status: Postponed (maintainer needs more info) » Needs work

ok initial workaround database.inc line 405 comment out $oquery= $this->escapeTableAlias($oquery);:


                  if (!$this->external)
                  {
                      $oquery= $this->escapeEmptyLiterals($oquery);
                      $oquery= $this->escapeAnsi($oquery);
                      $oquery= $this->lih->escapeLongIdentifiers($oquery);
                      $oquery= $this->escapeReserved($oquery);
                      $oquery= $this->escapeCompatibility($oquery);
                      $oquery= $this->prefixTables($oquery,true);
                      $oquery= $this->escapeIfFunction($oquery);
                      // $oquery= $this->escapeTableAlias($oquery);
                  }


aaaristo’s picture

Status: Needs work » Fixed

removed escapeTableAlias support
fixed in 1.11

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.