diff --git a/lib/filelib.php b/lib/filelib.php index b5f3fd13ce0..60fcea88f7c 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3706,7 +3706,8 @@ class curl { $this->reset_request_state_vars(); if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST)) { - if ($mockresponse = array_pop(self::$mockresponses)) { + $mockresponse = array_pop(self::$mockresponses); + if ($mockresponse !== null) { $this->info = [ 'http_code' => 200 ]; return $mockresponse; } diff --git a/mod/lti/locallib.php b/mod/lti/locallib.php index 7668e676631..b0e05eba707 100644 --- a/mod/lti/locallib.php +++ b/mod/lti/locallib.php @@ -4392,6 +4392,13 @@ function lti_load_cartridge($url, $map, $propertiesmap = array()) { $curl = new curl(); $response = $curl->get($url); + // Got a completely empty response (real or error), cannot process this with + // DOMDocument::loadXML() because it errors with ValueError. So let's throw + // the moodle_exception before waiting to examine the errors later. + if (trim($response) === '') { + throw new moodle_exception('errorreadingfile', '', '', $url); + } + // TODO MDL-46023 Replace this code with a call to the new library. $origerrors = libxml_use_internal_errors(true); $origentity = lti_libxml_disable_entity_loader(true); diff --git a/mod/lti/tests/locallib_test.php b/mod/lti/tests/locallib_test.php index 37791f3e1ca..02f1e9c1f84 100644 --- a/mod/lti/tests/locallib_test.php +++ b/mod/lti/tests/locallib_test.php @@ -1841,6 +1841,20 @@ MwIDAQAB ]; } + /** + * Verify that empty curl responses lead to the proper moodle_exception, not to XML ValueError. + * + * @covers ::lti_load_cartridge() + */ + public function test_empty_reponse_lti_load_cartridge() { + // Mock the curl response to empty string, this is hardly + // reproducible in real life (only Windows + GHA). + \curl::mock_response(''); + + $this->expectException(\moodle_exception::class); + lti_load_cartridge('http://example.com/mocked/empty/response', []); + } + /** * Create an LTI Tool. *