JS: Support enumeration through Object.entries

This commit is contained in:
Asger F
2019-11-15 10:10:32 +00:00
committed by Asger Feldthaus
parent ac2f0a8e11
commit 8af233307a
3 changed files with 123 additions and 18 deletions

View File

@@ -39,29 +39,13 @@ SourceNode getAnEnumeratedArrayElement(SourceNode array) {
* A data flow node that refers to the name of a property obtained by enumerating
* the properties of some object.
*/
class EnumeratedPropName extends DataFlow::Node {
DataFlow::Node object;
EnumeratedPropName() {
exists(ForInStmt stmt |
this = DataFlow::lvalueNode(stmt.getLValue()) and
object = stmt.getIterationDomain().flow()
)
or
exists(CallNode call, string name |
call = globalVarRef("Object").getAMemberCall(name) and
(name = "keys" or name = "getOwnPropertyNames") and
object = call.getArgument(0) and
this = getAnEnumeratedArrayElement(call)
)
}
abstract class EnumeratedPropName extends DataFlow::Node {
/**
* Gets the object whose properties are being enumerated.
*
* For example, gets `src` in `for (var key in src)`.
*/
Node getSourceObject() { result = object }
abstract DataFlow::Node getSourceObject();
/**
* Gets a local reference of the source object.
@@ -86,6 +70,53 @@ class EnumeratedPropName extends DataFlow::Node {
}
}
/**
* Property enumeration through `for-in` for `Object.keys` or `Object.getOwnPropertyName`.
*/
class ForInEnumeratedPropName extends EnumeratedPropName {
DataFlow::Node object;
ForInEnumeratedPropName() {
exists(ForInStmt stmt |
this = DataFlow::lvalueNode(stmt.getLValue()) and
object = stmt.getIterationDomain().flow()
)
or
exists(CallNode call, string name |
call = globalVarRef("Object").getAMemberCall(name) and
(name = "keys" or name = "getOwnPropertyNames") and
object = call.getArgument(0) and
this = getAnEnumeratedArrayElement(call)
)
}
override Node getSourceObject() { result = object }
}
/**
* Property enumeration through `Object.entries`.
*/
class EntriesEnumeratedPropName extends EnumeratedPropName {
CallNode entries;
SourceNode entry;
EntriesEnumeratedPropName() {
entries = globalVarRef("Object").getAMemberCall("entries") and
entry = getAnEnumeratedArrayElement(entries) and
this = entry.getAPropertyRead("0")
}
override DataFlow::Node getSourceObject() {
result = entries.getArgument(0)
}
override PropRead getASourceProp() {
result = super.getASourceProp()
or
result = entry.getAPropertyRead("1")
}
}
/**
* Holds if the properties of `node` are enumerated locally.
*/

View File

@@ -638,6 +638,35 @@ nodes
| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] |
| PrototypePollutionUtility/tests.js:257:55:257:57 | key |
| PrototypePollutionUtility/tests.js:257:55:257:57 | key |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] |
| PrototypePollutionUtility/tests.js:266:13:266:28 | value |
| PrototypePollutionUtility/tests.js:266:13:266:28 | value |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] |
| PrototypePollutionUtility/tests.js:268:30:268:32 | dst |
| PrototypePollutionUtility/tests.js:268:30:268:32 | dst |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:34:268:36 | key |
| PrototypePollutionUtility/tests.js:268:34:268:36 | key |
| PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst |
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst |
| examples/PrototypePollutionUtility.js:1:21:1:23 | src |
@@ -1539,6 +1568,38 @@ edges
| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) |
| PrototypePollutionUtility/tests.js:257:55:257:57 | key | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] |
| PrototypePollutionUtility/tests.js:257:55:257:57 | key | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:268:30:268:32 | dst |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:268:30:268:32 | dst |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:268:34:268:36 | key |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:268:34:268:36 | key |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key |
| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key |
| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value |
| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value |
| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst |
| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst |
| PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] |
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst |
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst |
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst |
@@ -1654,4 +1715,5 @@ edges
| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst |
| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst |
| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | this object |
| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst |
| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst |

View File

@@ -259,3 +259,15 @@ function mergeWithCopy(dst, src) {
}
return result;
}
function copyUsingEntries(dst, src) {
Object.entries(src).forEach(entry => {
let key = entry[0];
let value = entry[1];
if (dst[key]) {
copyUsingEntries(dst[key], value);
} else {
dst[key] = value; // NOT OK
}
});
}