Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/devtools/server/tests/xpcshell/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 12 kB image not shown  

Quelle  test_objectgrips-21.js   Sprache: JAVA

 
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */


"use strict";

Services.prefs.setBoolPref("security.allow_eval_with_system_principal"true);

registerCleanupFunction(() => {
  Services.prefs.clearUserPref("security.allow_eval_with_system_principal");
});

// Run test_unsafe_grips twice, one against a system principal debuggee
// and another time with a null principal debuggee

// The following tests work like this:
// - The specified code is evaluated in a system principal.
//   `Cu`, `systemPrincipal` and `Services` are provided as global variables.
// - The resulting object is debugged in a system or null principal debuggee,
//   depending on in which list the test is placed.
//   It is tested according to the specified test parameters.
// - An ordinary object that inherits from the resulting one is also debugged.
//   This is just to check that it can be normally debugged even with an unsafe
//   object in the prototype. The specified test parameters do not apply.

// The following tests are defined via properties with the following defaults.
const defaults = {
  // The class of the grip.
  class"Restricted",

  // The stringification of the object
  string: "",

  // Whether the object (not its grip) has class "Function".
  isFunction: false,

  // Whether the grip has a preview property.
  hasPreview: true,

  // Code that assigns the object to be tested into the obj variable.
  code: "var obj = {}",

  // The type of the grip of the prototype.
  protoType: "null",

  // Whether the object has some own string properties.
  hasOwnPropertyNames: false,

  // Whether the object has some own symbol properties.
  hasOwnPropertySymbols: false,

  // The descriptor obtained when retrieving property "x" or Symbol("x").
  property: undefined,

  // Code evaluated after the test, whose result is expected to be true.
  afterTest: "true == true",
};

// The following tests use a system principal debuggee.
const systemPrincipalTests = [
  {
    // Dead objects throw a TypeError when accessing properties.
    class"DeadObject",
    string: "",
    code: `
    var obj = Cu.Sandbox(null);
    Cu.nukeSandbox(obj);
  `,
    property: descriptor({ value: "TypeError" }),
  },
  {
    // This proxy checks that no trap runs (using a second proxy as the handler
    // there is no need to maintain a list of all possible traps).
    class"Proxy",
    string: "",
    code: `
    var trapDidRun = false;
    var obj = new Proxy({}, new Proxy({}, {get: (_, trap) => {
      trapDidRun = true;
      throw new Error("proxy trap '" + trap + "' was called.");
    }}));
  `,
    afterTest: "trapDidRun === false",
  },
  {
    // Like the previous test, but now the proxy has a Function class.
    class"Proxy",
    string: "",
    isFunction: true,
    code: `
    var trapDidRun = false;
    var obj = new Proxy(function(){}, new Proxy({}, {get: (_, trap) => {
      trapDidRun = true;
      throw new Error("proxy trap '" + trap + "' was called.(function)");
    }}));
  `,
    afterTest: "trapDidRun === false",
  },
  {
    // Invisisible-to-debugger objects can't be unwrapped, so we don't know if
    // they are proxies. Thus they shouldn't be accessed.
    class"InvisibleToDebugger: Array",
    string: "",
    hasPreview: false,
    code: `
    var s = Cu.Sandbox(systemPrincipal, {invisibleToDebugger: true});
    var obj = s.eval("[1, 2, 3]");
  `,
  },
  {
    // Like the previous test, but now the object has a Function class.
    class"InvisibleToDebugger: Function",
    string: "",
    isFunction: true,
    hasPreview: false,
    code: `
    var s = Cu.Sandbox(systemPrincipal, {invisibleToDebugger: true});
    var obj = s.eval("(function func(arg){})");
  `,
  },
  {
    // Cu.Sandbox is a WrappedNative that throws when accessing properties.
    class"nsXPCComponents_utils_Sandbox",
    string: "[object nsXPCComponents_utils_Sandbox]",
    code: `var obj = Cu.Sandbox;`,
    protoType: "object",
  },
];

// The following tests run code in a system principal, but the resulting object
// is debugged in a null principal.
const nullPrincipalTests = [
  {
    // The null principal gets undefined when attempting to access properties.
    string: "[object Object]",
    code: `var obj = {x: -1};`,
  },
  {
    // For arrays it's an error instead of undefined.
    string: "[object Object]",
    code: `var obj = [1, 2, 3];`,
    property: descriptor({ value: "Error" }),
  },
  {
    // For functions it's also an error.
    string: "function func(arg){}",
    isFunction: true,
    hasPreview: false,
    code: `var obj = function func(arg){};`,
    property: descriptor({ value: "Error" }),
  },
  {
    // Check that no proxy trap runs.
    string: "[object Object]",
    code: `
    var trapDidRun = false;
    var obj = new Proxy([], new Proxy({}, {get: (_, trap) => {
      trapDidRun = true;
      throw new Error("proxy trap '" + trap + "' was called.");
    }}));
  `,
    property: descriptor({ value: "Error" }),
    afterTest: `trapDidRun === false`,
  },
  {
    // Like the previous test, but now the object is a callable Proxy.
    string: "function () {\n [native code]\n}",
    isFunction: true,
    hasPreview: false,
    code: `
    var trapDidRun = false;
    var obj = new Proxy(function(){}, new Proxy({}, {get: (_, trap) => {
      trapDidRun = true;
      throw new Error("proxy trap '" + trap + "' was called.");
    }}));
  `,
    property: descriptor({ value: "Error" }),
    afterTest: `trapDidRun === false`,
  },
  {
    // Cross-origin Window objects do expose some properties and have a preview.
    string: "[object Object]",
    code: `var obj = Services.appShell.createWindowlessBrowser().document.defaultView;`,
    hasOwnPropertyNames: true,
    hasOwnPropertySymbols: true,
    property: descriptor({ value: "SecurityError" }),
    previewUrl: "about:blank",
  },
  {
    // Cross-origin Location objects do expose some properties and have a preview.
    string: "[object Object]",
    code: `var obj = Services.appShell.createWindowlessBrowser().document.defaultView
                   .location;`,
    hasOwnPropertyNames: true,
    hasOwnPropertySymbols: true,
    property: descriptor({ value: "SecurityError" }),
  },
];

function descriptor(descr) {
  return Object.assign(
    {
      configurable: false,
      writable: false,
      enumerable: false,
      value: undefined,
    },
    descr
  );
}

async function test_unsafe_grips(
  { threadFront, debuggee, isWorkerServer },
  tests
) {
  debuggee.eval(
    // These arguments are tested.
    // eslint-disable-next-line no-unused-vars
    function stopMe(arg1, arg2) {
      debugger;
    }.toString()
  );

  for (let data of tests) {
    data = { ...defaults, ...data };

    // Run the code and test the results.
    const sandbox = Cu.Sandbox(systemPrincipal);
    Object.assign(sandbox, { Services, systemPrincipal, Cu });
    sandbox.eval(data.code);
    debuggee.obj = sandbox.obj;
    const inherits = `Object.create(obj, {
        x: {value: 1},
        [Symbol.for("x")]: {value: 2}
      })`;

    const packet = await executeOnNextTickAndWaitForPause(
      () => debuggee.eval(`stopMe(obj, ${inherits});`),
      threadFront
    );

    const [objGrip, inheritsGrip] = packet.frame.arguments;
    for (const grip of [objGrip, inheritsGrip]) {
      const isUnsafe = grip === objGrip;
      // If `isUnsafe` is true, the parameters in `data` will be used to assert
      // against `objGrip`, the grip of the object `obj` created by the test.
      // Otherwise, the grip will refer to `inherits`, an ordinary object which
      // inherits from `obj`. Then all checks are hardcoded because in every test
      // all methods are expected to work the same on `inheritsGrip`.
      check_grip(grip, data, isUnsafe, isWorkerServer);

      const objClient = threadFront.pauseGrip(grip);
      let response, slice;

      response = await objClient.getPrototypeAndProperties();
      check_properties(response.ownProperties, data, isUnsafe);
      check_symbols(response.ownSymbols, data, isUnsafe);
      check_prototype(response.prototype, data, isUnsafe, isWorkerServer);

      response = await objClient.enumProperties({
        ignoreIndexedProperties: true,
      });
      slice = await response.slice(0, response.count);
      check_properties(slice.ownProperties, data, isUnsafe);

      response = await objClient.enumProperties({});
      slice = await response.slice(0, response.count);
      check_properties(slice.ownProperties, data, isUnsafe);

      response = await objClient.getProperty("x");
      check_property(response.descriptor, data, isUnsafe);

      response = await objClient.enumSymbols();
      slice = await response.slice(0, response.count);
      check_symbol_names(slice.ownSymbols, data, isUnsafe);

      response = await objClient.getProperty(Symbol.for("x"));
      check_symbol(response.descriptor, data, isUnsafe);

      response = await objClient.getPrototype();
      check_prototype(response.prototype, data, isUnsafe, isWorkerServer);
    }

    await threadFront.resume();

    ok(sandbox.eval(data.afterTest), "Check after test passes");
  }
}

function check_grip(grip, data, isUnsafe, isWorkerServer) {
  if (isUnsafe) {
    strictEqual(grip.class, data.class"The grip has the proper class.");
    strictEqual("preview" in grip, data.hasPreview, "Check preview presence.");
    // preview.url isn't populated on worker server.
    if (data.previewUrl && !isWorkerServer) {
      console.trace();
      strictEqual(
        grip.preview.url,
        data.previewUrl,
        `Check preview.url for "${data.code}".`
      );
    }
  } else {
    strictEqual(grip.class"Object""The grip has 'Object' class.");
    ok("preview" in grip, "The grip has a preview.");
  }
}

function check_properties(props, data, isUnsafe) {
  const propNames = Reflect.ownKeys(props);
  check_property_names(propNames, data, isUnsafe);
  if (isUnsafe) {
    deepEqual(props.x, undefined, "The property does not exist.");
  } else {
    strictEqual(props.x.value, 1, "The property has the right value.");
  }
}

function check_property_names(props, data, isUnsafe) {
  if (isUnsafe) {
    strictEqual(
      !!props.length,
      data.hasOwnPropertyNames,
      "Check presence of own string properties."
    );
  } else {
    strictEqual(props.length, 1, "1 own property was retrieved.");
    strictEqual(props[0], "x""The property has the right name.");
  }
}

function check_property(descr, data, isUnsafe) {
  if (isUnsafe) {
    deepEqual(descr, data.property, "Got the right property descriptor.");
  } else {
    strictEqual(descr.value, 1, "The property has the right value.");
  }
}

function check_symbols(symbols, data, isUnsafe) {
  check_symbol_names(symbols, data, isUnsafe);
  if (!isUnsafe) {
    check_symbol(symbols[0].descriptor, data, isUnsafe);
  }
}

function check_symbol_names(props, data, isUnsafe) {
  if (isUnsafe) {
    strictEqual(
      !!props.length,
      data.hasOwnPropertySymbols,
      "Check presence of own symbol properties."
    );
  } else {
    strictEqual(props.length, 1, "1 own symbol property was retrieved.");
    strictEqual(props[0].name, "Symbol(x)""The symbol has the right name.");
  }
}

function check_symbol(descr, data, isUnsafe) {
  if (isUnsafe) {
    deepEqual(
      descr,
      data.property,
      "Got the right symbol property descriptor."
    );
  } else {
    strictEqual(descr.value, 2, "The symbol property has the right value.");
  }
}

function check_prototype(proto, data, isUnsafe, isWorkerServer) {
  const protoGrip = proto && proto.getGrip ? proto.getGrip() : proto;
  if (isUnsafe) {
    deepEqual(protoGrip.type, data.protoType, "Got the right prototype type.");
  } else {
    check_grip(protoGrip, data, true, isWorkerServer);
  }
}

// threadFrontTest uses systemPrincipal by default, but let's be explicit here.
add_task(
  threadFrontTest(
    options => {
      return test_unsafe_grips(options, systemPrincipalTests, "system");
    },
    { principal: systemPrincipal }
  )
);

const nullPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
add_task(
  threadFrontTest(
    options => {
      return test_unsafe_grips(options, nullPrincipalTests, "null");
    },
    { principal: nullPrincipal }
  )
);

93%


¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.