1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

Merge pull request #12604 from calixteman/quickjs

JS -- Add a sandbox based on quickjs
This commit is contained in:
Brendan Dahl 2020-11-19 08:40:21 -08:00 committed by GitHub
commit c88e805870
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 886 additions and 245 deletions

View file

@ -22,7 +22,7 @@ import { ProxyHandler } from "./proxy.js";
import { Util } from "./util.js";
import { ZoomType } from "./constants.js";
function initSandbox({ data, extra, out, testMode = false }) {
function initSandbox({ data, extra, out }) {
const proxyHandler = new ProxyHandler(data.dispatchEventName);
const { send, crackURL } = extra;
const doc = new Doc({
@ -58,14 +58,6 @@ function initSandbox({ data, extra, out, testMode = false }) {
out[name] = aform[name].bind(aform);
}
}
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
testMode
) {
out._app = app;
}
}
export { initSandbox };

View file

@ -0,0 +1,103 @@
/* Copyright 2020 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import ModuleLoader from "../../external/quickjs/quickjs-eval.js";
class Sandbox {
constructor(module, testMode) {
this._evalInSandbox = module.cwrap("evalInSandbox", null, [
"string",
"int",
]);
this._dispatchEventName = null;
this._module = module;
this._testMode = testMode;
this._alertOnError = 1;
}
create(data) {
const sandboxData = JSON.stringify(data);
const extra = [
"send",
"setTimeout",
"clearTimeout",
"setInterval",
"clearInterval",
"crackURL",
];
const extraStr = extra.join(",");
let code = [
"exports = Object.create(null);",
"module = Object.create(null);",
// Next line is replaced by code from initialization.js
// when we create the bundle for the sandbox.
"/* INITIALIZATION_CODE */",
`data = ${sandboxData};`,
`module.exports.initSandbox({ data, extra: {${extraStr}}, out: this});`,
"delete exports;",
"delete module;",
"delete data;",
];
if (!this._testMode) {
code = code.concat(extra.map(name => `delete ${name};`));
code.push("delete debugMe;");
}
this._evalInSandbox(code.join("\n"), this._alertOnError);
this._dispatchEventName = data.dispatchEventName;
}
dispatchEvent(event) {
if (this._dispatchEventName === null) {
throw new Error("Sandbox must have been initialized");
}
event = JSON.stringify(event);
this._evalInSandbox(
`app["${this._dispatchEventName}"](${event});`,
this._alertOnError
);
}
dumpMemoryUse() {
this._module.ccall("dumpMemoryUse", null, []);
}
nukeSandbox() {
this._dispatchEventName = null;
this._module.ccall("nukeSandbox", null, []);
this._module = null;
this._evalInSandbox = null;
}
evalForTesting(code, key) {
if (this._testMode) {
this._evalInSandbox(
`send({ id: "${key}", result: ${code} });`,
this._alertOnError
);
}
}
}
function QuickJSSandbox(testMode = false) {
testMode =
testMode &&
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING"));
return ModuleLoader().then(module => {
return new Sandbox(module, testMode);
});
}
export { QuickJSSandbox };

View file

@ -49,6 +49,9 @@ class Util extends PDFObject {
}
crackURL(cURL) {
if (typeof cURL !== "string") {
throw new TypeError("First argument of util.crackURL must be a string");
}
return this._crackURL(cURL);
}