2012-04-22 11 views
5

JavaScript hace que sea fácil sobrescribir las propiedades y funciones del objeto global. Me gustaría encontrar una forma de verificar si la versión original de una propiedad global ha sido reemplazada.Compruebe si una propiedad/función global ha sido sobrescrita en JavaScript

considerar a alguien poner esto en su HTML:

<script type="text/javascript"> 
    window.encodeURIComponent = eval; 
</script> 
<script type="text/javascript" src="myscript.js"></script> 

Si MyScript.js llama a la función encodeURIComponent en alguna parte, y pasará a comportarse de forma impredecible. Entonces, ¿hay alguna manera de verificar dentro de myscript.js si alguien ha sobreescrito esa función antes de usarla?

Respuesta

1

Este es el navegador específica y definitivamente no funcionará para los no funciona, pero:

Llamando al método de una función toString debe producir algo como:

Chrome: 

"function encodeURIComponent() { [native code] }" 

Firefox: 

"function encodeURIComponent() { 
    [native code] 
}" 

IE 7/8/9: 
" 
function encodeURIComponent() { 
    [native code] 
} 
" 

Observe que el nombre de la función coincide con el nombre de la propiedad , y su cuerpo es reemplazado por "[native code]". La idea es eliminar todos los espacios en blanco de esta cadena y compararla con el resultado esperado, "functionxxx(){[nativecode]}".

tengo ni idea de si funciona para todos los navegadores/funciones, de ese ensayo y error:

var pattern = 'function' + propertyName + '(){[nativecode]}'; 
var func = window[propertyName].toString(); 
if(func.replace(/\s+/g, '') !== pattern) { 
    throw new Error("Property window." + propertyName + " has been modified!"); 
} 
6

La única cosa que sé es un enfoque directo con el análisis de la representación de cadena de la función. Normalmente, el código

window.encodeURIComponent.toString() 

debe producir algo como esto:

function encodeURIComponent() { [native code] } 

que puede ser analizado fácilmente para obtener información clave function encodeURIComponent.

Si la función se sobrescribe con eval, como en el ejemplo, que obtendrá:

function eval() { [native code] } 

En general, para el control de window propiedades, puede crear un iframe falso y comparar window.[property].toString() con iframe.contentWindow.[property].toString(). Si la comparación da false, la propiedad ha sido cambiada.

+0

Esta es una manera realmente inteligente y transversal de hacerlo. – sg3s

+0

Gracias Stan. ¿También sabe cómo asegurarse de que la propiedad toString de 'eval' no se haya sobrescrito con algo como' function() {return "function encodeURIComponent() {[native code]}"; } '? –

+0

en lugar de analizar y llamar a 'toString' simplemente puede hacer esto' window.encodeURIComponent.name' .. DE TODOS MODOS hay más método previo para lograr esto http://stackoverflow.com/a/10266791/474290 –

0

hay una manera fácil de hacerlo en JavaScript :) Pero usted tiene que tener acceso al HTML, por lo que no puede utilizar este método en el interior de un script ..

función es un objeto .. para que podamos guardar un enlace a un objeto y simplemente comparar esos enlaces. Solo piense en una función como si fuera un objeto simple. ¿Cómo puedes comparar objetos?

<script type="text/javascript"> 
    var a = window.encodeURIComponent; // a === window.encodeURIComponent -> true 
</script> 
<script type="text/javascript"> 
    window.encodeURIComponent = eval; // a === window.encodeURIComponent -> false 
</script> 
<script type="text/javascript" src="myscript.js"> 
    if (a !== window.encodeURIComponent) 
    { 
     throw new Error('Someone redefined function'); 
    } 
</script> 
3

Una forma interesante de hacer esto dentro de una secuencia de comandos es comparar la función prototipo

Por defecto - typeof window.encodeURIComponent.prototype === "undefined"

Pero si alguien redefine esta función por

window.encodeURIComponent = function() { eval(); } obtendremos

typeof window.encodeURIComponent.prototype === "Object"

PD: este método es más confiable que otros, pero no le dará el 100% de garantía. JavaScript es todos los objetos y todo en tiempo de ejecución .. sólo viven con esta ..

ACTUALIZACIÓN se pueden combinar ambos métodos .. mina y @Stans ..

este ejemplo no funcionan porque yo no estaba 't usando eval - eval también está teniendo prototipo 'indefinido' por defecto .. por lo que se puede hacer esto

window.encodeURIComponent.name === "encodeURIComponent" 
//to make shure that user won't use EVAL 
&& typeof window.encodeURIComponent.prototype === "undefined" 
//to make shure that user won't use self defined function 
+0

Ai_boy, parece que no puedo reproducir eso. 'typeof window.encodeURIComponent.prototype' es' "undefined" 'en ambos casos. –

+0

ver una actualización ... –

0

¿Qué tal esto?

function isNativeWindowProperty(propertyName) { 
    var result = false; 
    var iframe = document.createElement('iframe'); 
    iframe.src = 'javascript:;'; 
    document.getElementsByTagName('body')[0].appendChild(iframe); 
    if (window[propertyName].toString() === iframe.contentWindow[propertyName].toString()) { 
     // check window[propertyName].toString override 
     if (window[propertyName].toString.toString() === iframe.contentWindow[propertyName].toString.toString()) { 
      result = true; 
     } 
    } 
    iframe.parentNode.removeChild(iframe); 
    return result; 
}; 

console.log(isNativeWindowProperty('alert')); // true 

window.alert = function() {}; 
console.log(isNativeWindowProperty('alert')); // false 

window.alert.toString = function() { 
    return 'function alert() { [native code] }'; 
}; 
console.log(isNativeWindowProperty('alert')); // false 
+0

¿Tal vez podría agregar algo de texto para explicar cómo su código responde al queston? – Kmeixner

Cuestiones relacionadas