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