Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/J2000A/analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
J2000A committed Aug 4, 2023
2 parents 9bf2959 + 7e8e216 commit 698111f
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 18 deletions.
32 changes: 26 additions & 6 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1411,9 +1411,13 @@ struct
let new_value = VD.update_offset (Queries.to_value_domain_ask a) old_value offs projected_value lval_raw ((Var x), cil_offset) t in
if WeakUpdates.mem x st.weak then
VD.join old_value new_value
else if invariant then
else if invariant then (
(* without this, invariant for ambiguous pointer might worsen precision for each individual address to their join *)
VD.meet old_value new_value
try
VD.meet old_value new_value
with Lattice.Uncomparable ->
new_value
)
else
new_value
in
Expand Down Expand Up @@ -1998,6 +2002,16 @@ struct
let st' = invalidate ~deep:false ~ctx (Analyses.ask_of_ctx ctx) gs st shallow_addrs in
invalidate ~deep:true ~ctx (Analyses.ask_of_ctx ctx) gs st' deep_addrs

let check_free_of_non_heap_mem ctx special_fn ptr =
match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local ptr with
| Address a ->
let points_to_set = addrToLvalSet a in
if Q.LS.is_top points_to_set then
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potential free of non-dynamically allocated memory may occur" d_exp ptr special_fn.vname
else if (Q.LS.exists (fun (v, _) -> not (ctx.ask (Q.IsHeapVar v))) points_to_set) || (AD.mem Addr.UnknownPtr a) then
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr
| _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname

let special ctx (lv:lval option) (f: varinfo) (args: exp list) =
let invalidate_ret_lv st = match lv with
| Some lv ->
Expand Down Expand Up @@ -2278,6 +2292,8 @@ struct
| _ -> st
end
| Realloc { ptr = p; size }, _ ->
(* Realloc shouldn't be passed non-dynamically allocated memory *)
check_free_of_non_heap_mem ctx f p;
begin match lv with
| Some lv ->
let ask = Analyses.ask_of_ctx ctx in
Expand Down Expand Up @@ -2309,6 +2325,10 @@ struct
| None ->
st
end
| Free ptr, _ ->
(* Free shouldn't be passed non-dynamically allocated memory *)
check_free_of_non_heap_mem ctx f ptr;
st
| Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine
| Setjmp { env }, _ ->
let ask = Analyses.ask_of_ctx ctx in
Expand Down Expand Up @@ -2348,10 +2368,10 @@ struct
set ~ctx ~t_override:t ask ctx.global ctx.local (AD.of_var !longjmp_return) t rv (* Not raising Deadcode here, deadcode is raised at a higher level! *)
| Rand, _ ->
begin match lv with
| Some x ->
let result:value = (Int (ID.starting IInt Z.zero)) in
set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st x) (Cilfacade.typeOfLval x) result
| None -> st
| Some x ->
let result:value = (Int (ID.starting IInt Z.zero)) in
set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st x) (Cilfacade.typeOfLval x) result
| None -> st
end
| _, _ ->
let st =
Expand Down
24 changes: 12 additions & 12 deletions src/cdomains/valueDomain.ml
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ struct
warn_type "join" x y;
Top

let rec widen x y =
let widen x y =
match (x,y) with
| (Top, _) -> Top
| (_, Top) -> Top
Expand All @@ -582,7 +582,7 @@ struct
| (Struct x, Struct y) -> Struct (Structs.widen x y)
| (Union x, Union y) -> Union (Unions.widen x y)
| (Array x, Array y) -> Array (CArrays.widen x y)
| (Blob x, Blob y) -> Blob (Blobs.widen x y)
| (Blob x, Blob y) -> Blob (Blobs.widen x y) (* TODO: why no blob special cases like in join? *)
| (Thread x, Thread y) -> Thread (Threads.widen x y)
| (Int x, Thread y)
| (Thread y, Int x) ->
Expand Down Expand Up @@ -963,16 +963,16 @@ struct
Top
end
| JmpBuf _, _ ->
(* hack for jmp_buf variables *)
begin match value with
| JmpBuf t -> value (* if actually assigning jmpbuf, use value *)
| Blob(Bot, _, _) -> Bot (* TODO: Stopgap for malloced jmp_bufs, there is something fundamentally flawed somewhere *)
| _ ->
if !AnalysisState.global_initialization then
JmpBuf (JmpBufs.Bufs.empty (), false) (* if assigning global init, use empty set instead *)
else
Top
end
(* hack for jmp_buf variables *)
begin match value with
| JmpBuf t -> value (* if actually assigning jmpbuf, use value *)
| Blob(Bot, _, _) -> Bot (* TODO: Stopgap for malloced jmp_bufs, there is something fundamentally flawed somewhere *)
| _ ->
if !AnalysisState.global_initialization then
JmpBuf (JmpBufs.Bufs.empty (), false) (* if assigning global init, use empty set instead *)
else
Top
end
| _ ->
let result =
match offs with
Expand Down
5 changes: 5 additions & 0 deletions src/util/messageCategory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type undefined_behavior =
| NullPointerDereference
| UseAfterFree
| DoubleFree
| InvalidMemoryDeallocation
| Uninitialized
| DoubleLocking
| Other
Expand Down Expand Up @@ -65,6 +66,7 @@ struct
let nullpointer_dereference: category = create @@ NullPointerDereference
let use_after_free: category = create @@ UseAfterFree
let double_free: category = create @@ DoubleFree
let invalid_memory_deallocation: category = create @@ InvalidMemoryDeallocation
let uninitialized: category = create @@ Uninitialized
let double_locking: category = create @@ DoubleLocking
let other: category = create @@ Other
Expand Down Expand Up @@ -102,6 +104,7 @@ struct
| "nullpointer_dereference" -> nullpointer_dereference
| "use_after_free" -> use_after_free
| "double_free" -> double_free
| "invalid_memory_deallocation" -> invalid_memory_deallocation
| "uninitialized" -> uninitialized
| "double_locking" -> double_locking
| "other" -> other
Expand All @@ -113,6 +116,7 @@ struct
| NullPointerDereference -> ["NullPointerDereference"]
| UseAfterFree -> ["UseAfterFree"]
| DoubleFree -> ["DoubleFree"]
| InvalidMemoryDeallocation -> ["InvalidMemoryDeallocation"]
| Uninitialized -> ["Uninitialized"]
| DoubleLocking -> ["DoubleLocking"]
| Other -> ["Other"]
Expand Down Expand Up @@ -223,6 +227,7 @@ let behaviorName = function
|NullPointerDereference -> "NullPointerDereference"
|UseAfterFree -> "UseAfterFree"
|DoubleFree -> "DoubleFree"
|InvalidMemoryDeallocation -> "InvalidMemoryDeallocation"
|Uninitialized -> "Uninitialized"
|DoubleLocking -> "DoubleLocking"
|Other -> "Other"
Expand Down
14 changes: 14 additions & 0 deletions tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdlib.h>

int main(int argc, char const *argv[])
{
int a;
int *p = &a;
free(p); //WARN

char b = 'b';
char *p2 = &b;
free(p2); //WARN

return 0;
}
14 changes: 14 additions & 0 deletions tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdlib.h>

typedef struct custom_t {
int x;
int y;
} custom_t;

int main(int argc, char const *argv[])
{
custom_t *var;
free(var); //WARN

return 0;
}
25 changes: 25 additions & 0 deletions tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdlib.h>

typedef struct custom_t {
int x;
int y;
} custom_t;

#define MAX_SIZE 5000

int main(int argc, char const *argv[])
{
custom_t custom_arr[MAX_SIZE];
free(custom_arr); //WARN

int int_arr[MAX_SIZE];
free(int_arr); //WARN

char char_arr[MAX_SIZE];
free(char_arr); //WARN

char char_arr2[1];
free(char_arr2); //WARN

return 0;
}
25 changes: 25 additions & 0 deletions tests/regression/75-invalid_dealloc/04-invalid-realloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdlib.h>

typedef struct custom_t {
int x;
int y;
} custom_t;

#define MAX_SIZE 5000

int main(int argc, char const *argv[])
{
custom_t custom_arr[10];
realloc(custom_arr, MAX_SIZE); //WARN

int int_arr[100];
realloc(int_arr, MAX_SIZE); //WARN

char char_arr[1000];
realloc(char_arr, MAX_SIZE); //WARN

char char_arr2[1];
realloc(char_arr2, MAX_SIZE); //WARN

return 0;
}

0 comments on commit 698111f

Please sign in to comment.