diff --git a/infer/src/base/IssueType.ml b/infer/src/base/IssueType.ml index 44af0d721..80d73e2bc 100644 --- a/infer/src/base/IssueType.ml +++ b/infer/src/base/IssueType.ml @@ -297,8 +297,6 @@ let quandary_taint_error = from_string "QUANDARY_TAINT_ERROR" let registered_observer_being_deallocated = from_string "REGISTERED_OBSERVER_BEING_DEALLOCATED" -let remote_code_execution_risk = from_string "REMOTE_CODE_EXECUTION_RISK" - let resource_leak = from_string "RESOURCE_LEAK" let retain_cycle = from_string ~enabled:true "RETAIN_CYCLE" @@ -315,8 +313,12 @@ let skip_pointer_dereference = from_string "SKIP_POINTER_DEREFERENCE" let shell_injection = from_string "SHELL_INJECTION" +let shell_injection_risk = from_string "SHELL_INJECTION_RISK" + let sql_injection = from_string "SQL_INJECTION" +let sql_injection_risk = from_string "SQL_INJECTION_RISK" + let stack_variable_address_escape = from_string ~enabled:false "STACK_VARIABLE_ADDRESS_ESCAPE" let static_initialization_order_fiasco = from_string "STATIC_INITIALIZATION_ORDER_FIASCO" diff --git a/infer/src/base/IssueType.mli b/infer/src/base/IssueType.mli index c975a3e88..36b46289d 100644 --- a/infer/src/base/IssueType.mli +++ b/infer/src/base/IssueType.mli @@ -214,8 +214,6 @@ val quandary_taint_error : t val registered_observer_being_deallocated : t -val remote_code_execution_risk : t - val resource_leak : t val retain_cycle : t @@ -232,8 +230,12 @@ val skip_pointer_dereference : t val shell_injection : t +val shell_injection_risk : t + val sql_injection : t +val sql_injection_risk : t + val stack_variable_address_escape : t val static_initialization_order_fiasco : t diff --git a/infer/src/quandary/ClangTrace.ml b/infer/src/quandary/ClangTrace.ml index 22d9bc49d..51f1b8508 100644 --- a/infer/src/quandary/ClangTrace.ml +++ b/infer/src/quandary/ClangTrace.ml @@ -184,10 +184,10 @@ module SinkKind = struct | BufferAccess (** read/write an array *) | CreateFile (** create/open a file *) | HeapAllocation (** heap memory allocation *) - | Network (** network access *) | ShellExec (** shell exec function *) | SQL (** SQL query *) | StackAllocation (** stack memory allocation *) + | URL (** URL creation *) | Other (** for testing or uncategorized sinks *) [@@deriving compare] @@ -200,14 +200,14 @@ module SinkKind = struct CreateFile | "HeapAllocation" -> HeapAllocation - | "Network" -> - Network | "ShellExec" -> ShellExec | "SQL" -> SQL | "StackAllocation" -> StackAllocation + | "URL" -> + URL | _ -> Other @@ -308,11 +308,10 @@ module SinkKind = struct match HilExp.eval exp with | Some Const.Cint i -> (* check if the data kind might be CURLOPT_URL *) - if controls_request (IntLit.to_int i) then taint_after_nth 1 Network actuals - else None + if controls_request (IntLit.to_int i) then taint_after_nth 1 URL actuals else None | _ -> (* can't statically resolve data kind; taint it just in case *) - taint_after_nth 1 Network actuals ) + taint_after_nth 1 URL actuals ) | None -> None ) | "execl" | "execlp" | "execle" | "execv" | "execve" | "execvp" | "system" -> @@ -349,14 +348,14 @@ module SinkKind = struct "CreateFile" | HeapAllocation -> "HeapAllocation" - | Network -> - "Network" | ShellExec -> "ShellExec" | SQL -> "SQL" | StackAllocation -> "StackAllocation" + | URL -> + "URL" | Other -> "Other" ) end @@ -365,13 +364,24 @@ module CppSink = Sink.Make (SinkKind) module CppSanitizer = struct type t = - | Escape (** escaped string to sanitize SQL injection or ShellExec sinks *) + | EscapeShell (** escape string to sanitize shell commands *) + | EscapeSQL (** escape string to sanitize SQL queries *) + | EscapeURL (** escape string to sanitize URLs (e.g., prevent injecting GET/POST params) *) | All (** sanitizes all forms of taint *) [@@deriving compare] let equal = [%compare.equal : t] - let of_string = function "Escape" -> Escape | _ -> All + let of_string = function + | "EscapeShell" -> + EscapeShell + | "EscapeSQL" -> + EscapeSQL + | "EscapeURL" -> + EscapeURL + | _ -> + All + let external_sanitizers = List.map @@ -389,7 +399,15 @@ module CppSanitizer = struct external_sanitizers - let pp fmt = function Escape -> F.fprintf fmt "Escape" | All -> F.fprintf fmt "All" + let pp fmt = function + | EscapeShell -> + F.fprintf fmt "EscapeShell" + | EscapeSQL -> + F.fprintf fmt "EscapeSQL" + | EscapeURL -> + F.fprintf fmt "EscapeURL" + | All -> + F.fprintf fmt "All" end include Trace.Make (struct @@ -397,9 +415,10 @@ include Trace.Make (struct module Sink = CppSink module Sanitizer = CppSanitizer - (* return true if code injection is possible because the source is a string/is not sanitized *) - let is_injection_possible ?typ sanitizers = - let is_escaped = List.mem sanitizers Sanitizer.Escape ~equal:Sanitizer.equal in + (* return true if code injection is possible because the source is a string/is not sanitized with + [escape_sanitizer] *) + let is_injection_possible ?typ escape_sanitizer sanitizers = + let is_escaped = List.mem sanitizers escape_sanitizer ~equal:Sanitizer.equal in not is_escaped && match typ with @@ -416,33 +435,46 @@ include Trace.Make (struct (* the All sanitizer clears any form of taint; don't report *) None | UserControlledEndpoint (_, typ), CreateFile -> - Option.some_if (is_injection_possible ~typ sanitizers) IssueType.untrusted_file + Option.some_if + (is_injection_possible ~typ Sanitizer.EscapeShell sanitizers) + IssueType.untrusted_file | (Endpoint (_, typ) | CommandLineFlag (_, typ)), CreateFile -> - Option.some_if (is_injection_possible ~typ sanitizers) IssueType.untrusted_file_risk - | UserControlledEndpoint (_, typ), Network -> - Option.some_if (is_injection_possible ~typ sanitizers) IssueType.untrusted_url - | (Endpoint (_, typ) | CommandLineFlag (_, typ)), Network -> - Option.some_if (is_injection_possible ~typ sanitizers) IssueType.untrusted_url_risk - | (EnvironmentVariable | ReadFile), Network -> + Option.some_if + (is_injection_possible ~typ Sanitizer.EscapeShell sanitizers) + IssueType.untrusted_file_risk + | UserControlledEndpoint (_, typ), URL -> + Option.some_if + (is_injection_possible ~typ Sanitizer.EscapeURL sanitizers) + IssueType.untrusted_url + | (Endpoint (_, typ) | CommandLineFlag (_, typ)), URL -> + Option.some_if + (is_injection_possible ~typ Sanitizer.EscapeURL sanitizers) + IssueType.untrusted_url_risk + | (EnvironmentVariable | ReadFile), URL -> None | (UserControlledEndpoint (_, typ) | CommandLineFlag (_, typ)), SQL -> - if is_injection_possible ~typ sanitizers then Some IssueType.sql_injection + if is_injection_possible ~typ Sanitizer.EscapeSQL sanitizers then + Some IssueType.sql_injection else (* no injection risk, but still user-controlled *) Some IssueType.user_controlled_sql_risk | Endpoint (_, typ), SQL -> - if is_injection_possible ~typ sanitizers then - (* code injection if the caller of the endpoint doesn't sanitize on its end *) - Some IssueType.remote_code_execution_risk + if is_injection_possible ~typ Sanitizer.EscapeSQL sanitizers then + (* SQL injection if the caller of the endpoint doesn't sanitize on its end *) + Some IssueType.sql_injection_risk else (* no injection risk, but still user-controlled *) Some IssueType.user_controlled_sql_risk | (UserControlledEndpoint (_, typ) | CommandLineFlag (_, typ)), ShellExec -> (* we know the user controls the endpoint, so it's code injection without a sanitizer *) - Option.some_if (is_injection_possible ~typ sanitizers) IssueType.shell_injection + Option.some_if + (is_injection_possible ~typ Sanitizer.EscapeShell sanitizers) + IssueType.shell_injection | Endpoint (_, typ), ShellExec -> (* code injection if the caller of the endpoint doesn't sanitize on its end *) - Option.some_if (is_injection_possible ~typ sanitizers) IssueType.remote_code_execution_risk + Option.some_if + (is_injection_possible ~typ Sanitizer.EscapeShell sanitizers) + IssueType.shell_injection_risk | UserControlledEndpoint _, BufferAccess -> (* untrusted data from an endpoint flowing into a buffer *) Some IssueType.quandary_taint_error @@ -454,10 +486,19 @@ include Trace.Make (struct Some IssueType.quandary_taint_error | (EnvironmentVariable | ReadFile | Other), ShellExec -> (* untrusted flag, environment var, or file data flowing to shell *) - Option.some_if (is_injection_possible sanitizers) IssueType.shell_injection + Option.some_if + (is_injection_possible Sanitizer.EscapeShell sanitizers) + IssueType.shell_injection | (EnvironmentVariable | ReadFile | Other), SQL -> (* untrusted flag, environment var, or file data flowing to SQL *) - Option.some_if (is_injection_possible sanitizers) IssueType.sql_injection + Option.some_if + (is_injection_possible Sanitizer.EscapeSQL sanitizers) + IssueType.sql_injection + | Other, URL -> + (* untrusted flag, environment var, or file data flowing to URL *) + Option.some_if + (is_injection_possible Sanitizer.EscapeURL sanitizers) + IssueType.untrusted_url_risk | ( (CommandLineFlag _ | UserControlledEndpoint _ | EnvironmentVariable | ReadFile | Other) , HeapAllocation ) -> (* untrusted data of any kind flowing to heap allocation. this can cause crashes or DOS. *) diff --git a/infer/tests/codetoanalyze/cpp/quandary/.inferconfig b/infer/tests/codetoanalyze/cpp/quandary/.inferconfig index e59e68f2a..bb8d77818 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/.inferconfig +++ b/infer/tests/codetoanalyze/cpp/quandary/.inferconfig @@ -42,6 +42,11 @@ "kind": "SQL", "index": "all" }, + { + "procedure": "__infer_url_sink", + "kind": "URL", + "index": "all" + }, { "procedure": "basics::Obj::method_sink", "kind": "Other", @@ -69,8 +74,16 @@ "kind": "All" }, { - "procedure": "__infer_string_sanitizer", - "kind": "Escape" + "procedure": "__infer_shell_sanitizer", + "kind": "EscapeShell" + }, + { + "procedure": "__infer_sql_sanitizer", + "kind": "EscapeSQL" + }, + { + "procedure": "__infer_url_sanitizer", + "kind": "EscapeURL" }, { "procedure": "basics::Obj::sanitizer1" diff --git a/infer/tests/codetoanalyze/cpp/quandary/endpoints.cpp b/infer/tests/codetoanalyze/cpp/quandary/endpoints.cpp index 0d5d996c8..06eee2708 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/endpoints.cpp +++ b/infer/tests/codetoanalyze/cpp/quandary/endpoints.cpp @@ -12,8 +12,8 @@ #include extern void __infer_sql_sink(std::string); -extern std::string __infer_all_sanitizer(std::string); -extern std::string __infer_string_sanitizer(std::string); +extern std::string __infer_shell_sanitizer(std::string); +extern std::string __infer_sql_sanitizer(std::string); extern void curl_easy_setopt(void*, int, ...); @@ -60,17 +60,18 @@ class Service1 : facebook::fb303::cpp2::FacebookServiceSvIf { __infer_sql_sink(formal); } - void sanitized_sql_bad(std::string formal) { - // this should report USER_CONTROLLED_SQL_RISK - __infer_sql_sink(__infer_string_sanitizer(formal)); + void sanitized_sql_with_shell_bad(std::string formal) { + // this should report REMOTE_CODE_EXECUTION_RISK + __infer_sql_sink(__infer_shell_sanitizer(formal)); } - void service1_endpoint_sql_sanitized_ok(std::string formal) { - __infer_sql_sink(__infer_all_sanitizer(formal)); + void service1_endpoint_sql_sanitized_bad(std::string formal) { + // this should report USER_CONTROLLED_SQL_RISK + __infer_sql_sink(__infer_sql_sanitizer(formal)); } void service1_endpoint_shell_sanitized_ok(std::string formal) { - system(__infer_string_sanitizer(formal).c_str()); + system(__infer_shell_sanitizer(formal).c_str()); } void service1_endpoint_struct_string_field_bad(request formal) { diff --git a/infer/tests/codetoanalyze/cpp/quandary/issues.exp b/infer/tests/codetoanalyze/cpp/quandary/issues.exp index 304928f3f..ae97daf7b 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/issues.exp +++ b/infer/tests/codetoanalyze/cpp/quandary/issues.exp @@ -36,7 +36,7 @@ codetoanalyze/cpp/quandary/basics.cpp, basics::via_field_bad1, 3, QUANDARY_TAINT codetoanalyze/cpp/quandary/basics.cpp, basics::via_field_bad2, 2, QUANDARY_TAINT_ERROR, [Return from basics::template_source_>,Call to basics::template_sink_>] codetoanalyze/cpp/quandary/basics.cpp, basics::via_passthrough_bad1, 4, QUANDARY_TAINT_ERROR, [Return from basics::Obj_string_source,Call to basics::Obj_string_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::via_passthrough_bad2, 3, QUANDARY_TAINT_ERROR, [Return from basics::Obj_string_source,Call to basics::Obj_string_sink] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_FP_service1_endpoint_struct_int_field_ok, 1, REMOTE_CODE_EXECUTION_RISK, [Return from endpoints::Service1_FP_service1_endpoint_struct_int_field_ok,Call to system] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_FP_service1_endpoint_struct_int_field_ok, 1, SHELL_INJECTION_RISK, [Return from endpoints::Service1_FP_service1_endpoint_struct_int_field_ok,Call to system] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_endpoint_to_curl_url_bad, 1, UNTRUSTED_URL_RISK, [Return from endpoints::Service1_endpoint_to_curl_url_bad,Call to curl_easy_setopt] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_endpoint_to_curl_url_exp_bad, 1, UNTRUSTED_URL_RISK, [Return from endpoints::Service1_endpoint_to_curl_url_exp_bad,Call to curl_easy_setopt] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_endpoint_to_curl_url_unknown_exp_bad, 1, UNTRUSTED_URL_RISK, [Return from endpoints::Service1_endpoint_to_curl_url_unknown_exp_bad,Call to curl_easy_setopt] @@ -52,14 +52,15 @@ codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_open_or_create_c_s codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_open_or_create_c_style_file_bad, 4, UNTRUSTED_FILE_RISK, [Return from endpoints::Service1_open_or_create_c_style_file_bad,Call to fopen] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_open_or_create_c_style_file_bad, 5, UNTRUSTED_FILE_RISK, [Return from endpoints::Service1_open_or_create_c_style_file_bad,Call to freopen] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_open_or_create_c_style_file_bad, 6, UNTRUSTED_FILE_RISK, [Return from endpoints::Service1_open_or_create_c_style_file_bad,Call to rename] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_sanitized_sql_bad, 2, USER_CONTROLLED_SQL_RISK, [Return from endpoints::Service1_sanitized_sql_bad,Call to __infer_sql_sink] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_service1_endpoint_bad, 2, REMOTE_CODE_EXECUTION_RISK, [Return from endpoints::Service1_service1_endpoint_bad,Call to system] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_service1_endpoint_struct_string_field_bad, 1, REMOTE_CODE_EXECUTION_RISK, [Return from endpoints::Service1_service1_endpoint_struct_string_field_bad,Call to system] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_unsanitized_sql_bad, 2, REMOTE_CODE_EXECUTION_RISK, [Return from endpoints::Service1_unsanitized_sql_bad,Call to __infer_sql_sink] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_sanitized_sql_with_shell_bad, 2, SQL_INJECTION_RISK, [Return from endpoints::Service1_sanitized_sql_with_shell_bad,Call to __infer_sql_sink] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_service1_endpoint_bad, 2, SHELL_INJECTION_RISK, [Return from endpoints::Service1_service1_endpoint_bad,Call to system] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_service1_endpoint_sql_sanitized_bad, 2, USER_CONTROLLED_SQL_RISK, [Return from endpoints::Service1_service1_endpoint_sql_sanitized_bad,Call to __infer_sql_sink] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_service1_endpoint_struct_string_field_bad, 1, SHELL_INJECTION_RISK, [Return from endpoints::Service1_service1_endpoint_struct_string_field_bad,Call to system] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_unsanitized_sql_bad, 2, SQL_INJECTION_RISK, [Return from endpoints::Service1_unsanitized_sql_bad,Call to __infer_sql_sink] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_user_controlled_endpoint_to_shell_bad, 2, SHELL_INJECTION, [Return from endpoints::Service1_user_controlled_endpoint_to_shell_bad,Call to system] codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service1_user_controlled_endpoint_to_sql_bad, 2, SQL_INJECTION, [Return from endpoints::Service1_user_controlled_endpoint_to_sql_bad,Call to __infer_sql_sink] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service2_service2_endpoint_bad, 2, REMOTE_CODE_EXECUTION_RISK, [Return from endpoints::Service2_service2_endpoint_bad,Call to system] -codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service3_service3_endpoint_bad, 2, REMOTE_CODE_EXECUTION_RISK, [Return from endpoints::Service3_service3_endpoint_bad,Call to system] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service2_service2_endpoint_bad, 2, SHELL_INJECTION_RISK, [Return from endpoints::Service2_service2_endpoint_bad,Call to system] +codetoanalyze/cpp/quandary/endpoints.cpp, endpoints::Service3_service3_endpoint_bad, 2, SHELL_INJECTION_RISK, [Return from endpoints::Service3_service3_endpoint_bad,Call to system] codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 6, SHELL_INJECTION, [Return from getenv,Call to execl] codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 8, SHELL_INJECTION, [Return from getenv,Call to execl] codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 11, SHELL_INJECTION, [Return from getenv,Call to execl] @@ -97,7 +98,10 @@ codetoanalyze/cpp/quandary/pointers.cpp, pointers::assign_source_by_reference_ba codetoanalyze/cpp/quandary/pointers.cpp, pointers::assign_source_by_reference_bad2, 2, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source with tainted data @val$0*,Return from pointers::assign_source_by_reference,Call to __infer_taint_sink] codetoanalyze/cpp/quandary/pointers.cpp, pointers::assign_source_by_reference_bad3, 3, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source with tainted data @val$0*,Return from pointers::assign_source_by_reference with tainted data @val$0*,Return from pointers::call_assign_source_by_reference,Call to __infer_taint_sink] codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::dead_sanitizer_bad, 3, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source,Call to __infer_taint_sink] -codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::escape_string_to_all_bad, 3, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source,Call to __infer_taint_sink] +codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::escape_shell_to_url_bad, 3, UNTRUSTED_URL_RISK, [Return from __infer_taint_source,Call to __infer_url_sink] +codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::escape_sql_to_shell_bad, 3, SHELL_INJECTION, [Return from __infer_taint_source,Call to system] +codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::escape_sql_to_url_bad, 3, UNTRUSTED_URL_RISK, [Return from __infer_taint_source,Call to __infer_url_sink] +codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::escape_url_to_sql_bad, 3, SQL_INJECTION, [Return from __infer_taint_source,Call to __infer_sql_sink] codetoanalyze/cpp/quandary/sanitizers.cpp, sanitizers::kill_sanitizer_bad, 4, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source,Call to __infer_taint_sink] codetoanalyze/cpp/quandary/strings.cpp, strings::append1_bad, 2, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source,Call to __infer_taint_sink] codetoanalyze/cpp/quandary/strings.cpp, strings::append2_bad, 3, QUANDARY_TAINT_ERROR, [Return from __infer_taint_source,Call to __infer_taint_sink] diff --git a/infer/tests/codetoanalyze/cpp/quandary/sanitizers.cpp b/infer/tests/codetoanalyze/cpp/quandary/sanitizers.cpp index 093762a41..6d260b8bf 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/sanitizers.cpp +++ b/infer/tests/codetoanalyze/cpp/quandary/sanitizers.cpp @@ -12,38 +12,69 @@ extern std::string __infer_taint_source(); -extern void __infer_taint_sink(std::string); extern void __infer_sql_sink(std::string); +extern void __infer_taint_sink(std::string); +extern void __infer_url_sink(std::string); extern std::string __infer_all_sanitizer(std::string); -extern std::string __infer_string_sanitizer(std::string); +extern std::string __infer_shell_sanitizer(std::string); +extern std::string __infer_sql_sanitizer(std::string); +extern std::string __infer_url_sanitizer(std::string); namespace sanitizers { -void escape_string_to_sql_ok() { +void escape_sql_to_sql_ok() { auto source = __infer_taint_source(); - auto sanitized = __infer_string_sanitizer(source); + auto sanitized = __infer_sql_sanitizer(source); __infer_sql_sink(sanitized); } -void escape_string_to_shell_ok() { +void escape_shell_to_shell_ok() { auto source = __infer_taint_source(); - auto sanitized = __infer_string_sanitizer(source); + auto sanitized = __infer_shell_sanitizer(source); system(sanitized.c_str()); } -void escape_string_to_all_bad() { +void escape_url_to_url_ok() { auto source = __infer_taint_source(); - auto sanitized = __infer_string_sanitizer(source); - __infer_taint_sink(sanitized); // wrong kind of sanitizer; report + auto sanitized = __infer_url_sanitizer(source); + __infer_url_sink(sanitized); } +void foo(std::string sanitized) { __infer_url_sink(sanitized); } + void all_to_all_ok() { auto source = __infer_taint_source(); auto sanitized = __infer_all_sanitizer(source); __infer_taint_sink(sanitized); } +// test a few permutations of "wrong sanitizer for this sink" + +void escape_sql_to_shell_bad() { + auto source = __infer_taint_source(); + auto sanitized = __infer_sql_sanitizer(source); + system(sanitized.c_str()); +} + +void escape_sql_to_url_bad() { + auto source = __infer_taint_source(); + auto sanitized = __infer_sql_sanitizer(source); + __infer_url_sink(sanitized); +} + +void escape_shell_to_url_bad() { + auto source = __infer_taint_source(); + auto sanitized = __infer_shell_sanitizer(source); + __infer_url_sink(sanitized); +} + +void escape_url_to_sql_bad() { + auto source = __infer_taint_source(); + auto sanitized = __infer_url_sanitizer(source); + __infer_sql_sink(sanitized); +} + void dead_sanitizer_bad() { auto source = __infer_taint_source(); auto sanitized = __infer_all_sanitizer(source); @@ -61,7 +92,7 @@ void kill_sanitizer_bad() { void double_sanitize_ok() { auto source = __infer_taint_source(); auto x = __infer_all_sanitizer(source); - auto y = __infer_string_sanitizer(x); + auto y = __infer_sql_sanitizer(x); __infer_taint_sink(y); } @@ -97,7 +128,7 @@ void different_sanitizer_branches_ok(bool b) { if (b) { x = __infer_all_sanitizer(source); } else { - x = __infer_string_sanitizer(source); + x = __infer_sql_sanitizer(source); } __infer_sql_sink(x); }