Skip to content

Commit aae80e6

Browse files
committed
Pdo\Pgsql::setNoticeCallback(): test with unimplemented trampoline
Add a test with a runtime BadMethodCallException. Streamline issue78621_method.phpt.
1 parent a4cc92c commit aae80e6

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed

ext/pdo_pgsql/tests/issue78621.inc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ $db->exec("insert into t values ('ah')");
1919
while (count($rounds)) {
2020
try {
2121
attach($db, array_shift($rounds));
22-
} catch (TypeError $err) {
23-
echo "Caught TypeError: ".$err->getMessage()."\n";
22+
} catch (Throwable $err) {
23+
echo "Caught ".get_class($err).": ".$err->getMessage()."\n";
24+
}
25+
try {
26+
$db->exec("delete from t");
27+
$db->exec("insert into t values ('ah')");
28+
} catch (Throwable $err) {
29+
echo "Caught ".get_class($err)." ".$err->getMessage()."\n";
2430
}
25-
$db->exec("delete from t");
26-
$db->exec("insert into t values ('ah')");
2731
}
2832
$db->setNoticeCallback(null);
2933
$db->exec("delete from t");

ext/pdo_pgsql/tests/issue78621_method.phpt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,24 @@ class Logger
1616
public function __call(string $method, array $args)
1717
{
1818
$realMethod = strtr($method, [ 'whatever' => 'disp' ]);
19+
if (!method_exists($this, $realMethod)) {
20+
throw new BadMethodCallException('Call to undefined method '.__CLASS__.'::'.$realMethod);
21+
}
1922
echo "$method trampoline for $realMethod\n";
2023
return call_user_func_array([ $this, $realMethod ], $args);
2124
}
2225
}
2326
$logger = new Logger();
24-
function attach($db, $prefix = '')
27+
function attach($db, $method)
2528
{
2629
global $logger;
27-
global $flavor;
28-
switch($flavor)
29-
{
30-
case 0: $db->setNoticeCallback([ $logger, 'disp'.$prefix ]); break;
31-
case 1: $db->setNoticeCallback([ $logger, 'whatever'.$prefix ]); break;
32-
}
30+
$db->setNoticeCallback([ $logger, $method ]);
3331
}
3432
echo "Testing with method explicitely plugged:\n";
35-
$flavor = 0;
33+
$rounds = [ 'disp', 'dispRe' ];
3634
require dirname(__FILE__) . '/issue78621.inc';
3735
echo "Testing with a bit of magic:\n";
38-
++$flavor;
36+
$rounds = [ 'whatever', 'whateverRe', 'unexisting' ];
3937
require dirname(__FILE__) . '/issue78621.inc';
4038
?>
4139
--EXPECT--
@@ -55,6 +53,7 @@ whatever trampoline for disp
5553
NOTICE: I tampered your data, did you know?
5654
whateverRe trampoline for dispRe
5755
ReNOTICE: I tampered your data, did you know?
56+
Caught BadMethodCallException Call to undefined method Logger::unexisting
5857
array(1) {
5958
[0]=>
6059
array(1) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
Pdo\Pgsql::setNoticeCallback() use F ZPP for trampoline callback and does not leak
3+
--EXTENSIONS--
4+
pdo
5+
pdo_pgsql
6+
--SKIPIF--
7+
<?php
8+
require __DIR__ . '/config.inc';
9+
require dirname(__DIR__, 2) . '/pdo/tests/pdo_test.inc';
10+
PDOTest::skip();
11+
?>
12+
--FILE--
13+
<?php
14+
15+
require_once __DIR__ . "/config.inc";
16+
17+
$db = new Pdo\Pgsql($config['ENV']['PDOTEST_DSN']);
18+
19+
function disp($message) { echo trim($message)."\n"; }
20+
function attach($db, $callback)
21+
{
22+
if (is_array($callback) && $callback[0] === null) {
23+
$callback = $callback[1];
24+
$rc = new ReflectionClass(Pdo\Pgsql::class);
25+
$db = $rc->newInstanceWithoutConstructor();
26+
}
27+
$db->setNoticeCallback($callback);
28+
}
29+
30+
class T { public function z($m) { echo $m."\n"; } public function __call($m, $p) { echo "bah $m\n"; } }
31+
$t = new T;
32+
$rounds = [
33+
[ $t, 'disp' ],
34+
3, // Error; but then as the old callback is kept, it will be used in the call that follows the caught error.
35+
null, // No callback; hopefully this clears everything.
36+
'wouldAnyoneNameAFunctionThisWay', // So this one will crash and *no output will follow*.
37+
[ null, [ $t, 'disp' ] ], // Valid callback on an unvalid Pdo.
38+
[ $t, 'disp' ],
39+
];
40+
require __DIR__ . '/issue78621.inc';
41+
42+
?>
43+
--EXPECTF--
44+
bah disp
45+
Caught TypeError: %s: Argument #1 ($callback) %s
46+
bah disp
47+
Caught TypeError: %s: Argument #1 ($callback) %s
48+
Caught Error: Pdo\Pgsql object is uninitialized
49+
bah disp
50+
array(1) {
51+
[0]=>
52+
array(1) {
53+
["a"]=>
54+
string(2) "oh"
55+
}
56+
}
57+
Done
58+

0 commit comments

Comments
 (0)