|
2 | 2 |
|
3 | 3 | import ContentFeature from '../content-feature.js'
|
4 | 4 | import { DDGProxy, getStackTraceOrigins, getStack, matchHostname, injectGlobalStyles, createStyleElement, postDebugMessage, taintSymbol, hasTaintedMethod, taintedOrigins, getTabHostname, isBeingFramed } from '../utils.js'
|
5 |
| -import { defineProperty } from '../wrapper-utils.js' |
| 5 | +import { defineProperty, wrapFunction } from '../wrapper-utils.js' |
6 | 6 | import { wrapScriptCodeOverload } from './runtime-checks/script-overload.js'
|
7 | 7 | import { findClosestBreakpoint } from './runtime-checks/helpers.js'
|
8 | 8 | import { Reflect } from '../captured-globals.js'
|
@@ -473,6 +473,86 @@ function isInterrogatingDebugMessage (matchType, matchedStackDomain, stack, scri
|
473 | 473 | })
|
474 | 474 | }
|
475 | 475 |
|
| 476 | +function isRuntimeElement (element) { |
| 477 | + try { |
| 478 | + return element instanceof DDGRuntimeChecks |
| 479 | + } catch {} |
| 480 | + return false |
| 481 | +} |
| 482 | + |
| 483 | +function overloadGetOwnPropertyDescriptor () { |
| 484 | + const capturedDescriptors = { |
| 485 | + HTMLScriptElement: Object.getOwnPropertyDescriptors(HTMLScriptElement), |
| 486 | + HTMLScriptElementPrototype: Object.getOwnPropertyDescriptors(HTMLScriptElement.prototype) |
| 487 | + } |
| 488 | + /** |
| 489 | + * @param {any} value |
| 490 | + * @returns {string | undefined} |
| 491 | + */ |
| 492 | + function getInterfaceName (value) { |
| 493 | + let interfaceName |
| 494 | + if (value === HTMLScriptElement) { |
| 495 | + interfaceName = 'HTMLScriptElement' |
| 496 | + } |
| 497 | + if (value === HTMLScriptElement.prototype) { |
| 498 | + interfaceName = 'HTMLScriptElementPrototype' |
| 499 | + } |
| 500 | + return interfaceName |
| 501 | + } |
| 502 | + // TODO: Consoldiate with wrapProperty code |
| 503 | + function getInterfaceDescriptor (interfaceValue, interfaceName, propertyName) { |
| 504 | + const capturedInterface = capturedDescriptors[interfaceName] && capturedDescriptors[interfaceName][propertyName] |
| 505 | + const capturedInterfaceOut = { ...capturedInterface } |
| 506 | + if (capturedInterface.get) { |
| 507 | + capturedInterfaceOut.get = wrapFunction(function () { |
| 508 | + if (isRuntimeElement(this)) { |
| 509 | + return this[propertyName] |
| 510 | + } |
| 511 | + return capturedInterface.get.call(this) |
| 512 | + }, capturedInterface.get) |
| 513 | + } |
| 514 | + if (capturedInterface.set) { |
| 515 | + capturedInterfaceOut.set = wrapFunction(function (value) { |
| 516 | + if (isRuntimeElement(this)) { |
| 517 | + this[interfaceName] = value |
| 518 | + return |
| 519 | + } |
| 520 | + return capturedInterface.set.call(this, [value]) |
| 521 | + }, capturedInterface.set) |
| 522 | + } |
| 523 | + return capturedInterfaceOut |
| 524 | + } |
| 525 | + const proxy = new DDGProxy(featureName, Object, 'getOwnPropertyDescriptor', { |
| 526 | + apply (fn, scope, args) { |
| 527 | + const interfaceValue = args[0] |
| 528 | + const interfaceName = getInterfaceName(interfaceValue) |
| 529 | + const propertyName = args[1] |
| 530 | + const capturedInterface = capturedDescriptors[interfaceName] && capturedDescriptors[interfaceName][propertyName] |
| 531 | + if (interfaceName && capturedInterface) { |
| 532 | + return getInterfaceDescriptor(interfaceValue, interfaceName, propertyName) |
| 533 | + } |
| 534 | + return Reflect.apply(fn, scope, args) |
| 535 | + } |
| 536 | + }) |
| 537 | + proxy.overload() |
| 538 | + const proxy2 = new DDGProxy(featureName, Object, 'getOwnPropertyDescriptors', { |
| 539 | + apply (fn, scope, args) { |
| 540 | + const interfaceValue = args[0] |
| 541 | + const interfaceName = getInterfaceName(interfaceValue) |
| 542 | + const capturedInterface = capturedDescriptors[interfaceName] |
| 543 | + if (interfaceName && capturedInterface) { |
| 544 | + const out = {} |
| 545 | + for (const propertyName of Object.getOwnPropertyNames(capturedInterface)) { |
| 546 | + out[propertyName] = getInterfaceDescriptor(interfaceValue, interfaceName, propertyName) |
| 547 | + } |
| 548 | + return out |
| 549 | + } |
| 550 | + return Reflect.apply(fn, scope, args) |
| 551 | + } |
| 552 | + }) |
| 553 | + proxy2.overload() |
| 554 | +} |
| 555 | + |
476 | 556 | function overrideCreateElement (debug) {
|
477 | 557 | const proxy = new DDGProxy(featureName, Document.prototype, 'createElement', {
|
478 | 558 | apply (fn, scope, args) {
|
@@ -576,6 +656,9 @@ export default class RuntimeChecks extends ContentFeature {
|
576 | 656 | if (this.getFeatureSettingEnabled('overloadReplaceChild')) {
|
577 | 657 | overloadReplaceChild()
|
578 | 658 | }
|
| 659 | + if (this.getFeatureSettingEnabled('overloadGetOwnPropertyDescriptor')) { |
| 660 | + overloadGetOwnPropertyDescriptor() |
| 661 | + } |
579 | 662 | }
|
580 | 663 |
|
581 | 664 | injectGenericOverloads () {
|
|
0 commit comments