Skip to content

Commit

Permalink
Handle method calls with field access (#427)
Browse files Browse the repository at this point in the history
A field access example might be a call with
   java.security.SecureRandom.getInstance();
where instead of importing SecureRandom from java.security, the full
package path to access is included thus negating the need to import.

Signed-off-by: Eric Brown <eric.brown@securesauce.dev>
  • Loading branch information
ericwb committed Apr 15, 2024
1 parent acd2283 commit d733f52
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 6 deletions.
20 changes: 14 additions & 6 deletions precli/parsers/java.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ def _get_func_ident(self, node: Node) -> Node:

def visit_local_variable_declaration(self, nodes: list[Node]):
# type_identifier variable_declarator
if nodes[0].type != tokens.TYPE_IDENTIFIER:
if nodes[0].type not in (
tokens.TYPE_IDENTIFIER,
tokens.SCOPED_TYPE_IDENTIFIER,
):
return
if nodes[1].type != tokens.VARIABLE_DECLARATOR:
return
Expand All @@ -126,7 +129,11 @@ def visit_local_variable_declaration(self, nodes: list[Node]):

if (
len(var_nodes) > 1
and var_nodes[0].type == tokens.IDENTIFIER
and var_nodes[0].type
in (
tokens.IDENTIFIER,
tokens.SCOPED_TYPE_IDENTIFIER,
)
and var_nodes[1].type
in (
tokens.METHOD_INVOCATION,
Expand Down Expand Up @@ -216,7 +223,7 @@ def visit_method_invocation(self, nodes: list[Node]):
func_call_qual = method_name

arg_list_node = self.child_by_type(meth_invoke, tokens.ARGUMENT_LIST)
func_call_args = self.get_func_args(arg_list_node)
call_args = self.get_func_args(arg_list_node)

call = Call(
node=meth_invoke,
Expand All @@ -226,7 +233,7 @@ def visit_method_invocation(self, nodes: list[Node]):
var_node=obj_node,
ident_node=method_node,
arg_list_node=arg_list_node,
args=func_call_args,
args=call_args,
)

self.analyze_node(tokens.METHOD_INVOCATION, call=call)
Expand Down Expand Up @@ -283,8 +290,9 @@ def resolve(self, node: Node, default=None):
if symbol is not None:
value = self.join_symbol(nodetext, symbol)
case tokens.FIELD_ACCESS:
# TODO
pass
symbol = Symbol(nodetext, tokens.IDENTIFIER, nodetext)
if symbol is not None:
value = self.join_symbol(nodetext, symbol)
case tokens.IDENTIFIER:
symbol = self.get_qual_name(node)
if symbol is not None:
Expand Down
1 change: 1 addition & 0 deletions precli/parsers/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
PATTERN_LIST = "pattern_list"
EXPRESSION_LIST = "expression_list"
TYPE_IDENTIFIER = "type_identifier"
SCOPED_TYPE_IDENTIFIER = "scoped_type_identifier"
VARIABLE_DECLARATOR = "variable_declarator"
COMPARISON_OPERATOR = "comparison_operator"
ASSERT = "assert"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// level: WARNING
// start_line: 9
// end_line: 9
// start_column: 83
// end_column: 93
public class JavaSecuritySecureRandomSHA1PRNG {
public static void main(String[] args) {
try {
java.security.SecureRandom sr = java.security.SecureRandom.getInstance("SHA1PRNG");
} catch (java.security.NoSuchAlgorithmException e) {
System.err.println("SHA1PRNG random algorithm not available.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def test_rule_meta(self):

@parameterized.expand(
[
"JavaSecuritySecureRandomSHA1PRNG.java",
"SecureRandomDefault.java",
"SecureRandomSHA1PRNG.java",
]
Expand Down

0 comments on commit d733f52

Please sign in to comment.