Ericsson Internal | 2018-02-21
Statistics Based Checkers in the Clang Static Analyzer
Ádám Balogh adam.balogh@ericsson.com
Euro LLVM 2019, Brussels, Belgium Ericsson 2019-04-08
in the Clang Static Analyzer dm Balogh adam.balogh@ericsson.com - - PowerPoint PPT Presentation
Statistics Based Checkers in the Clang Static Analyzer dm Balogh adam.balogh@ericsson.com Euro LLVM 2019, Brussels, Belgium Ericsson 2019-04-08 Ericsson Internal | 2018-02-21 The Problem Huge legacy code with weak documentation
Ericsson Internal | 2018-02-21
Ádám Balogh adam.balogh@ericsson.com
Euro LLVM 2019, Brussels, Belgium Ericsson 2019-04-08
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation
int may_return_return_negative(); // no body available
X.h
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls
int may_return_return_negative(); // no body available
X.h
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls
int may_return_return_negative(); // no body available
X.h
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y1.c
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls
int may_return_return_negative(); // no body available
X.h
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y1.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y2.c
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls
int may_return_return_negative(); // no body available
X.h
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y1.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y2.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y3.c
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls
int may_return_return_negative(); // no body available
X.h
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y1.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y2.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y3.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y4.c
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls
int may_return_return_negative(); // no body available
X.h
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y1.c
int i = may_return_return_negative(); v[i]; // error: negative indexing
Yn.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y2.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y3.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y4.c
Ericsson Internal | 2018-02-21
— Huge legacy code with weak documentation — Many calls for may_return_negative(), return value is checked for negative in e.g. 98% of the calls — Goal: detect the 2% where the negativeness of the return value is not checked
int may_return_return_negative(); // no body available
X.h
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y1.c
int i = may_return_return_negative(); v[i]; // error: negative indexing
Yn.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y2.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y3.c
int i = may_return_return_negative(); if (i < 0) return; v[i]; // OK.
Y4.c
Ericsson Internal | 2018-02-21
Ignored Return Value
fread(data, …); // data may be garbage // if read failed
Ignored.c
Find calls where the return value is ignored but it should not
Ericsson Internal | 2018-02-21
Ignored Return Value Special Return Value
int i = ret_neg(); v[i]; // error
NegRet.c
fread(data, …); // data may be garbage // if read failed
Ignored.c
Negative Integers Find calls where the return value is ignored but it should not Find calls where the integer return value is not checked for negative but it should
Ericsson Internal | 2018-02-21
Ignored Return Value Special Return Value
int i = ret_neg(); v[i]; // error
NegRet.c
T *t = ret_null(); t->field; // error
NullRet.c
fread(data, …); // data may be garbage // if read failed
Ignored.c
Negative Integers Null Pointers Find calls where the return value is ignored but it should not Find calls where the integer return value is not checked for negative but it should Find calls where the pointer return value is not checked for null pointer but it should
Ericsson Internal | 2018-02-21
Other “special” values may be added Ignored Return Value Special Return Value
int i = ret_neg(); v[i]; // error
NegRet.c
T *t = ret_null(); t->field; // error
NullRet.c
fread(data, …); // data may be garbage // if read failed
Ignored.c
Negative Integers Null Pointers Find calls where the return value is ignored but it should not Find calls where the integer return value is not checked for negative but it should Find calls where the pointer return value is not checked for null pointer but it should
Ericsson Internal | 2018-02-21
X.c X.c X.c *.c Y.cpp Y.cpp Y.cpp *.cpp
Ericsson Internal | 2018-02-21
X.c X.c X.c *.c Y.cpp Y.cpp Y.cpp *.cpp clang SA *.yaml *.yaml Phase 1: Collect statistics
Ericsson Internal | 2018-02-21
X.c X.c X.c *.c Y.cpp Y.cpp Y.cpp *.cpp clang SA clang SA *.yaml *.yaml Phase 1: Collect statistics Phase 2: Analyze
Ericsson Internal | 2018-02-21
— Threshold and minimum required number of calls configurable (default: 85% and 10 calls) X.c X.c X.c *.c Y.cpp Y.cpp Y.cpp *.cpp clang SA clang SA *.yaml *.yaml Phase 1: Collect statistics Phase 2: Analyze
Ericsson Internal | 2018-02-21
— Threshold and minimum required number of calls configurable (default: 85% and 10 calls) — CodeChecker support exists, open sourcing planned X.c X.c X.c *.c Y.cpp Y.cpp Y.cpp *.cpp clang SA clang SA *.yaml *.yaml Phase 1: Collect statistics Phase 2: Analyze
Ericsson Internal | 2018-02-21
— No warnings, just state split
Ericsson Internal | 2018-02-21
— No warnings, just state split
int i = may_return_negative();
Ericsson Internal | 2018-02-21
— No warnings, just state split
int i = may_return_negative(); i : [INT_MIN..-1] i: [0..INT_MAX]
Ericsson Internal | 2018-02-21
— No warnings, just state split
int i = may_return_negative(); i : [INT_MIN..-1] i: [0..INT_MAX] x = v[i]; //OK. x = v[i]; //Error!
Ericsson Internal | 2018-02-21
— No warnings, just state split
int i = may_return_negative(); i : [INT_MIN..-1] i: [0..INT_MAX] x = v[i]; //OK. x = v[i]; //Error!
Reported by negative array ← indexing checker!
Ericsson Internal | 2018-02-21
— No warnings, just state split — Performance impact: low because special return value branch terminates quickly — Either by early exit or because of error
int i = may_return_negative(); i : [INT_MIN..-1] i: [0..INT_MAX] x = v[i]; //OK. x = v[i]; //Error!
Reported by negative array ← indexing checker!
Ericsson Internal | 2018-02-21
— False Positives: The possible return values often depend from the arguments
Ericsson Internal | 2018-02-21
— False Positives: The possible return values often depend from the arguments — Solution: Take the parameters also into consideration
Thank You! adam.balogh@ericsson.com