Closed
Description
I managed to come across a weird scenario where javascript code executes PHP that throws exception and this exception is not caught within javascript despite try/catch blocks and FLAG_PROPAGATE_PHP_EXCEPTIONS being set.
My current understanding is that it happens when exception is thrown in PHP magic methods.
Below is the code reproducing the issue (+Dockerfile if of any use)
Code:
<?php
class SomeClass {
function someMethod($someVariable) { return $someVariable; }
public function triggerException() { throw new Exception("Some exception");}
public function __get($key) { $this->triggerException(); }
}
function execute($code) {
$js = new V8Js();
$js->output = new stdClass();
$js->SomeClassInstance = new SomeClass();
try {
$js->executeString("try{ $code } catch(e) {PHP.output.result = 'Caught exception at javascript level : ' + e.getMessage();}", '', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS);
print($js->output->result.PHP_EOL);
} catch (Exception $e) {
print( "Caught exception at php level : ".$e->getMessage().PHP_EOL);
}
}
execute("PHP.SomeClassInstance.triggerException();"); //caught in js
execute("PHP.SomeClassInstance.someMethod(PHP.SomeClassInstance.TriggerMagicMethod);");//caught in js
execute("PHP.SomeClassInstance.TriggerMagicMethod;");//caught in PHP !
Dockerfile:
FROM stesie/v8js
RUN echo "<?php\n" \
"class SomeClass {\n" \
" function someMethod(\$someVariable) { return \$someVariable; }\n" \
" public function triggerException() { throw new Exception('Some exception');}\n" \
" public function __get(\$key) { \$this->triggerException(); }\n" \
"}\n" \
"\n" \
"function execute(\$code) {\n" \
" \$js = new V8Js();\n" \
" \$js->output = new stdClass();\n" \
" \$js->SomeClassInstance = new SomeClass();\n" \
" try {\n" \
" \$js->executeString(\"try{ \$code } catch(e) {PHP.output.result = 'Caught exception at javascript level : ' + e.getMessage();}\", '', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS);\n" \
" print(\$js->output->result.PHP_EOL);\n" \
" } catch (Exception \$e) {\n" \
" print( 'Caught exception at php level : '.\$e->getMessage().PHP_EOL);\n" \
" }\n" \
"}\n" \
"" \
"execute('PHP.SomeClassInstance.triggerException();'); //caught in js\n" \
"execute('PHP.SomeClassInstance.someMethod(PHP.SomeClassInstance.TriggerMagicMethod);');//caught in js\n" \
"execute('PHP.SomeClassInstance.TriggerMagicMethod;');//caught in PHP !" > /test.php
CMD php /test.php