Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions src/__tests__/ObjectStateMutations-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,29 @@ describe('ObjectStateMutations', () => {
});
});

it('can remove dot notation array changes from the server when value is undefined', () => {
const serverData = {
items: [
{ value: 'a', count: 5 },
{ value: 'b', count: 1 },
],
};
ObjectStateMutations.commitServerChanges(
serverData,
{},
{
'items.0.count': 15,
'items.1.count': undefined,
}
);
expect(serverData).toEqual({
items: [
{ value: 'a', count: 15 },
{ value: 'b' },
],
});
});

it('can commit dot notation array changes from the server to empty serverData', () => {
const serverData = {};
ObjectStateMutations.commitServerChanges(
Expand Down Expand Up @@ -366,6 +389,29 @@ describe('ObjectStateMutations', () => {
delete Object.prototype.malicious;
});

it('should not pollute Object.prototype in estimateAttribute with malicious attribute names', () => {
const testObj = {};

const serverData = {};
const pendingOps = [
{
__proto__: new ParseOps.SetOp({ polluted: 'yes' }),
constructor: new ParseOps.SetOp({ malicious: 'data' }),
},
];

ObjectStateMutations.estimateAttribute(serverData, pendingOps, {
className: 'TestClass',
id: 'test123',
}, '__proto__');

// Verify Object.prototype was not polluted
expect(testObj.polluted).toBeUndefined();
expect(testObj.malicious).toBeUndefined();
expect({}.polluted).toBeUndefined();
expect({}.malicious).toBeUndefined();
});

it('should not pollute Object.prototype in estimateAttributes with malicious attribute names', () => {
const testObj = {};

Expand All @@ -389,13 +435,69 @@ describe('ObjectStateMutations', () => {
expect({}.malicious).toBeUndefined();
});

it('should not pollute Object.prototype in setServerData with malicious attribute names', () => {
const testObj = {};

const serverData = {};
const attributes = {
__proto__: { polluted: 'yes' },
constructor: { malicious: 'data' },
};

ObjectStateMutations.setServerData(serverData, attributes);

// Verify Object.prototype was not polluted
expect(testObj.polluted).toBeUndefined();
expect(testObj.malicious).toBeUndefined();
expect({}.polluted).toBeUndefined();
expect({}.malicious).toBeUndefined();
});

it('should not pollute Object.prototype in mergeFirstPendingState with malicious attribute names', () => {
const testObj = {};
const pendingOps = [
{
__proto__: new ParseOps.SetOp({ polluted: 'yes' }),
constructor: new ParseOps.SetOp({ malicious: 'data' }),
},
];

ObjectStateMutations.mergeFirstPendingState(pendingOps);

// Verify Object.prototype was not polluted
expect(testObj.polluted).toBeUndefined();
expect(testObj.malicious).toBeUndefined();
expect({}.polluted).toBeUndefined();
expect({}.malicious).toBeUndefined();
});

it('should not pollute Object.prototype in setPendingOp with malicious attribute names', () => {
const testObj = {};
const pendingOps = [
{
__proto__: new ParseOps.SetOp({ polluted: 'yes' }),
constructor: new ParseOps.SetOp({ malicious: 'data' }),
},
];

ObjectStateMutations.setPendingOp(pendingOps, '__proto__', new ParseOps.SetOp({ polluted: 'foo' }));

// Verify Object.prototype was not polluted
expect(testObj.polluted).toBeUndefined();
expect(testObj.malicious).toBeUndefined();
expect({}.polluted).toBeUndefined();
expect({}.malicious).toBeUndefined();
});

it('should not pollute Object.prototype in commitServerChanges with nested __proto__ path', () => {
const testObj = {};

const serverData = {};
const objectCache = {};
ObjectStateMutations.commitServerChanges(serverData, objectCache, {
'__proto__.polluted': 'exploited',
__proto__: { polluted: 'yes' },
constructor: { malicious: 'data' },
});

// Verify Object.prototype was not polluted
Expand Down