Skip to content

Commit 3c1e252

Browse files
committedJan 12, 2020
fix: log error for illegal property access only once per property
1 parent 0d5c807 commit 3c1e252

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed
 

‎lib/handlebars/base.js

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Exception from './exception';
33
import { registerDefaultHelpers } from './helpers';
44
import { registerDefaultDecorators } from './decorators';
55
import logger from './logger';
6+
import { resetLoggedProperties } from './internal/proto-access';
67

78
export const VERSION = '4.7.0';
89
export const COMPILER_REVISION = 8;
@@ -78,6 +79,13 @@ HandlebarsEnvironment.prototype = {
7879
},
7980
unregisterDecorator: function(name) {
8081
delete this.decorators[name];
82+
},
83+
/**
84+
* Reset the memory of illegal property accesses that have already been logged.
85+
* @deprecated should only be used in handlebars test-cases
86+
*/
87+
resetLoggedPropertyAccesses() {
88+
resetLoggedProperties();
8189
}
8290
};
8391

‎lib/handlebars/internal/proto-access.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { createNewLookupObject } from './create-new-lookup-object';
22
import * as logger from '../logger';
33

4+
const loggedProperties = Object.create(null);
5+
46
export function createProtoAccessControl(runtimeOptions) {
57
let defaultMethodWhiteList = Object.create(null);
68
defaultMethodWhiteList['constructor'] = false;
@@ -45,12 +47,24 @@ function checkWhiteList(protoAccessControlForType, propertyName) {
4547
if (protoAccessControlForType.defaultValue !== undefined) {
4648
return protoAccessControlForType.defaultValue;
4749
}
48-
// eslint-disable-next-line no-console
49-
logger.log(
50-
'error',
51-
`Handlebars: Access has been denied to resolve the property "${propertyName}" because it is not an "own property" of its parent.\n` +
52-
`You can add a runtime option to disable the check or this warning:\n` +
53-
`See http://localhost:8080/api-reference/runtime-options.html#options-to-control-prototype-access for details`
54-
);
50+
logUnexpecedPropertyAccessOnce(propertyName);
5551
return false;
5652
}
53+
54+
function logUnexpecedPropertyAccessOnce(propertyName) {
55+
if (loggedProperties[propertyName] !== true) {
56+
loggedProperties[propertyName] = true;
57+
logger.log(
58+
'error',
59+
`Handlebars: Access has been denied to resolve the property "${propertyName}" because it is not an "own property" of its parent.\n` +
60+
`You can add a runtime option to disable the check or this warning:\n` +
61+
`See http://localhost:8080/api-reference/runtime-options.html#options-to-control-prototype-access for details`
62+
);
63+
}
64+
}
65+
66+
export function resetLoggedProperties() {
67+
Object.keys(loggedProperties).forEach(propertyName => {
68+
delete loggedProperties[propertyName];
69+
});
70+
}

‎spec/security.js

+21
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ describe('security issues', function() {
190190
return 'returnValue';
191191
};
192192

193+
beforeEach(function() {
194+
handlebarsEnv.resetLoggedPropertyAccesses();
195+
});
196+
193197
afterEach(function() {
194198
sinon.restore();
195199
});
@@ -214,6 +218,23 @@ describe('security issues', function() {
214218
expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
215219
});
216220

221+
it('should only log the warning once', function() {
222+
var spy = sinon.spy(console, 'error');
223+
224+
expectTemplate('{{aMethod}}')
225+
.withInput(new TestClass())
226+
.withCompileOptions(compileOptions)
227+
.toCompileTo('');
228+
229+
expectTemplate('{{aMethod}}')
230+
.withInput(new TestClass())
231+
.withCompileOptions(compileOptions)
232+
.toCompileTo('');
233+
234+
expect(spy.calledOnce).to.be.true();
235+
expect(spy.args[0][0]).to.match(/Handlebars: Access has been denied/);
236+
});
237+
217238
it('can be allowed, which disables the warning', function() {
218239
var spy = sinon.spy(console, 'error');
219240

0 commit comments

Comments
 (0)
Please sign in to comment.