Skip to content

Commit

Permalink
Support better closure analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Mar 24, 2024
1 parent 7a98677 commit 20e79e9
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 27 deletions.
27 changes: 25 additions & 2 deletions src/analyzer/expr/call/arguments_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,9 +1069,32 @@ fn handle_possibly_matching_inout_param(
);
}

if functionlike_id == &FunctionLikeIdentifier::Function(StrId::PREG_MATCH_WITH_MATCHES)
&& argument_offset == 2
if matches!(
functionlike_id,
FunctionLikeIdentifier::Function(
StrId::PREG_MATCH_WITH_MATCHES | StrId::PREG_MATCH_ALL_WITH_MATCHES
)
) && argument_offset == 2
{
let argument_node = DataFlowNode::get_for_method_argument(
functionlike_id.to_string(statements_analyzer.get_interner()),
0,
Some(statements_analyzer.get_hpos(all_args[1].1.pos())),
Some(statements_analyzer.get_hpos(function_call_pos)),
);

analysis_data
.data_flow_graph
.add_node(argument_node.clone());

analysis_data.data_flow_graph.add_path(
&argument_node,
&out_node,
PathKind::Aggregate,
vec![],
vec![],
);

let argument_node = DataFlowNode::get_for_method_argument(
functionlike_id.to_string(statements_analyzer.get_interner()),
1,
Expand Down
1 change: 1 addition & 0 deletions src/analyzer/expr/call/expression_call_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub(crate) fn analyze(
start_line: 0,
},
);
lambda_storage.user_defined = true;
lambda_storage.params = closure_params
.iter()
.map(|fn_param| {
Expand Down
85 changes: 61 additions & 24 deletions src/analyzer/expr/call/function_call_return_type_fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,6 @@ fn add_dataflow(

// todo conditionally remove taints


let function_call_node = if let GraphKind::WholeProgram(_) = &data_flow_graph.kind {
DataFlowNode::get_for_method_return(
functionlike_id.to_string(statements_analyzer.get_interner()),
Expand Down Expand Up @@ -951,6 +950,7 @@ fn get_special_argument_nodes(
| StrId::BASE64_DECODE
| StrId::URLENCODE
| StrId::URLDECODE
| StrId::GZINFLATE
| StrId::LIB_DICT_FILTER
| StrId::LIB_DICT_FILTER_ASYNC
| StrId::LIB_DICT_FILTER_KEYS
Expand All @@ -963,6 +963,7 @@ fn get_special_argument_nodes(
| StrId::LIB_VEC_FILTER_WITH_KEY
| StrId::LIB_VEC_DROP
| StrId::LIB_VEC_REVERSE
| StrId::LIB_DICT_REVERSE
| StrId::LIB_VEC_UNIQUE
| StrId::LIB_KEYSET_FILTER
| StrId::LIB_KEYSET_FILTER_NULLS
Expand All @@ -980,28 +981,30 @@ fn get_special_argument_nodes(
| StrId::LOG
| StrId::IP2LONG
| StrId::BIN2HEX
| StrId::HEX2BIN => (vec![(0, PathKind::Default)], None),
StrId::LIB_VEC_DIFF
| StrId::HEX2BIN
| StrId::ESCAPESHELLARG => (vec![(0, PathKind::Default)], None),
StrId::LIB_REGEX_FIRST_MATCH => (vec![(0, PathKind::Default)], Some(PathKind::Default)),
StrId::LIB_DICT_SELECT_KEYS
| StrId::LIB_VEC_TAKE
| StrId::LIB_DICT_TAKE
| StrId::LIB_STR_SLICE
| StrId::LIB_STR_FORMAT_NUMBER
| StrId::LIB_DICT_DIFF_BY_KEY
| StrId::NUMBER_FORMAT
| StrId::LIB_DICT_CHUNK
| StrId::LIB_VEC_DIFF
| StrId::LIB_KEYSET_DIFF
| StrId::LIB_KEYSET_INTERSECT
| StrId::LIB_VEC_INTERSECT
| StrId::LIB_VEC_SLICE
| StrId::LIB_VEC_RANGE
| StrId::LIB_VEC_CHUNK
| StrId::LIB_KEYSET_CHUNK
| StrId::LIB_STR_STRIP_PREFIX
| StrId::LIB_STR_STRIP_SUFFIX
| StrId::LIB_STR_REPEAT
| StrId::SUBSTR
| StrId::LIB_DICT_ASSOCIATE
| StrId::LIB_REGEX_FIRST_MATCH => {
(vec![(0, PathKind::Default)], Some(PathKind::Default))
}
StrId::LIB_DICT_SELECT_KEYS
| StrId::LIB_VEC_TAKE
| StrId::LIB_DICT_TAKE
| StrId::LIB_STR_SLICE
| StrId::LIB_STR_FORMAT_NUMBER
| StrId::LIB_DICT_DIFF_BY_KEY => {
| StrId::LIB_DICT_ASSOCIATE => {
(vec![(0, PathKind::Default)], Some(PathKind::Aggregate))
}
StrId::LIB_C_IS_EMPTY
Expand Down Expand Up @@ -1035,7 +1038,10 @@ fn get_special_argument_nodes(
| StrId::GET_CLASS
| StrId::CTYPE_LOWER
| StrId::SHA1
| StrId::MD5 => (vec![(0, PathKind::Aggregate)], None),
| StrId::MD5
| StrId::DIRNAME
| StrId::CRC32
| StrId::FILTER_VAR => (vec![(0, PathKind::Aggregate)], None),
StrId::LIB_MATH_ALMOST_EQUALS
| StrId::LIB_MATH_BASE_CONVERT
| StrId::LIB_MATH_EXP
Expand All @@ -1059,15 +1065,22 @@ fn get_special_argument_nodes(
| StrId::STRPOS
| StrId::SUBSTR_COUNT
| StrId::STRCMP
| StrId::STRNATCASECMP
| StrId::LIB_KEYSET_EQUAL => (vec![], Some(PathKind::Aggregate)),
StrId::LIB_C_CONTAINS
| StrId::LIB_C_CONTAINS_KEY
| StrId::IN_ARRAY
| StrId::PREG_MATCH
| StrId::LIB_REGEX_MATCHES
| StrId::PREG_MATCH_WITH_MATCHES
| StrId::PREG_MATCH_ALL_WITH_MATCHES => (
vec![(0, PathKind::Aggregate), (1, PathKind::Aggregate)],
| StrId::PREG_MATCH_ALL_WITH_MATCHES
| StrId::HASH => (
vec![
(0, PathKind::Aggregate),
(1, PathKind::Aggregate),
(3, PathKind::Aggregate),
(4, PathKind::Aggregate),
],
None,
),
StrId::JSON_ENCODE | StrId::SERIALIZE => (vec![(0, PathKind::Serialize)], None),
Expand All @@ -1087,27 +1100,38 @@ fn get_special_argument_nodes(
None,
)
}
StrId::LIB_STR_REPLACE | StrId::LIB_STR_REPLACE_CI => {
(vec![(0, PathKind::Default), (2, PathKind::Default)], None)
}
StrId::PREG_REPLACE_WITH_COUNT => (
vec![
(0, PathKind::Aggregate),
(1, PathKind::Default),
(2, PathKind::Default),
(0, PathKind::Aggregate),
],
None,
),
StrId::PREG_GREP => (vec![(0, PathKind::Aggregate), (1, PathKind::Default)], None),
StrId::LIB_STR_REPLACE_EVERY => (
vec![
(0, PathKind::Default),
(1, PathKind::UnknownArrayFetch(ArrayDataKind::ArrayValue)),
],
None,
),
StrId::LIB_REGEX_REPLACE => (

StrId::STR_PAD
| StrId::LIB_STR_PAD_LEFT
| StrId::LIB_STR_PAD_RIGHT
| StrId::CHUNK_SPLIT
| StrId::LIB_REGEX_REPLACE
| StrId::LIB_STR_REPLACE
| StrId::LIB_STR_REPLACE_CI => (
vec![
(0, PathKind::Default),
(1, PathKind::Aggregate),
(2, PathKind::Default),
],
None,
),
StrId::STR_PAD | StrId::CHUNK_SPLIT => {
(vec![(0, PathKind::Default), (2, PathKind::Default)], None)
}
StrId::IMPLODE | StrId::JOIN => (
vec![
(0, PathKind::Default),
Expand Down Expand Up @@ -1136,6 +1160,19 @@ fn get_special_argument_nodes(
)],
None,
),
StrId::LIB_VEC_ZIP => (
vec![
(
0,
PathKind::UnknownArrayAssignment(ArrayDataKind::ArrayValue),
),
(
1,
PathKind::UnknownArrayAssignment(ArrayDataKind::ArrayValue),
),
],
None,
),
StrId::PATHINFO => (
vec![
(
Expand Down Expand Up @@ -1176,6 +1213,7 @@ fn get_special_argument_nodes(
PathKind::UnknownArrayAssignment(ArrayDataKind::ArrayValue),
),
(1, PathKind::Aggregate),
(2, PathKind::Aggregate),
],
None,
),
Expand Down Expand Up @@ -1220,7 +1258,6 @@ fn get_special_argument_nodes(
)],
None,
),
StrId::LIB_DICT_CHUNK => (vec![(0, PathKind::Default), (1, PathKind::Aggregate)], None),
StrId::LIB_C_FIRST
| StrId::LIB_C_FIRSTX
| StrId::LIB_C_LAST
Expand Down
2 changes: 1 addition & 1 deletion src/code_info_builder/functionlike_scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ pub(crate) fn get_functionlike(
file_source.file_path,
);

functionlike_info.user_defined = user_defined && name.is_some();
functionlike_info.user_defined = user_defined;
functionlike_info.is_closure = name.is_none();

if let Some(name_pos) = name_pos {
Expand Down
14 changes: 14 additions & 0 deletions src/str/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ fn main() -> Result<()> {
"HH\\Lib\\Dict\\map_with_key",
"HH\\Lib\\Dict\\map_with_key_async",
"HH\\Lib\\Dict\\merge",
"HH\\Lib\\Dict\\reverse",
"HH\\Lib\\Dict\\select_keys",
"HH\\Lib\\Dict\\take",
"HH\\Lib\\Keyset\\chunk",
"HH\\Lib\\Keyset\\diff",
"HH\\Lib\\Keyset\\equal",
"HH\\Lib\\Keyset\\filter",
Expand Down Expand Up @@ -134,6 +136,8 @@ fn main() -> Result<()> {
"HH\\Lib\\Str\\join",
"HH\\Lib\\Str\\length",
"HH\\Lib\\Str\\lowercase",
"HH\\Lib\\Str\\pad_left",
"HH\\Lib\\Str\\pad_right",
"HH\\Lib\\Str\\repeat",
"HH\\Lib\\Str\\replace",
"HH\\Lib\\Str\\replace_ci",
Expand Down Expand Up @@ -171,6 +175,7 @@ fn main() -> Result<()> {
"HH\\Lib\\Vec\\sort",
"HH\\Lib\\Vec\\take",
"HH\\Lib\\Vec\\unique",
"HH\\Lib\\Vec\\zip",
"HH\\MemberOf",
"HH\\Shapes",
"HH\\Traversable",
Expand Down Expand Up @@ -224,20 +229,25 @@ fn main() -> Result<()> {
"convert_uudecode",
"convert_uuencode",
"count",
"crc32",
"ctype_lower",
"date",
"date_format",
"debug_backtrace",
"dirname",
"echo",
"escapeshellarg",
"explode",
"extension",
"file_get_contents",
"filename",
"filter_var",
"fromItems",
"function_exists",
"get_class",
"get_object_vars",
"gzinflate",
"hash",
"hash_equals",
"hash_hmac",
"hex2bin",
Expand Down Expand Up @@ -268,16 +278,19 @@ fn main() -> Result<()> {
"microtime",
"mktime",
"nl2br",
"number_format",
"ord",
"parent",
"password_hash",
"pathinfo",
"preg_filter",
"preg_grep",
"preg_match",
"preg_match_all_with_matches",
"preg_match_with_matches",
"preg_quote",
"preg_replace",
"preg_replace_with_count",
"preg_split",
"print_r",
"printf",
Expand Down Expand Up @@ -310,6 +323,7 @@ fn main() -> Result<()> {
"stripcslashes",
"stripslashes",
"stristr",
"strnatcasecmp",
"strpad",
"strpbrk",
"strpos",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function foo(int $i): void {
$a = (int $b) ==> $b;
$c = $a($i);
echo $c;
}

0 comments on commit 20e79e9

Please sign in to comment.