Skip to content

[Bug #77120] Handle OCI_SUCCESS_WITH_INFO returned from OCISessionBegin #6857

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions ext/pdo_oci/oci_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, swor
}

/* little mini hack so that we can use this code from the dbh ctor */
if (!dbh->methods) {
if (!dbh->methods && status != OCI_SUCCESS_WITH_INFO) {
zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s]: %s", *pdo_err, einfo->errmsg);
}

Expand Down Expand Up @@ -336,9 +336,13 @@ static zend_long oci_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /* {{{
H->last_err = OCIStmtExecute(H->svc, stmt, H->err, 1, 0, NULL, NULL,
(dbh->auto_commit && !dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);

if (H->last_err) {
sword last_err = H->last_err;

if (last_err) {
H->last_err = oci_drv_error("OCIStmtExecute");
} else {
}

if (!last_err || last_err == OCI_SUCCESS_WITH_INFO) {
/* return the number of affected rows */
H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, H->err);
ret = rowcount;
Expand Down Expand Up @@ -831,7 +835,12 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ *
H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT);
if (H->last_err) {
oci_drv_error("OCISessionBegin");
goto cleanup;
/* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
* user's password has expired, but is still usable.
*/
if (H->last_err != OCI_SUCCESS_WITH_INFO) {
goto cleanup;
}
}

/* set the server handle into service handle */
Expand Down
116 changes: 116 additions & 0 deletions ext/pdo_oci/tests/oci_success_with_info.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
--TEST--
Handling OCI_SUCCESS_WITH_INFO
--SKIPIF--
<?php
if (!extension_loaded('pdo') || !extension_loaded('pdo_oci')) die('skip not loaded');
?>
--FILE--
<?php

function connectAsAdmin(): PDO {
return PDOTest::test_factory(__DIR__ . '/../../pdo_oci/tests/common.phpt');
}

function connectAsUser(string $username, string $password): PDO {
return new PDO(getenv('PDOTEST_DSN'), $username, $password);
}

function dropProfile(PDO $conn): void {
$conn->exec(<<<'SQL'
BEGIN
EXECUTE IMMEDIATE 'DROP PROFILE BUG77120_PROFILE CASCADE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2380 THEN
RAISE;
END IF;
END;
SQL
);
}

function dropUser(PDO $conn): void {
$conn->exec(<<<'SQL'
BEGIN
EXECUTE IMMEDIATE 'DROP USER BUG77120_USER CASCADE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1918 THEN
RAISE;
END IF;
END;
SQL
);
}

function triggerCompilationError(PDO $conn): void {
$conn->exec(<<<'SQL'
CREATE OR REPLACE FUNCTION BUG77120(INT A) RETURN INT
AS
BEGIN
RETURN 0;
END;
SQL
);
}

require __DIR__ . '/../../pdo/tests/pdo_test.inc';

$conn = connectAsAdmin();

dropUser($conn);
dropProfile($conn);

$password = bin2hex(random_bytes(8));

$conn->exec('CREATE PROFILE BUG77120_PROFILE LIMIT PASSWORD_LIFE_TIME 1/86400 PASSWORD_GRACE_TIME 1');
$conn->exec('CREATE USER BUG77120_USER IDENTIFIED BY "' . $password . '" PROFILE BUG77120_PROFILE');
$conn->exec('GRANT CREATE SESSION TO BUG77120_USER');

// let the password expire
sleep(2);

$conn = connectAsUser('BUG77120_USER', $password);
var_dump($conn->errorInfo());

$conn = connectAsAdmin();
dropUser($conn);
dropProfile($conn);

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
triggerCompilationError($conn);
var_dump($conn->errorInfo());

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
triggerCompilationError($conn);
var_dump($conn->errorInfo());

?>
--EXPECTF--
array(3) {
[0]=>
string(5) "HY000"
[1]=>
int(28002)
[2]=>
string(%d) "OCISessionBegin: OCI_SUCCESS_WITH_INFO: ORA-28002: %s
(%s:%d)"
}
array(3) {
[0]=>
string(5) "HY000"
[1]=>
int(24344)
[2]=>
string(%d) "OCIStmtExecute: OCI_SUCCESS_WITH_INFO: ORA-24344: %s
(%s:%d)"
}
array(3) {
[0]=>
string(5) "HY000"
[1]=>
int(24344)
[2]=>
string(%d) "OCIStmtExecute: OCI_SUCCESS_WITH_INFO: ORA-24344: %s
(%s:%d)"
}