From 84d1fd3b521eaad6dfbe888001114e3c9d1f2b5f Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Thu, 18 Feb 2021 07:48:43 -0800 Subject: [PATCH] [pulse] add tests Summary: These tests showcase weaknesses of Pulse w.r.t. detecting issues in situations with 1) pointer aliasing, and 2) pointers null-tests Reviewed By: ezgicicek Differential Revision: D26488145 fbshipit-source-id: 3de230bd2 --- .../tests/codetoanalyze/cpp/pulse/issues.exp | 1 + .../tests/codetoanalyze/cpp/pulse/nullptr.cpp | 21 +++++++++ .../cpp/pulse/use_after_free.cpp | 46 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp b/infer/tests/codetoanalyze/cpp/pulse/issues.exp index d8bfc88d5..8e73c8218 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/cpp/pulse/issues.exp @@ -51,6 +51,7 @@ codetoanalyze/cpp/pulse/interprocedural.cpp, set_x_then_crash_double_latent, 4, codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_bad, 1, USE_AFTER_DELETE, no_bucket, ERROR, [calling context starts here,in call to `invalidate_node_alias_latent`,invalidation part of the trace starts here,parameter `head` of invalidate_node_alias_latent,assigned,assigned,was invalidated by `delete`,use-after-lifetime part of the trace starts here,parameter `head` of invalidate_node_alias_latent,assigned,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_latent, 12, USE_AFTER_DELETE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,parameter `head` of invalidate_node_alias_latent,assigned,assigned,was invalidated by `delete`,use-after-lifetime part of the trace starts here,parameter `head` of invalidate_node_alias_latent,assigned,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_latent, 12, USE_AFTER_DELETE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,parameter `head` of invalidate_node_alias_latent,assigned,assigned,assigned,was invalidated by `delete`,use-after-lifetime part of the trace starts here,parameter `head` of invalidate_node_alias_latent,assigned,assigned,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/nullptr.cpp, call_test_after_dereference_bad, 1, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,when calling `FN_test_after_dereference_latent` here,parameter `x` of FN_test_after_dereference_latent,invalid access occurs here] codetoanalyze/cpp/pulse/nullptr.cpp, deref_nullptr_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/nullptr.cpp, no_check_return_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `may_return_nullptr` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `may_return_nullptr`,return from call to `may_return_nullptr`,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/nullptr.cpp, std_false_type_deref_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/cpp/pulse/nullptr.cpp b/infer/tests/codetoanalyze/cpp/pulse/nullptr.cpp index 67f4723c8..9cb93d707 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/nullptr.cpp +++ b/infer/tests/codetoanalyze/cpp/pulse/nullptr.cpp @@ -194,3 +194,24 @@ void delete_nullptr_ok() { int* p = nullptr; delete p; } + +void FN_test_after_dereference_latent(int* x) { + // create a path split where x==0 in one of the paths + if (x == 0) + ; + *x = 42; +} + +void call_test_after_dereference_bad() { + FN_test_after_dereference_latent(NULL); +} + +void FN_test_after_dereference2_latent(int* x) { + *x = 42; + if (x == 0) + ; +} + +void FN_call_test_after_dereference2_bad() { + FN_test_after_dereference2_latent(NULL); +} diff --git a/infer/tests/codetoanalyze/cpp/pulse/use_after_free.cpp b/infer/tests/codetoanalyze/cpp/pulse/use_after_free.cpp index 9188c56c3..ee2eac0e2 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/use_after_free.cpp +++ b/infer/tests/codetoanalyze/cpp/pulse/use_after_free.cpp @@ -30,3 +30,49 @@ void free_null_then_deref_bad() { free(x); *x = 1; } + +void FN_assumed_aliasing_latent(int* x, int* y) { + if (x == y) { + free(x); + free(y); + } +} + +void FN_trigger_assumed_aliasing_bad(int* x) { + FN_assumed_aliasing_latent(x, x); +} + +void FN_assumed_aliasing2_latent(int* x, int* y) { + if (x == y) + ; + free(x); + free(y); +} + +void FN_trigger_assumed_aliasing2_bad(int* x) { + FN_assumed_aliasing2_latent(x, x); +} + +void FN_assumed_aliasing3_latent(int* x, int* y) { + free(x); + if (x == y) + ; + free(y); +} + +void FN_trigger_assumed_aliasing3_bad(int* x) { + FN_assumed_aliasing3_latent(x, x); +} + +void FN_assumed_aliasing4_latent(int* x, int* y) { + free(x); + free(y); + // we create the x==y case too late: x|->- * y|->- is already in the + // state so adding x==y creates a contradition + if (x == y) + ; +} + +void FN_trigger_assumed_aliasing4_bad(int* x) { + FN_assumed_aliasing4_latent(x, x); +}