Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright (C) 2011 Google Inc. | 1 // Copyright (C) 2011 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // https://www.apache.org/licenses/LICENSE-2.0 | 7 // https://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 /** | 15 /** |
16 * @fileoverview Monkey patch almost ES5 platforms into a closer | 16 * @fileoverview Monkey patch almost ES5 platforms into a closer |
17 * emulation of full <a href= | 17 * emulation of full <a href= |
18 * "https://code.google.com/p/es-lab/wiki/SecureableES5">Secureable | 18 * "https://code.google.com/p/es-lab/wiki/SecureableES5">Secureable |
19 * ES5</a>. | 19 * ES5</a>. |
20 * | 20 * |
21 * <p>Assumes only ES3, but only proceeds to do useful repairs when | 21 * <p>Assumes only ES3, but only proceeds to do useful repairs when |
22 * the platform is close enough to ES5 to be worth attempting | 22 * the platform is close enough to ES5 to be worth attempting |
23 * repairs. Compatible with almost-ES5, ES5, ES5-strict, and | 23 * repairs. Compatible with almost-ES5, ES5, ES5-strict, and |
24 * anticipated ES6. | 24 * anticipated ES6. |
25 * | 25 * |
26 * <p>Ignore the "...requires ___global_test_function___" below. We | 26 * <p>Ignore the "...requires ___global_test_function___" below. We |
27 * create it, use it, and delete it all within this module. But we | 27 * create it, use it, and delete it all within this module. But we |
28 * need to lie to the linter since it can't tell. | 28 * need to lie to the linter since it can't tell. Likewise ignore the |
29 * "...requires NonexistentGlobal", since we need the attempt to | |
30 * access it to create a ReferenceError. Therefore, we actually | |
31 * require its absence, but the linter doesn't know that. | |
kpreid2
2015/02/17 19:23:07
Given that you've pointed out precedent for using
MarkM
2015/02/17 22:29:15
That worked. See reply below.
| |
29 * | 32 * |
30 * //requires ses.mitigateSrcGotchas | 33 * //requires ses.mitigateSrcGotchas |
31 * //provides ses.ok, ses.okToLoad, ses.getMaxSeverity | 34 * //provides ses.ok, ses.okToLoad, ses.getMaxSeverity |
32 * //provides ses.is, ses.makeDelayedTamperProof | 35 * //provides ses.is, ses.makeDelayedTamperProof |
33 * //provides ses.makeCallerHarmless, ses.makeArgumentsHarmless | 36 * //provides ses.makeCallerHarmless, ses.makeArgumentsHarmless |
34 * //provides ses.noFuncPoison | 37 * //provides ses.noFuncPoison |
35 * //provides ses.verifyStrictFunctionBody | 38 * //provides ses.verifyStrictFunctionBody |
36 * | 39 * |
37 * @author Mark S. Miller | 40 * @author Mark S. Miller |
38 * @requires ___global_test_function___, ___global_valueOf_function___ | 41 * @requires ___global_test_function___, ___global_valueOf_function___ |
39 * @requires JSON, eval, this | 42 * @requires JSON, eval, this |
40 * @requires navigator, document, DOMException | 43 * @requires navigator, document, DOMException |
44 * @requires NonexistentGlobal | |
41 * @overrides ses, repairES5Module | 45 * @overrides ses, repairES5Module |
42 * @overrides RegExp, WeakMap, Object, parseInt | 46 * @overrides RegExp, WeakMap, Object, parseInt |
43 */ | 47 */ |
44 var RegExp; | 48 var RegExp; |
45 var ses; | 49 var ses; |
46 | 50 |
47 /** | 51 /** |
48 * <p>Qualifying platforms generally include all JavaScript platforms | 52 * <p>Qualifying platforms generally include all JavaScript platforms |
49 * shown on <a href="http://kangax.github.com/es5-compat-table/" | 53 * shown on <a href="http://kangax.github.com/es5-compat-table/" |
50 * >ECMAScript 5 compatibility table</a> that implement {@code | 54 * >ECMAScript 5 compatibility table</a> that implement {@code |
(...skipping 3129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3180 } else { | 3184 } else { |
3181 return 'Unexpected prototype identity from setting a function\'s ' + | 3185 return 'Unexpected prototype identity from setting a function\'s ' + |
3182 'prototype with defineProperty.'; | 3186 'prototype with defineProperty.'; |
3183 } | 3187 } |
3184 } else { | 3188 } else { |
3185 return 'Unexpected result of setting a function\'s prototype ' + | 3189 return 'Unexpected result of setting a function\'s prototype ' + |
3186 'with defineProperty: ' + typeof bar.prototype; | 3190 'with defineProperty: ' + typeof bar.prototype; |
3187 } | 3191 } |
3188 } | 3192 } |
3189 | 3193 |
3194 /** | |
3195 * Tests for https://bugzilla.mozilla.org/show_bug.cgi?id=1125389 | |
3196 * which is a Firefox specific bug that enables one to extend | |
3197 * objects that were supposedly made non-extensible. | |
3198 * | |
3199 * <p>We use ReferenceError rather than the more traditional | |
3200 * TypeError below (by changing the right side of the assignment to, | |
3201 * for example 1) since doing so no longer provokes the bug on FF35. | |
3202 */ | |
3203 function test_NON_EXTENSIBLES_EXTENSIBLE() { | |
3204 function Obj() { | |
3205 this.x = 0; | |
3206 Object.preventExtensions(this); | |
3207 } | |
3208 var i = 0; | |
3209 function test() { | |
3210 var A = new Obj(); | |
3211 while (i < 2000) { | |
3212 i++; | |
3213 if (Object.isExtensible(A)) { | |
3214 return; | |
3215 } | |
3216 } | |
3217 A.length1 = NonexistentGlobal; | |
kpreid2
2015/02/17 19:23:07
Will this also provoke the bug if we use an actual
MarkM
2015/02/17 22:29:15
Good intuition and good news:
Not only does an ex
| |
3218 } | |
3219 try { | |
3220 test(); | |
3221 } catch (e) { | |
3222 if (e instanceof ReferenceError && i === 2000) { | |
3223 return false; | |
3224 } else { | |
3225 return 'Unexpected error: ' + e; | |
3226 } | |
3227 } | |
3228 return true; | |
3229 } | |
3230 | |
3190 ////////////////////// Repairs ///////////////////// | 3231 ////////////////////// Repairs ///////////////////// |
3191 // | 3232 // |
3192 // Each repair_NAME function exists primarily to repair the problem | 3233 // Each repair_NAME function exists primarily to repair the problem |
3193 // indicated by the corresponding test_NAME function. But other test | 3234 // indicated by the corresponding test_NAME function. But other test |
3194 // failures can still trigger a given repair. | 3235 // failures can still trigger a given repair. |
3195 | 3236 |
3196 | 3237 |
3197 var call = Function.prototype.call; | 3238 var call = Function.prototype.call; |
3198 var apply = Function.prototype.apply; | 3239 var apply = Function.prototype.apply; |
3199 | 3240 |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3818 // conflicting with the caller-specified property names, without | 3859 // conflicting with the caller-specified property names, without |
3819 // needing to examine props twice. | 3860 // needing to examine props twice. |
3820 if (props !== undefined) { | 3861 if (props !== undefined) { |
3821 Object.defineProperties(o, props); | 3862 Object.defineProperties(o, props); |
3822 } | 3863 } |
3823 return o; | 3864 return o; |
3824 } | 3865 } |
3825 }); | 3866 }); |
3826 } | 3867 } |
3827 | 3868 |
3869 /** | |
3870 * According to | |
3871 * https://bugzilla.mozilla.org/show_bug.cgi?id=1125389#c28 comment 28 | |
3872 * <blockquote> | |
3873 * <blockquote> | |
3874 * [...] is there anything that content script could do to prevent | |
3875 * this bug from occurring? | |
3876 * </blockquote> | |
3877 * [...] If the object which preventExtensions is called on has | |
3878 * any properties which are non-configurable or non-writable | |
3879 * then the bug won't impact anything (so calling seal() or | |
3880 * freeze() on an object with at least one property shouldn't be | |
3881 * able to trigger this bug) | |
3882 * </blockquote> | |
3883 * | |
3884 * <p>WeakMap.js, if it needs to install a WeakMap emulation, does | |
3885 * so by adding a hidden own property to objects at the time they | |
3886 * would be made non-extensible, by monkey patching those functions | |
3887 * that would make them non-extensible. It also monkey patches those | |
3888 * functions that would reveal non-enumerable own properties, so | |
3889 * that they don't reveal this hidden property. | |
3890 * | |
3891 * <p>Were both this repair and the WeakMap emulation of more long | |
3892 * term interest, we should find a way to reuse this monkey patching | |
3893 * logic, so the same monkey patching could serve both purposes. As | |
3894 * it is, this repair becomes unneeded as of FF36, as the underlying | |
3895 * problem is fixed there, so we expediently that part of | |
3896 * WeakMap.js's logic without worrying about reusable | |
3897 * abstractions. Unlike the WeakMap fix, here, the hidden property | |
3898 * need not be unguessage, but only resistent to accidental | |
3899 * collision. If the WeakMap installation repair happens on top of | |
3900 * this one, they should compose fine. | |
3901 */ | |
3902 function repair_NON_EXTENSIBLES_EXTENSIBLE() { | |
3903 var hop = Object.prototype.hasOwnProperty; | |
3904 var gopn = Object.getOwnPropertyNames; | |
3905 var defProp = Object.defineProperty; | |
3906 var isExtensible = Object.isExtensible; | |
3907 | |
3908 var BOGUS_NAME = '___j9d04gcuzydmfgvi___'; | |
3909 | |
3910 function isNotBogusName(name) { return name !== BOGUS_NAME; } | |
3911 | |
3912 defProp(Object, 'getOwnPropertyNames', { | |
kpreid2
2015/02/17 19:23:07
All property descriptors should be configurable:tr
MarkM
2015/02/17 22:29:15
Added comment both here and in WeakMap.js explaini
| |
3913 value: function nonBogusGetOwnPropertyNames(obj) { | |
3914 return gopn(obj).filter(isNotBogusName); | |
kpreid2
2015/02/17 19:23:07
Worth noting that this is not sound in a writable-
MarkM
2015/02/17 22:29:15
Done.
| |
3915 } | |
3916 }); | |
3917 if ('getPropertyNames' in Object) { | |
3918 var originalGetPropertyNames = Object.getPropertyNames; | |
3919 defProp(Object, 'getPropertyNames', { | |
3920 value: function nonBogusGetPropertyNames(obj) { | |
3921 return originalGetPropertyNames(obj).filter(isNotBogusName); | |
3922 } | |
3923 }); | |
3924 } | |
3925 | |
3926 function makeBogus(obj) { | |
kpreid2
2015/02/17 19:23:07
Unhelpful function name, sounds constructorish. Ho
MarkM
2015/02/17 22:29:15
Done.
| |
3927 if (obj !== Object(obj)) { return; } | |
3928 if (!Object.isExtensible(obj)) { return; } | |
3929 defProp(obj, BOGUS_NAME, { | |
3930 value: 'BOGUS', | |
3931 writable: false, | |
3932 enumerable: false, | |
3933 configurable: false | |
3934 }); | |
3935 } | |
3936 | |
3937 var oldFreeze = Object.freeze; | |
3938 defProp(Object, 'freeze', { | |
3939 value: function bogosifyingFreeze(obj) { | |
3940 makeBogus(obj); | |
3941 return oldFreeze(obj); | |
3942 } | |
3943 }); | |
3944 | |
3945 var oldSeal = Object.seal; | |
3946 defProp(Object, 'seal', { | |
3947 value: function bogosifyingSeal(obj) { | |
3948 makeBogus(obj); | |
3949 return oldSeal(obj); | |
3950 } | |
3951 }); | |
3952 | |
3953 var oldPreventExtensions = Object.preventExtensions; | |
3954 defProp(Object, 'preventExtensions', { | |
3955 value: function bogosifyingPreventExtensions(obj) { | |
3956 makeBogus(obj); | |
3957 return oldPreventExtensions(obj); | |
3958 } | |
3959 }); | |
3960 } | |
3961 | |
3828 ////////////////////// Generic tests/repairs ///////////////////// | 3962 ////////////////////// Generic tests/repairs ///////////////////// |
3829 // | 3963 // |
3830 // These are tests and repairs which follow a pattern, such that it is | 3964 // These are tests and repairs which follow a pattern, such that it is |
3831 // more practical to define them programmatically. | 3965 // more practical to define them programmatically. |
3832 | 3966 |
3833 function arrayPutProblem(destination, | 3967 function arrayPutProblem(destination, |
3834 prop, testArgs, i, expected, kind, opt_repair) { | 3968 prop, testArgs, i, expected, kind, opt_repair) { |
3835 var pos = ['first', 'last'][i]; | 3969 var pos = ['first', 'last'][i]; |
3836 var descs = { | 3970 var descs = { |
3837 readonly: {writable: false, configurable: false}, | 3971 readonly: {writable: false, configurable: false}, |
(...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5002 id: 'NUMERIC_PROPERTIES_INVISIBLE', | 5136 id: 'NUMERIC_PROPERTIES_INVISIBLE', |
5003 description: 'Numeric properties not reflectable on create()d objects', | 5137 description: 'Numeric properties not reflectable on create()d objects', |
5004 test: test_NUMERIC_PROPERTIES_INVISIBLE, | 5138 test: test_NUMERIC_PROPERTIES_INVISIBLE, |
5005 repair: repair_NUMERIC_PROPERTIES_INVISIBLE, | 5139 repair: repair_NUMERIC_PROPERTIES_INVISIBLE, |
5006 preSeverity: severities.UNSAFE_SPEC_VIOLATION, | 5140 preSeverity: severities.UNSAFE_SPEC_VIOLATION, |
5007 canRepair: true, | 5141 canRepair: true, |
5008 urls: ['http://webreflection.blogspot.co.uk/2014/04/all-ie-objects-are-bro ken.html'], | 5142 urls: ['http://webreflection.blogspot.co.uk/2014/04/all-ie-objects-are-bro ken.html'], |
5009 // TODO(kpreid): link Microsoft info page when available | 5143 // TODO(kpreid): link Microsoft info page when available |
5010 sections: ['8.12.6'], | 5144 sections: ['8.12.6'], |
5011 tests: [] // TODO(kpreid): contribute tests | 5145 tests: [] // TODO(kpreid): contribute tests |
5146 }, | |
5147 { | |
5148 id: 'NON_EXTENSIBLES_EXTENSIBLE', | |
5149 description: 'Non-extensible objects can be extended', | |
5150 test: test_NON_EXTENSIBLES_EXTENSIBLE, | |
5151 repair: repair_NON_EXTENSIBLES_EXTENSIBLE, | |
5152 preSeverity: severities.NOT_ISOLATED, | |
5153 canRepair: true, | |
5154 urls: ['https://bugzilla.mozilla.org/show_bug.cgi?id=1125389', | |
5155 'https://code.google.com/p/google-caja/issues/detail?id=1954'], | |
5156 sections: [], | |
5157 tests: [] | |
5012 } | 5158 } |
5013 ]; | 5159 ]; |
5014 | 5160 |
5015 // SPLICE_PUT_IGNORES_FIRST_READONLY | 5161 // SPLICE_PUT_IGNORES_FIRST_READONLY |
5016 // SPLICE_PUT_DOESNT_THROW_FIRST_READONLY | 5162 // SPLICE_PUT_DOESNT_THROW_FIRST_READONLY |
5017 // SPLICE_PUT_IGNORES_FIRST_NON_WRITABLE | 5163 // SPLICE_PUT_IGNORES_FIRST_NON_WRITABLE |
5018 // SPLICE_PUT_DOESNT_THROW_FIRST_NON_WRITABLE | 5164 // SPLICE_PUT_DOESNT_THROW_FIRST_NON_WRITABLE |
5019 // SPLICE_PUT_IGNORES_LAST_READONLY | 5165 // SPLICE_PUT_IGNORES_LAST_READONLY |
5020 // SPLICE_PUT_DOESNT_THROW_LAST_READONLY | 5166 // SPLICE_PUT_DOESNT_THROW_LAST_READONLY |
5021 arrayPutProblem(supportedProblems, | 5167 arrayPutProblem(supportedProblems, |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5157 ses.es5ProblemReports = indexedReports; | 5303 ses.es5ProblemReports = indexedReports; |
5158 } catch (err) { | 5304 } catch (err) { |
5159 ses._repairer.updateMaxSeverity(ses.severities.NOT_SUPPORTED); | 5305 ses._repairer.updateMaxSeverity(ses.severities.NOT_SUPPORTED); |
5160 var during = ses._repairer.wasDoing(); | 5306 var during = ses._repairer.wasDoing(); |
5161 logger.error('ES5 Repair ' + during + 'failed with: ', err); | 5307 logger.error('ES5 Repair ' + during + 'failed with: ', err); |
5162 } | 5308 } |
5163 | 5309 |
5164 logger.reportMax(); | 5310 logger.reportMax(); |
5165 | 5311 |
5166 })(this); | 5312 })(this); |
OLD | NEW |