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