diff --git a/rules/cpp/security/missing-nul-cpp-string-memcpy-cpp.yml b/rules/cpp/security/missing-nul-cpp-string-memcpy-cpp.yml new file mode 100644 index 00000000..5191c61c --- /dev/null +++ b/rules/cpp/security/missing-nul-cpp-string-memcpy-cpp.yml @@ -0,0 +1,404 @@ +id: missing-nul-cpp-string-memcpy-copy-cpp +language: cpp +severity: warning +message: >- + The number of bytes copied from `$STR` does not include the NUL + terminator. This can lead to an out-of-bounds read and information + disclosure. One extra byte should be added to the length to ensure that + the NUL terminator is copied. +note: >- + [CWE-125]: Out-of-bounds Read + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator + +ast-grep-essentials: true + +rule: + any: + - kind: qualified_identifier + - kind: identifier + pattern: $MEMFUNC + regex: ^(memcpy|wmemcpy|memmove|wmemmove|std::memcpy|std::wmemcpy|std::memmove|std::wmemmove)$ + inside: + stopBy: end + any: + - kind: call_expression + all: + - has: + any: + - kind: qualified_identifier + - kind: identifier + nthChild: 1 + pattern: $MEMFUNC + - has: + kind: argument_list + nthChild: 2 + all: + - has: + pattern: $DEST + nthChild: + position: 1 + ofRule: + not: + kind: comment + - has: + pattern: $STR.c_str() + nthChild: + position: 2 + ofRule: + not: + kind: comment + - has: + pattern: strlen($STR.c_str()) + nthChild: + position: 3 + ofRule: + not: + kind: comment + - not: + has: + nthChild: + position: 4 + ofRule: + not: + kind: comment + # - pattern: $MEMFUNC($DEST, $STR.c_str(), strlen($STR.c_str())) + any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - kind: call_expression + all: + - has: + any: + - kind: qualified_identifier + - kind: identifier + nthChild: 1 + pattern: $MEMFUNC + - has: + kind: argument_list + nthChild: 2 + all: + - has: + pattern: $DEST + nthChild: + position: 1 + ofRule: + not: + kind: comment + - has: + pattern: $STR.c_str() + nthChild: + position: 2 + ofRule: + not: + kind: comment + - has: + pattern: $STR.size() + nthChild: + position: 3 + ofRule: + not: + kind: comment + - not: + has: + nthChild: + position: 4 + ofRule: + not: + kind: comment + # pattern: $MEMFUNC($DEST, $STR.c_str(), $STR.size()) + any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - kind: call_expression + all: + - has: + pattern: $MEMFUNC + any: + - kind: qualified_identifier + - kind: identifier + nthChild: 1 + - has: + kind: argument_list + nthChild: 2 + all: + - has: + pattern: $DEST + nthChild: + position: 1 + ofRule: + not: + kind: comment + - has: + pattern: $STR.c_str() + nthChild: + position: 2 + ofRule: + not: + kind: comment + - has: + pattern: $STR.length() + nthChild: + position: 3 + ofRule: + not: + kind: comment + - not: + has: + nthChild: + position: 4 + ofRule: + not: + kind: comment + # pattern: $MEMFUNC($DEST, $STR.c_str(), $STR.length()) + any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - kind: call_expression + all: + - has: + nthChild: 1 + any: + - kind: qualified_identifier + - kind: identifier + pattern: $MEMFUNC + - has: + nthChild: 2 + kind: argument_list + all: + - has: + pattern: $DEST + nthChild: + position: 1 + ofRule: + not: + kind: comment + - has: + pattern: $STR.c_str() + nthChild: + position: 2 + ofRule: + not: + kind: comment + - has: + pattern: $LEN + nthChild: + position: 3 + ofRule: + not: + kind: comment + - not: + has: + nthChild: + position: 4 + ofRule: + not: + kind: comment + # pattern: $MEMFUNC($DEST, $STR.c_str(), $LEN) + - all: + - any: + - follows: + stopBy: end + any: + - pattern: $LEN = strlen($STR.c_str()); + - pattern: $SET $LEN = strlen($STR.c_str()); + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $LEN = strlen($STR.c_str()); + - pattern: $SET $LEN = strlen($STR.c_str()); + - inside: + stopBy: end + follows: + stopBy: end + kind: declaration + has: + kind: init_declarator + all: + - has: + kind: identifier + pattern: $LEN + - has: + kind: call_expression + pattern: from.size() + - any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - kind: call_expression + all: + - has: + any: + - kind: qualified_identifier + - kind: identifier + nthChild: 1 + pattern: $MEMFUNC + - has: + kind: argument_list + all: + - has: + pattern: $DEST + nthChild: + position: 1 + ofRule: + not: + kind: comment + - has: + pattern: $STR.c_str() + nthChild: + position: 2 + ofRule: + not: + kind: comment + - has: + pattern: $LEN + nthChild: + position: 3 + ofRule: + not: + kind: comment + - not: + has: + nthChild: + position: 4 + ofRule: + not: + kind: comment + # pattern: $MEMFUNC($DEST, $STR.c_str(), $LEN) + follows: + stopBy: end + any: + - pattern: $LEN = $STR.size(); + - pattern: $SET $LEN = $STR.size(); + any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - kind: call_expression + all: + - has: + any: + - kind: qualified_identifier + - kind: identifier + nthChild: 1 + pattern: $MEMFUNC + - has: + kind: argument_list + all: + - has: + pattern: $DEST + nthChild: + position: 1 + ofRule: + not: + kind: comment + - has: + pattern: $STR.c_str() + nthChild: + position: 2 + ofRule: + not: + kind: comment + - has: + pattern: $LEN + nthChild: + position: 3 + ofRule: + not: + kind: comment + - not: + has: + nthChild: + position: 4 + ofRule: + not: + kind: comment + # pattern: $MEMFUNC($DEST, $STR.c_str(), $LEN) + - any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $LEN = $STR.length(); + - pattern: $SET $LEN = $STR.length(); + - follows: + stopBy: end + any: + - pattern: $LEN = $STR.length(); + - pattern: $SET $LEN = $STR.length(); + any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; + - follows: + stopBy: end + any: + - pattern: $TYPE $DEST[$DIM] = $$$; + - pattern: $TYPE $DEST[$DIM]; + - pattern: $TYPE *$DEST = $$$; diff --git a/rules/cpp/security/string-view-temporary-string-cpp.yml b/rules/cpp/security/string-view-temporary-string-cpp.yml new file mode 100644 index 00000000..874d9df0 --- /dev/null +++ b/rules/cpp/security/string-view-temporary-string-cpp.yml @@ -0,0 +1,943 @@ +id: string-view-temporary-string-cpp +language: Cpp +severity: warning +message: >- + This `std::string_view` is constructed from a temporary `std::string`. + The `std::string` value is immeadiately destroyed after assignment and + accessing data through the `std::string_view` will trigger a + use-after-free. +note: >- + [CWE-416] Use After Free. + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM50-CPP.+Do+not+access+freed+memory + +ast-grep-essentials: true + +utils: + $VAR = std::to_string(...): + # $VAR = std::to_string(...); + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^(string_view|wstring_view)$ + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: qualified_identifier + regex: ^std::to_string$ + - has: + stopBy: neighbor + kind: argument_list + + $VAR = $EXPR.substr(...): + # $VAR = std::to_string(...); + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^(string_view|wstring_view)$ + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + regex: ^(string.substr|wstring.substr)$ + - has: + stopBy: neighbor + kind: argument_list + + $VAR = $EXPR + ...: + # $VAR = $EXPR + ... + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^(string_view|wstring_view)$ + - has: + stopBy: neighbor + kind: binary_expression + has: + stopBy: neighbor + kind: identifier + regex: ^(wstring|string)$ + nthChild: 1 + + $VAR = "..." + $EXPR: + # $VAR = "..." + $EXPR + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^(string_view|wstring_view)$ + - has: + stopBy: end + kind: binary_expression + all: + - has: + stopBy: end + kind: string_literal + nthChild: 1 + - has: + stopBy: end + kind: identifier + regex: ^(string|wstring)$ + + $VAR_instance = "..." + $EXPR: + # $VAR_instance = "..." + $EXPR + kind: expression_statement + all: + - has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $VAR_INSTANCE + - has: + stopBy: neighbor + kind: binary_expression + all: + - has: + stopBy: neighbor + kind: string_literal + - has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - any: + - inside: + stopBy: end + follows: + stopBy: end + kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + kind: init_declarator + has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - any: + - inside: + stopBy: end + follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(string_view|basic_string_view<.*>|std::basic_string_view<.*>|std::string_view|std::wstring_view|wstring_view)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $VAR_INSTANCE + + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(string_view|basic_string_view<.*>|std::basic_string_view<.*>|std::string_view|std::wstring_view|wstring_view)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $VAR_INSTANCE + + $VAR_instance = $EXPR_instance + ...: + kind: expression_statement + all: + - has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $VAR_INSTANCE + - has: + stopBy: neighbor + kind: binary_expression + has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - any: + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: init_declarator + has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - inside: + stopBy: end + follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(string_view|basic_string_view<.*>|std::basic_string_view<.*>|std::string_view|std::wstring_view|wstring_view)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $VAR_INSTANCE + + $VAR_instance = $EXPR_instance.substr(...): + # $VAR = std::to_string(...); + kind: expression_statement + all: + - has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $VAR_INSTANCE + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: end + kind: field_expression + all: + - any: + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + nthChild: 1 + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: field_identifier + regex: ^substr$ + - has: + stopBy: neighbor + kind: argument_list + - any: + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: init_declarator + has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - inside: + stopBy: end + follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(string_view|basic_string_view<.*>|std::basic_string_view<.*>|std::string_view|std::wstring_view|wstring_view)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $VAR_INSTANCE + + $VAR_instance = std::to_string(...): + # $VAR = std::to_string(...); + kind: expression_statement + all: + - has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $VAR_INSTANCE + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: end + kind: qualified_identifier + regex: ^std::to_string$ + - has: + stopBy: neighbor + kind: argument_list + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(string_view|basic_string_view<.*>|std::basic_string_view<.*>|std::string_view|std::wstring_view|wstring_view)$ + nthChild: 1 + - has: + stopBy: neighbor + kind: identifier + pattern: $VAR_INSTANCE + + $VAR(std::to_string(...)): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(basic_string_view<.*>|std::basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: qualified_identifier + regex: ^std::to_string$ + - has: + stopBy: neighbor + kind: argument_list + + $VAR(std::to_string(...))_as_declaration: + kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(basic_string_view<.*>|std::basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: qualified_identifier + regex: ^std::to_string$ + - has: + stopBy: neighbor + kind: argument_list + + $VAR($EXPR + ...): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(basic_string_view<.*>|std::basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: end + kind: binary_expression + has: + stopBy: neighbor + kind: identifier + regex: ^(wstring|string)$ + nthChild: 1 + + $VAR($EXPR_instance + ...): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(std::basic_string_view<.*>|basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: end + kind: argument_list + has: + stopBy: neighbor + kind: binary_expression + has: + stopBy: end + kind: identifier + nthChild: 1 + pattern: $EXPR_INSTANCE + - any: + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: init_declarator + has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - inside: + stopBy: end + follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + pattern: $EXPR_INSTANCE + + $VAR("..." + $EXPR_instance ): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(basic_string_view<.*>|std::basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: end + kind: argument_list + has: + stopBy: end + kind: binary_expression + all: + - has: + stopBy: neighbor + kind: string_literal + nthChild: 1 + has: + stopBy: neighbor + kind: string_content + - has: + stopBy: end + kind: identifier + nthChild: 2 + pattern: $EXPR_INSTANCE + - any: + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: init_declarator + has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - inside: + stopBy: end + follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + pattern: $EXPR_INSTANCE + + $VAR("..." + $EXPR): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(basic_string_view<.*>|std::basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: end + kind: argument_list + has: + stopBy: neighbor + kind: binary_expression + all: + - has: + stopBy: neighbor + kind: string_literal + nthChild: 1 + has: + stopBy: neighbor + kind: string_content + - has: + stopBy: end + kind: identifier + nthChild: 2 + regex: ^(wstring|string)$ + + $VAR($EXPR.substr(...)): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: end + kind: argument_list + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + regex: ^(string.substr|wstring.substr)$ + - has: + stopBy: neighbor + kind: argument_list + + $VAR($EXPR_instance.substr(...)): + kind: call_expression + all: + - has: + stopBy: neighbor + regex: ^(basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view|std::basic_string_view<.*>)$ + - has: + stopBy: end + kind: argument_list + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: end + kind: field_expression + all: + - any: + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + nthChild: 1 + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: field_identifier + regex: ^substr$ + - has: + stopBy: neighbor + kind: argument_list + - any: + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: init_declarator + has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - inside: + stopBy: end + follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: end + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + pattern: $EXPR_INSTANCE + + $VAR_instance $VAR = "..." + $EXPR: + # $VAR_instance $VAR = "..." + $EXPR + kind: declaration + all: + - has: + kind: type_identifier + regex: ^(string_view|basic_string_view<.*>|std::basic_string_view<.*>|std::string_view|std::wstring_view|wstring_view)$ + - has: + stopBy: neighbor + kind: init_declarator + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $VAR_INSTANCE + - has: + stopBy: neighbor + kind: binary_expression + all: + - has: + stopBy: neighbor + kind: string_literal + - has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - any: + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: neighbor + kind: init_declarator + has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + + $VAR $VAR_instance = "..." + $EXPR: + # $VAR_instance = "..." + $EXPR + kind: declaration + all: + - has: + nthChild: 1 + regex: ^(basic_string_view<.*>|std::basic_string_view<.*>|string_view|std::string_view|wstring_view|std::wstring_view)$ + - has: + stopBy: neighbor + kind: init_declarator + all: + - has: + stopBy: neighbor + kind: identifier + - has: + stopBy: neighbor + kind: binary_expression + all: + - has: + stopBy: neighbor + kind: string_literal + - has: + stopBy: neighbor + kind: identifier + pattern: $EXPR_INSTANCE + - any: + - inside: + stopBy: end + follows: + stopBy: end + kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + nthChild: 1 + - has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + - follows: + stopBy: end + any: + - kind: field_declaration + - kind: declaration + all: + - has: + stopBy: neighbor + any: + - kind: type_identifier + - kind: qualified_identifier + regex: ^(wstring|string|std::wstring|std::string|std::basic_string<.*>|basic_string<.*>)$ + - has: + stopBy: end + kind: init_declarator + has: + stopBy: end + kind: identifier + pattern: $EXPR_INSTANCE + +rule: + any: + - kind: expression_statement + any: + - matches: $VAR = std::to_string(...) + - matches: $VAR = $EXPR.substr(...) + - matches: $VAR = $EXPR + ... + - matches: $VAR = "..." + $EXPR + - matches: $VAR_instance = "..." + $EXPR + - matches: $VAR_instance = $EXPR_instance + ... + - matches: $VAR_instance = $EXPR_instance.substr(...) + - matches: $VAR_instance = $EXPR_instance.substr(...) + - matches: $VAR_instance = std::to_string(...) + - kind: call_expression + any: + - matches: $VAR(std::to_string(...)) + - matches: $VAR($EXPR + ...) + - matches: $VAR($EXPR_instance + ...) + - matches: $VAR("..." + $EXPR_instance ) + - matches: $VAR("..." + $EXPR) + - matches: $VAR($EXPR.substr(...)) + - matches: $VAR($EXPR_instance.substr(...)) + - kind: declaration + any: + - matches: $VAR(std::to_string(...))_as_declaration + - matches: $VAR_instance $VAR = "..." + $EXPR + - matches: $VAR $VAR_instance = "..." + $EXPR + all: + - not: + has: + stopBy: end + kind: ERROR + - not: + inside: + stopBy: end + kind: ERROR diff --git a/tests/__snapshots__/missing-nul-cpp-string-memcpy-copy-cpp-snapshot.yml b/tests/__snapshots__/missing-nul-cpp-string-memcpy-copy-cpp-snapshot.yml new file mode 100644 index 00000000..2a9efda5 --- /dev/null +++ b/tests/__snapshots__/missing-nul-cpp-string-memcpy-copy-cpp-snapshot.yml @@ -0,0 +1,173 @@ +id: missing-nul-cpp-string-memcpy-copy-cpp +snapshots: + ? | + void test_001() + { + string from = "hello"; + char to[20]; + size_t len_001 = strlen(from.c_str()); + memcpy(to, from.c_str(), len_001); + } + : labels: + - source: memcpy + style: primary + start: 109 + end: 115 + - source: memcpy + style: secondary + start: 109 + end: 115 + - source: to + style: secondary + start: 116 + end: 118 + - source: from.c_str() + style: secondary + start: 120 + end: 132 + - source: len_001 + style: secondary + start: 134 + end: 141 + - source: (to, from.c_str(), len_001) + style: secondary + start: 115 + end: 142 + - source: size_t len_001 = strlen(from.c_str()); + style: secondary + start: 66 + end: 104 + - source: size_t len_001 = strlen(from.c_str()); + style: secondary + start: 66 + end: 104 + - source: char to[20]; + style: secondary + start: 49 + end: 61 + - source: char to[20]; + style: secondary + start: 49 + end: 61 + - source: memcpy(to, from.c_str(), len_001) + style: secondary + start: 109 + end: 142 + ? | + void test_002() + { + string from = "hello"; + char to[20]; + size_t len_002 = from.size(); + memcpy(to, from.c_str(), len_002); + } + : labels: + - source: memcpy + style: primary + start: 100 + end: 106 + - source: memcpy + style: secondary + start: 100 + end: 106 + - source: to + style: secondary + start: 107 + end: 109 + - source: from.c_str() + style: secondary + start: 111 + end: 123 + - source: len_002 + style: secondary + start: 125 + end: 132 + - source: (to, from.c_str(), len_002) + style: secondary + start: 106 + end: 133 + - source: len_002 + style: secondary + start: 73 + end: 80 + - source: from.size() + style: secondary + start: 83 + end: 94 + - source: len_002 = from.size() + style: secondary + start: 73 + end: 94 + - source: size_t len_002 = from.size(); + style: secondary + start: 66 + end: 95 + - source: size_t len_002 = from.size(); + style: secondary + start: 66 + end: 95 + - source: char to[20]; + style: secondary + start: 49 + end: 61 + - source: char to[20]; + style: secondary + start: 49 + end: 61 + - source: memcpy(to, from.c_str(), len_002) + style: secondary + start: 100 + end: 133 + ? | + void test_003() + { + string from = "hello"; + char to[20]; + size_t len_003 = from.length(); + memcpy(to, from.c_str(), len_003); + } + : labels: + - source: memcpy + style: primary + start: 102 + end: 108 + - source: memcpy + style: secondary + start: 102 + end: 108 + - source: to + style: secondary + start: 109 + end: 111 + - source: from.c_str() + style: secondary + start: 113 + end: 125 + - source: len_003 + style: secondary + start: 127 + end: 134 + - source: (to, from.c_str(), len_003) + style: secondary + start: 108 + end: 135 + - source: size_t len_003 = from.length(); + style: secondary + start: 66 + end: 97 + - source: size_t len_003 = from.length(); + style: secondary + start: 66 + end: 97 + - source: char to[20]; + style: secondary + start: 49 + end: 61 + - source: char to[20]; + style: secondary + start: 49 + end: 61 + - source: memcpy(to, from.c_str(), len_003) + style: secondary + start: 102 + end: 135 diff --git a/tests/__snapshots__/string-view-temporary-string-cpp-snapshot.yml b/tests/__snapshots__/string-view-temporary-string-cpp-snapshot.yml new file mode 100644 index 00000000..3704d557 --- /dev/null +++ b/tests/__snapshots__/string-view-temporary-string-cpp-snapshot.yml @@ -0,0 +1,326 @@ +id: string-view-temporary-string-cpp +snapshots: + ? | + extern std::string returns_std_string(); + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = returns_std_string() + "bar"; + } + : labels: + - source: view = returns_std_string() + "bar"; + style: primary + start: 115 + end: 151 + - source: view + style: secondary + start: 115 + end: 119 + - source: returns_std_string + style: secondary + start: 122 + end: 140 + - source: returns_std_string() + "bar" + style: secondary + start: 122 + end: 150 + - source: view = returns_std_string() + "bar" + style: secondary + start: 115 + end: 150 + - source: std::string + style: secondary + start: 7 + end: 18 + - source: returns_std_string + style: secondary + start: 19 + end: 37 + - source: extern std::string returns_std_string(); + style: secondary + start: 0 + end: 40 + - source: extern std::string returns_std_string(); + style: secondary + start: 0 + end: 40 + - source: std::string_view + style: secondary + start: 91 + end: 107 + - source: view + style: secondary + start: 108 + end: 112 + - source: std::string_view view; + style: secondary + start: 91 + end: 113 + ? | + extern std::string returns_std_string(); + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = returns_std_string() + foo; + } + : labels: + - source: view = returns_std_string() + foo; + style: primary + start: 115 + end: 149 + - source: view + style: secondary + start: 115 + end: 119 + - source: returns_std_string + style: secondary + start: 122 + end: 140 + - source: returns_std_string() + foo + style: secondary + start: 122 + end: 148 + - source: view = returns_std_string() + foo + style: secondary + start: 115 + end: 148 + - source: std::string + style: secondary + start: 7 + end: 18 + - source: returns_std_string + style: secondary + start: 19 + end: 37 + - source: extern std::string returns_std_string(); + style: secondary + start: 0 + end: 40 + - source: extern std::string returns_std_string(); + style: secondary + start: 0 + end: 40 + - source: std::string_view + style: secondary + start: 91 + end: 107 + - source: view + style: secondary + start: 108 + end: 112 + - source: std::string_view view; + style: secondary + start: 91 + end: 113 + ? | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = "bar" + foo; + } + : labels: + - source: view = "bar" + foo; + style: primary + start: 74 + end: 93 + - source: view + style: secondary + start: 74 + end: 78 + - source: '"bar"' + style: secondary + start: 81 + end: 86 + - source: foo + style: secondary + start: 89 + end: 92 + - source: '"bar" + foo' + style: secondary + start: 81 + end: 92 + - source: view = "bar" + foo + style: secondary + start: 74 + end: 92 + - source: std::string + style: secondary + start: 24 + end: 35 + - source: foo + style: secondary + start: 36 + end: 39 + - source: std::string foo = "foo"; + style: secondary + start: 24 + end: 48 + - source: std::string_view + style: secondary + start: 50 + end: 66 + - source: view + style: secondary + start: 67 + end: 71 + - source: std::string_view view; + style: secondary + start: 50 + end: 72 + ? | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = foo + "bar"; + } + : labels: + - source: view = foo + "bar"; + style: primary + start: 74 + end: 93 + - source: view + style: secondary + start: 74 + end: 78 + - source: '"bar"' + style: secondary + start: 87 + end: 92 + - source: foo + style: secondary + start: 81 + end: 84 + - source: foo + "bar" + style: secondary + start: 81 + end: 92 + - source: view = foo + "bar" + style: secondary + start: 74 + end: 92 + - source: std::string + style: secondary + start: 24 + end: 35 + - source: foo + style: secondary + start: 36 + end: 39 + - source: std::string foo = "foo"; + style: secondary + start: 24 + end: 48 + - source: std::string_view + style: secondary + start: 50 + end: 66 + - source: view + style: secondary + start: 67 + end: 71 + - source: std::string_view view; + style: secondary + start: 50 + end: 72 + ? | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = foo + "foo" + bar; + } + : labels: + - source: view = foo + "foo" + bar; + style: primary + start: 74 + end: 99 + - source: view + style: secondary + start: 74 + end: 78 + - source: foo + style: secondary + start: 81 + end: 84 + - source: foo + "foo" + bar + style: secondary + start: 81 + end: 98 + - source: view = foo + "foo" + bar + style: secondary + start: 74 + end: 98 + - source: std::string + style: secondary + start: 24 + end: 35 + - source: foo + style: secondary + start: 36 + end: 39 + - source: std::string foo = "foo"; + style: secondary + start: 24 + end: 48 + - source: std::string_view + style: secondary + start: 50 + end: 66 + - source: view + style: secondary + start: 67 + end: 71 + - source: std::string_view view; + style: secondary + start: 50 + end: 72 + ? | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = foo + foo + "bar"; + } + : labels: + - source: view = foo + foo + "bar"; + style: primary + start: 74 + end: 99 + - source: view + style: secondary + start: 74 + end: 78 + - source: foo + style: secondary + start: 81 + end: 84 + - source: foo + foo + "bar" + style: secondary + start: 81 + end: 98 + - source: view = foo + foo + "bar" + style: secondary + start: 74 + end: 98 + - source: std::string + style: secondary + start: 24 + end: 35 + - source: foo + style: secondary + start: 36 + end: 39 + - source: std::string foo = "foo"; + style: secondary + start: 24 + end: 48 + - source: std::string_view + style: secondary + start: 50 + end: 66 + - source: view + style: secondary + start: 67 + end: 71 + - source: std::string_view view; + style: secondary + start: 50 + end: 72 diff --git a/tests/cpp/missing-nul-cpp-string-memcpy-cpp-test.yml b/tests/cpp/missing-nul-cpp-string-memcpy-cpp-test.yml new file mode 100644 index 00000000..e0aa67dc --- /dev/null +++ b/tests/cpp/missing-nul-cpp-string-memcpy-cpp-test.yml @@ -0,0 +1,43 @@ +id: missing-nul-cpp-string-memcpy-copy-cpp +valid: + - | + void test_001() + { + string from = "hello"; + char to[20]; + size_t len_001 = strlen(from.c_str()+1); + memcpy(to, from.c_str(), len_001); + } + - | + void test_002() + { + string from = "hello"; + char to[20]; + size_t len_002 = from.size()+1; + memcpy(to, from.c_str(), len_002); + } +invalid: + - | + void test_001() + { + string from = "hello"; + char to[20]; + size_t len_001 = strlen(from.c_str()); + memcpy(to, from.c_str(), len_001); + } + - | + void test_002() + { + string from = "hello"; + char to[20]; + size_t len_002 = from.size(); + memcpy(to, from.c_str(), len_002); + } + - | + void test_003() + { + string from = "hello"; + char to[20]; + size_t len_003 = from.length(); + memcpy(to, from.c_str(), len_003); + } diff --git a/tests/cpp/string-view-temporary-string-cpp-test.yml b/tests/cpp/string-view-temporary-string-cpp-test.yml new file mode 100644 index 00000000..0ebc90ce --- /dev/null +++ b/tests/cpp/string-view-temporary-string-cpp-test.yml @@ -0,0 +1,47 @@ +id: string-view-temporary-string-cpp +valid: + - | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + std::string other = foo + "bar"; + } +invalid: + - | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = foo + "bar"; + } + - | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = "bar" + foo; + } + - | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = foo + foo + "bar"; + } + - | + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = foo + "foo" + bar; + } + - | + extern std::string returns_std_string(); + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = returns_std_string() + foo; + } + - | + extern std::string returns_std_string(); + void operator_plus() { + std::string foo = "foo"; + std::string_view view; + view = returns_std_string() + "bar"; + }