Reviewed By: sblackshear Differential Revision: D6511316 fbshipit-source-id: 239811emaster
parent
4795139459
commit
d83a9445f1
@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2017 - present Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
TESTS_DIR = ../..
|
||||
|
||||
ANALYZER = checkers
|
||||
# see explanations in cpp/errors/Makefile for the custom isystem
|
||||
CLANG_OPTIONS = -x c++ -std=c++11 -nostdinc++ -isystem$(MODELS_DIR)/cpp/include -isystem$(CLANG_INCLUDES)/c++/v1/ -c
|
||||
INFER_OPTIONS = --uninit-only --uninit-interproc --debug-exceptions --project-root $(TESTS_DIR)
|
||||
INFERPRINT_OPTIONS = --issues-tests
|
||||
CLEAN_EXTRA = -c
|
||||
SOURCES = $(wildcard *.cpp)
|
||||
|
||||
include $(TESTS_DIR)/infer.make
|
||||
|
||||
infer-out/report.json: $(MAKEFILE_LIST)
|
||||
|
||||
infer-out/report.json: $(CLANG_DEPS) $(SOURCES) $(MAKEFILE_LIST)
|
||||
$(QUIET)$(REMOVE_DIR) buck-out && \
|
||||
$(call silent_on_success,Testing uninit analysis with inter-procedural mode,\
|
||||
$(INFER_BIN) $(INFER_OPTIONS) --results-dir $(CURDIR)/infer-out -- clang $(CLEAN_EXTRA) $(SOURCES))
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
struct is {
|
||||
int n;
|
||||
int b;
|
||||
};
|
||||
|
||||
void i_init(int* i) { *i = 10; }
|
||||
|
||||
void i_no_init(int* i) { i = 0; }
|
||||
|
||||
// error is detected before call if x was not init
|
||||
int i_inc(int x) { return x++; }
|
||||
|
||||
int no_init_in_callee_bad() {
|
||||
int a;
|
||||
int b = 0;
|
||||
|
||||
i_no_init(&a);
|
||||
|
||||
b = a; // error
|
||||
return b;
|
||||
}
|
||||
|
||||
int init_in_calee_ok() {
|
||||
int a;
|
||||
int b = 0;
|
||||
|
||||
i_init(&a);
|
||||
b = a; // OK
|
||||
return b;
|
||||
}
|
||||
|
||||
int no_init_field_in_calee_bad() {
|
||||
struct is t;
|
||||
int b = 0;
|
||||
|
||||
i_no_init(&t.n);
|
||||
|
||||
b = t.n; // error
|
||||
return b;
|
||||
}
|
||||
|
||||
int init_field_in_calee_ok() {
|
||||
struct is t;
|
||||
int b = 0;
|
||||
|
||||
i_init(&t.n);
|
||||
|
||||
b = t.n; // OK
|
||||
return b;
|
||||
}
|
||||
|
||||
int no_init_in_calee_bad2() {
|
||||
int a;
|
||||
int c = 0;
|
||||
|
||||
i_no_init(&a);
|
||||
|
||||
c = i_inc(a); // error
|
||||
return c;
|
||||
}
|
||||
|
||||
int init_in_calee_ok2() {
|
||||
int a;
|
||||
int c = 0;
|
||||
|
||||
i_init(&a);
|
||||
|
||||
c = i_inc(a); // ok
|
||||
}
|
||||
|
||||
int i_no_init_return_bad() {
|
||||
int x;
|
||||
return x; // error
|
||||
}
|
||||
|
||||
// this shows that in case a function return an uninit value, it gets the
|
||||
// blame / rather than the caller.
|
||||
int blame_on_callee() {
|
||||
int a;
|
||||
int c = i_no_init_return_bad();
|
||||
|
||||
a = c; // we don't flag the error here as it is flagged in no_init_return
|
||||
// definition
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i_maybe_init(int y, int* formal) {
|
||||
|
||||
if (y == 0) {
|
||||
*formal = 5;
|
||||
};
|
||||
}
|
||||
|
||||
void i_must_init_ok(int y, int* formal) {
|
||||
|
||||
if (y == 0) {
|
||||
*formal = 5;
|
||||
} else {
|
||||
*formal = 17;
|
||||
};
|
||||
}
|
||||
|
||||
int i_call_maybe_init_bad(int y) {
|
||||
int x;
|
||||
i_maybe_init(y, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
int i_call_must_init_ok(int y) {
|
||||
int x;
|
||||
i_must_init_ok(y, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void i_square_init(int x, int& res) { res = x * x; }
|
||||
|
||||
int i_square_no_init(int x, int& res) { return res * res; }
|
||||
|
||||
void i_use_square_OK() {
|
||||
|
||||
int i;
|
||||
i_square_init(2, i);
|
||||
}
|
||||
|
||||
void FN_use_square_bad() {
|
||||
|
||||
int i;
|
||||
i = i_square_no_init(2, i); // We should report here
|
||||
}
|
||||
|
||||
int i_no_deref(int* x) {
|
||||
int* y = 0;
|
||||
x = y;
|
||||
return *x; // this is not actually a deref of a formal
|
||||
}
|
||||
|
||||
void i_init_x(int* x) {
|
||||
int* y;
|
||||
y = x;
|
||||
*y = 25; // this is writing x. Need aliasing info
|
||||
}
|
||||
|
||||
int FP_use_init_x_OK() {
|
||||
|
||||
int a;
|
||||
i_init_x(&a);
|
||||
|
||||
return a; // We should not report here
|
||||
}
|
||||
|
||||
struct s {
|
||||
int n;
|
||||
int b;
|
||||
};
|
||||
|
||||
void init_some_field_of_struct(struct s* z) { z->n = 10; };
|
||||
|
||||
void init_full_struct(struct s* z) {
|
||||
z->n = 10;
|
||||
z->b = 17;
|
||||
};
|
||||
|
||||
int call_init_some_field_of_struct_ok() {
|
||||
struct s t;
|
||||
init_some_field_of_struct(&t);
|
||||
|
||||
return t.n;
|
||||
}
|
||||
|
||||
int call_init_some_field_of_struct_bad() {
|
||||
struct s t;
|
||||
init_some_field_of_struct(&t);
|
||||
|
||||
return t.b;
|
||||
}
|
||||
|
||||
int call_init_full_struct_ok() {
|
||||
struct s t;
|
||||
init_full_struct(&t);
|
||||
|
||||
int i = t.n;
|
||||
int b = t.b;
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
build_systems/uninit/inter_proc_uninit.cpp, FP_use_init_x_OK, 5, UNINITIALIZED_VALUE, []
|
||||
build_systems/uninit/inter_proc_uninit.cpp, call_init_some_field_of_struct_bad, 4, UNINITIALIZED_VALUE, []
|
||||
build_systems/uninit/inter_proc_uninit.cpp, i_call_maybe_init_bad, 3, UNINITIALIZED_VALUE, []
|
||||
build_systems/uninit/inter_proc_uninit.cpp, i_no_init_return_bad, 2, UNINITIALIZED_VALUE, []
|
||||
build_systems/uninit/inter_proc_uninit.cpp, no_init_field_in_calee_bad, 6, UNINITIALIZED_VALUE, []
|
||||
build_systems/uninit/inter_proc_uninit.cpp, no_init_in_calee_bad2, 6, UNINITIALIZED_VALUE, []
|
||||
build_systems/uninit/inter_proc_uninit.cpp, no_init_in_callee_bad, 6, UNINITIALIZED_VALUE, []
|
@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
void init(int* i) { *i = 10; }
|
||||
|
||||
void init_bool(bool* i) { *i = false; }
|
||||
|
||||
void no_init(int* i) { i = 0; }
|
||||
|
||||
void no_init_bool(bool* i) { i = 0; }
|
||||
|
||||
int inc(int x) { return x++; }
|
||||
// error is detected before call as we copy x
|
||||
// so no need to put it in the summary
|
||||
|
||||
int no_init_return_bad() {
|
||||
int x;
|
||||
return x; // error
|
||||
}
|
||||
|
||||
void bad1() {
|
||||
int a;
|
||||
int b = a; // Error
|
||||
int c = b; // Error but we do not report as it depends from line 20
|
||||
}
|
||||
|
||||
int bad2() {
|
||||
int a;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
no_init(&a);
|
||||
|
||||
b = a; // error
|
||||
}
|
||||
|
||||
int bad3() {
|
||||
int a;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
no_init(&a);
|
||||
|
||||
c = inc(a); // error
|
||||
}
|
||||
|
||||
int ok1() {
|
||||
int a;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
init(&a);
|
||||
c = a; // OK
|
||||
}
|
||||
|
||||
int ok2() {
|
||||
int a;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
init(&a);
|
||||
|
||||
c = inc(a); // ok
|
||||
}
|
||||
|
||||
int bad4() {
|
||||
int a;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
no_init(&a);
|
||||
|
||||
b = a; // report here error
|
||||
|
||||
c = inc(b); // do not report as it depends from line 31
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this function shows that we correctly reportat
|
||||
// line 88 but not report the error at line 90
|
||||
int bad5() {
|
||||
int a;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
no_init(&a);
|
||||
|
||||
b = a; // error
|
||||
|
||||
return b; // should not report as it depends from line 31
|
||||
}
|
||||
|
||||
// this shows that in case a function return an uninit value, it gets the blame
|
||||
// rather than the caller.
|
||||
int blame_on_callee() {
|
||||
int a;
|
||||
int c = no_init_return_bad();
|
||||
|
||||
a = c; // we don't flag the error here as it is flagged in no_init_return
|
||||
// definition
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void maybe_init(int y, int* formal) {
|
||||
|
||||
if (y == 0) {
|
||||
*formal = 5;
|
||||
};
|
||||
}
|
||||
|
||||
void must_init(int y, int* formal) {
|
||||
|
||||
if (y == 0) {
|
||||
*formal = 5;
|
||||
} else {
|
||||
*formal = 17;
|
||||
};
|
||||
}
|
||||
|
||||
int call_maybe_init_bad(int y) {
|
||||
int x;
|
||||
maybe_init(y, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
int call_must_init_ok(int y) {
|
||||
int x;
|
||||
must_init(y, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void square_init(int x, int& res) { res = x * x; }
|
||||
|
||||
int square_no_init(int x, int& res) { return res * res; }
|
||||
|
||||
void use_square_OK() {
|
||||
|
||||
int i;
|
||||
square_init(2, i);
|
||||
}
|
||||
|
||||
void use_square_bad() {
|
||||
|
||||
int i;
|
||||
i = square_no_init(2, i); // Error
|
||||
}
|
||||
|
||||
int no_deref(int* x) {
|
||||
int* y = 0;
|
||||
x = y;
|
||||
return *x; // this is not actually a deref of a formal
|
||||
}
|
||||
|
||||
void init_x(int* x) {
|
||||
int* y;
|
||||
y = x;
|
||||
*y = 25; // this is writing x
|
||||
}
|
||||
|
||||
int use_init_x_OK() {
|
||||
|
||||
int a;
|
||||
init_x(&a);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void bool1_bad() {
|
||||
bool a;
|
||||
bool b = a;
|
||||
bool c = b;
|
||||
}
|
||||
|
||||
int bool2_bad() {
|
||||
bool a;
|
||||
bool b = 0;
|
||||
bool c = 0;
|
||||
|
||||
no_init_bool(&a);
|
||||
|
||||
b = a; // error
|
||||
}
|
||||
|
||||
int bool1_ok() {
|
||||
bool a;
|
||||
bool b = 0;
|
||||
bool c = 0;
|
||||
|
||||
init_bool(&a);
|
||||
c = a; // OK
|
||||
}
|
Loading…
Reference in new issue