Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 1 file). Show all
Unified · Split
| @@ -1361,28 +1361,22 @@ void ScriptEngine::print(const QString& message) { · 1360 unmodified lines | |||
| 1361 | QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& relativeTo) { | 1361 | QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& relativeTo) { |
| 1362 | QUrl defaultScriptsLoc = defaultScriptsLocation(); | 1362 | QUrl defaultScriptsLoc = defaultScriptsLocation(); |
| 1363 | QUrl url(moduleId); | 1363 | QUrl url(moduleId); |
| 1364 | ExceptionEmitter tryCatcher(this, __FUNCTION__); | ||
| 1364 | 1365 | ||
| 1365 | // helper to generate an exception and return a null string | 1366 | auto displayId = moduleId; |
| 1366 | auto resolverException = [=](const QString& detail, const QString& type = "Error") -> QString { | 1367 | if (displayId.length() > MAX_DEBUG_VALUE_LENGTH) { |
| 1367 | auto displayId = moduleId; | 1368 | displayId = displayId.mid(0, MAX_DEBUG_VALUE_LENGTH) + "..."; |
| 1368 | if (displayId.length() > MAX_DEBUG_VALUE_LENGTH) { | 1369 | } |
| 1369 | displayId = displayId.mid(0, MAX_DEBUG_VALUE_LENGTH) + "..."; | 1370 | auto message = QString("Cannot find module '%1' (%2)").arg(displayId); |
| 1370 | } | 1371 | auto ctx = currentContext(); |
| 1371 | currentContext()->throwValue(makeError( | ||
| 1372 | QString("Cannot find module '%1' (%2)") | ||
| 1373 | .arg(displayId) | ||
| 1374 | .arg(detail), type)); | ||
| 1375 | return QString(); | ||
| 1376 | }; | ||
| 1377 | 1372 | ||
| 1378 | // de-fuzz the input a little by restricting to rational sizes | 1373 | // de-fuzz the input a little by restricting to rational sizes |
| 1379 | auto idLength = url.toString().length(); | 1374 | auto idLength = url.toString().length(); |
| 1380 | if (idLength < 1 || idLength > MAX_MODULE_ID_LENTGH) { | 1375 | if (idLength < 1 || idLength > MAX_MODULE_ID_LENTGH) { |
| 1381 | return resolverException( | 1376 | auto details = QString("rejecting invalid module id size (%1 chars [1,%2])") |
| 1382 | QString("rejecting invalid module id size (%1 chars [1,%2])") | 1377 | .arg(idLength).arg(MAX_MODULE_ID_LENTGH); |
| 1383 | .arg(idLength).arg(MAX_MODULE_ID_LENTGH), | 1378 | ctx->throwValue(makeError(message.arg(details), "RangeError")); |
| 1384 | "RangeError" | 1379 | return nullptr; |
| 1385 | ); | ||
| 1386 | } | 1380 | } |
| 1387 | 1381 | ||
| 1388 | // this regex matches: absolute, dotted or path-like URLs | 1382 | // this regex matches: absolute, dotted or path-like URLs |
| @@ -1402,12 +1396,14 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re · 13 unmodified lines | |||
| 1402 | url = defaultScriptsLoc; | 1396 | url = defaultScriptsLoc; |
| 1403 | url.setPath(systemModulePath); | 1397 | url.setPath(systemModulePath); |
| 1404 | if (!QFileInfo(url.toLocalFile()).isFile()) { | 1398 | if (!QFileInfo(url.toLocalFile()).isFile()) { |
| 1405 | return resolverException("system module not found"); | 1399 | ctx->throwValue(makeError(message.arg("system module not found"))); |
| 1400 | return nullptr; | ||
| 1406 | } | 1401 | } |
| 1407 | } | 1402 | } |
| 1408 | 1403 | ||
| 1409 | if (url.isRelative()) { | 1404 | if (url.isRelative()) { |
| 1410 | return resolverException("could not resolve module id"); | 1405 | ctx->throwValue(makeError(message.arg("could not resolve module id"))); |
| 1406 | return nullptr; | ||
| 1411 | } | 1407 | } |
| 1412 | 1408 | ||
| 1413 | // if it looks like a local file, verify that it's an allowed path and really a file | 1409 | // if it looks like a local file, verify that it's an allowed path and really a file |
| @@ -1420,18 +1416,21 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re · 6 unmodified lines | |||
| 1420 | 1416 | ||
| 1421 | bool disallowOutsideFiles = !defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile(); | 1417 | bool disallowOutsideFiles = !defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile(); |
| 1422 | if (disallowOutsideFiles && !PathUtils::isDescendantOf(canonical, currentSandboxURL)) { | 1418 | if (disallowOutsideFiles && !PathUtils::isDescendantOf(canonical, currentSandboxURL)) { |
| 1423 | return resolverException( | 1419 | ctx->throwValue(makeError(message.arg( |
| 1424 | QString("path '%1' outside of origin script '%2' '%3'") | 1420 | QString("path '%1' outside of origin script '%2' '%3'") |
| 1425 | .arg(PathUtils::stripFilename(url)) | 1421 | .arg(PathUtils::stripFilename(url)) |
| 1426 | .arg(PathUtils::stripFilename(currentSandboxURL)) | 1422 | .arg(PathUtils::stripFilename(currentSandboxURL)) |
| 1427 | .arg(canonical.toString()) | 1423 | .arg(canonical.toString()) |
| 1428 | ); | 1424 | ))); |
| 1425 | return nullptr; | ||
| 1429 | } | 1426 | } |
| 1430 | if (!file.exists()) { | 1427 | if (!file.exists()) { |
| 1431 | return resolverException("path does not exist: " + url.toLocalFile()); | 1428 | ctx->throwValue(makeError(message.arg("path does not exist: " + url.toLocalFile()))); |
| 1429 | return nullptr; | ||
| 1432 | } | 1430 | } |
| 1433 | if (!file.isFile()) { | 1431 | if (!file.isFile()) { |
| 1434 | return resolverException("path is not a file: " + url.toLocalFile()); | 1432 | ctx->throwValue(makeError(message.arg("path is not a file: " + url.toLocalFile()))); |
| 1433 | return nullptr; | ||
| 1435 | } | 1434 | } |
| 1436 | } | 1435 | } |
| 1437 | 1436 | ||
| @@ -1611,6 +1610,7 @@ QScriptValue ScriptEngine::require(const QString& moduleId) { · 173 unmodified lines | |||
| 1611 | // serialize require calls so the ordering/caching works correctly across multiple Entities | 1610 | // serialize require calls so the ordering/caching works correctly across multiple Entities |
| 1612 | // note: this is a Recursive mutex so nested require's should not affected | 1611 | // note: this is a Recursive mutex so nested require's should not affected |
| 1613 | QMutexLocker locker(&_requireLock); | 1612 | QMutexLocker locker(&_requireLock); |
| 1613 | ExceptionEmitter tryCatcher(this, __FUNCTION__); | ||
| 1614 | // _requireDepth++; | 1614 | // _requireDepth++; |
| 1615 | // QObject autoDecrement;connect(&autoDecrement, &QObject::destroyed, this, [this](){ _requireDepth--; }); | 1615 | // QObject autoDecrement;connect(&autoDecrement, &QObject::destroyed, this, [this](){ _requireDepth--; }); |
| 1616 | 1616 | ||
| @@ -1632,7 +1632,7 @@ QScriptValue ScriptEngine::require(const QString& moduleId) { · 15 unmodified lines | |||
| 1632 | 1632 | ||
| 1633 | // start by resolving the moduleId into a fully-qualified path/URL | 1633 | // start by resolving the moduleId into a fully-qualified path/URL |
| 1634 | QString modulePath = _requireResolve(moduleId); | 1634 | QString modulePath = _requireResolve(moduleId); |
| 1635 | if (hasUncaughtException()) { | 1635 | if (modulePath.isNull() || tryCatcher.hasPending()) { |
| 1636 | // the resolver already threw an exception -- bail early | 1636 | // the resolver already threw an exception -- bail early |
| 1637 | return nullValue(); | 1637 | return nullValue(); |
| 1638 | } | 1638 | } |