├── src ├── odr_violation_function_lib.cpp ├── odr_violation_function_lib.h ├── no_undefined_behavior.cpp ├── odr_violation_struct_ret_lib.h ├── virtual_call_in_destructor_link.cpp ├── reading_uninitialized_value_lib.cpp ├── virtual_call_in_constructor_link.cpp ├── dereferencing_nullptr.cpp ├── reading_uninitialized_value_lib.h ├── reading_uninitialized_value_lib_call_cref.cpp ├── non_trivial_destructor_and_global.h ├── mutate_const_value.cpp ├── virtual_call_in_constructor_lib.cpp ├── virtual_call_in_destructor_lib.cpp ├── signed_integer_overflow.cpp ├── reading_uninitialized_value_cout.cpp ├── reference_out_of_scope.cpp ├── reading_uninitialized_value_add.cpp ├── array_out_of_bounds.cpp ├── odr_violation_struct_ret_lib.cpp ├── preincrement_plus_value.cpp ├── preincrement_plus_postincrement.cpp ├── divide_by_zero.cpp ├── reading_uninitialized_value_printf.cpp ├── reading_uninitialized_value_func_arg.cpp ├── reading_uninitialized_value_return.cpp ├── non_trivial_destructor_and_global.cpp ├── reading_uninitialized_value_if.cpp ├── std_vector_reserve_set_read.cpp ├── stack_overflow.cpp ├── access_after_realloc.cpp ├── automatic_variable_over_stack.cpp ├── reading_uninitialized_value_partial.cpp ├── large_double_to_int.cpp ├── shifting_more_than_width.cpp ├── virtual_call_in_constructor_lib.hpp ├── virtual_call_in_destructor_lib.hpp ├── read_from_old_type.cpp ├── initialize_std_string_with_nullptr.cpp ├── virtual_call_in_constructor.cpp ├── virtual_call_in_destructor.cpp ├── strptime_mktime_unitialized.cpp ├── virtual_call_in_constructor_helper.cpp ├── virtual_call_in_destructor_helper.cpp ├── operator_star_on_empty_optional.cpp ├── odr_violation_function.cpp ├── malloc_cast_pod_struct.cpp ├── reinterpret_cast_int32_to_float.cpp ├── reinterpret_cast_float_to_int32.cpp ├── reinterpret_cast_int32_to_uint32.cpp ├── reinterpret_cast_uint32_to_int32.cpp ├── out_of_bounds_pointer.cpp ├── bad_alignment.cpp ├── odr_violation_struct_ret.cpp ├── reinterpret_cast_bad_size.cpp ├── reinterpret_cast_unaligned_bytes_to_uint32.cpp ├── delete_incomplete_type.cpp ├── bad_identifier_name.cpp ├── sort_comp_reflexive_int_less_equal.cpp ├── sort_comp_reflexive_double_nan.cpp └── empty_deq_begin.cpp ├── .travis.yml ├── appveyor.yml ├── .gitignore ├── ubuntu_docker_generate_results.bash ├── generate_results.ps1 ├── associate_warnings.py ├── CMakeLists.txt ├── download_msvc_files.py ├── generate_results.bash ├── LICENSE ├── print_results.py └── README.md /src/odr_violation_function_lib.cpp: -------------------------------------------------------------------------------- 1 | int foo() { return 2; } 2 | -------------------------------------------------------------------------------- /src/odr_violation_function_lib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int foo(); 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | script: ./ubuntu_docker_generate_results.bash 2 | os: linux 3 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2022 2 | build_script: 3 | - ps: .\generate_results.ps1 4 | -------------------------------------------------------------------------------- /src/no_undefined_behavior.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { return EXIT_SUCCESS; } 4 | -------------------------------------------------------------------------------- /src/odr_violation_struct_ret_lib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Point; 4 | 5 | Point foo(); 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | build 4 | native_build 5 | *swp 6 | src/a.out 7 | ub-docker-script.* 8 | -------------------------------------------------------------------------------- /src/virtual_call_in_destructor_link.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "virtual_call_in_destructor_lib.hpp" 4 | 5 | int main() { 6 | const Child c; 7 | return EXIT_SUCCESS; 8 | } 9 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "reading_uninitialized_value_lib.h" 4 | 5 | void read_from_cref(int const &cref) { std::cout << cref << '\n'; } 6 | -------------------------------------------------------------------------------- /src/virtual_call_in_constructor_link.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "virtual_call_in_constructor_lib.hpp" 4 | 5 | int main() { 6 | const Child c; 7 | return EXIT_SUCCESS; 8 | } 9 | -------------------------------------------------------------------------------- /src/dereferencing_nullptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | int32_t *p = nullptr; 7 | std::cout << *p << '\n'; 8 | return EXIT_SUCCESS; 9 | } 10 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_lib.h: -------------------------------------------------------------------------------- 1 | #ifndef READING_FROM_UNITIALIZED_LIB_H 2 | #define READING_FROM_UNITIALIZED_LIB_H 3 | 4 | void read_from_cref(const int &cref); 5 | 6 | #endif // READING_FROM_UNITIALIZED_LIB_H 7 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_lib_call_cref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "reading_uninitialized_value_lib.h" 4 | 5 | int main() { 6 | int i; 7 | read_from_cref(i); 8 | return EXIT_SUCCESS; 9 | } 10 | -------------------------------------------------------------------------------- /src/non_trivial_destructor_and_global.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern int global_int; 4 | 5 | class NonTrivialDestructor { 6 | public: 7 | ~NonTrivialDestructor(); 8 | }; 9 | 10 | NonTrivialDestructor *new_non_trivial_destructor_ptr(); 11 | -------------------------------------------------------------------------------- /src/mutate_const_value.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | const int i = 0; 6 | const int &i_ref = i; 7 | const_cast(i_ref) = 1; 8 | std::cout << i << '\n'; 9 | return EXIT_SUCCESS; 10 | } 11 | -------------------------------------------------------------------------------- /src/virtual_call_in_constructor_lib.cpp: -------------------------------------------------------------------------------- 1 | #include "virtual_call_in_constructor_lib.hpp" 2 | 3 | #include 4 | 5 | Parent::Parent() { Helper(); } 6 | 7 | void Parent::Helper() { Foo(); } 8 | 9 | void Child::Foo() { std::cout << "here\n"; } 10 | -------------------------------------------------------------------------------- /src/virtual_call_in_destructor_lib.cpp: -------------------------------------------------------------------------------- 1 | #include "virtual_call_in_destructor_lib.hpp" 2 | 3 | #include 4 | 5 | Parent::~Parent() { Helper(); } 6 | 7 | void Parent::Helper() { Foo(); } 8 | 9 | void Child::Foo() { std::cout << "here\n"; } 10 | -------------------------------------------------------------------------------- /src/signed_integer_overflow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | int32_t a = std::numeric_limits::max(); 8 | ++a; 9 | std::cout << a << '\n'; 10 | return EXIT_SUCCESS; 11 | } -------------------------------------------------------------------------------- /src/reading_uninitialized_value_cout.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/book/uninitialized 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | int32_t a; 10 | std::cout << a << '\n'; 11 | return EXIT_SUCCESS; 12 | } 13 | -------------------------------------------------------------------------------- /src/reference_out_of_scope.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int &get_bad_reference() { 5 | int a = 1; 6 | return a; 7 | } 8 | 9 | int main() { 10 | const int &a = get_bad_reference(); 11 | std::cout << "a=" << a << '\n'; 12 | return EXIT_SUCCESS; 13 | } 14 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_add.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/book/uninitialized 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | int32_t a; 10 | int32_t b; 11 | std::cout << a + b << '\n'; 12 | return EXIT_SUCCESS; 13 | } 14 | -------------------------------------------------------------------------------- /src/array_out_of_bounds.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | static constexpr int kArraySize = 10; 8 | std::array arr{}; 9 | std::cout << arr[arr.size()] << '\n'; 10 | return EXIT_SUCCESS; 11 | } 12 | -------------------------------------------------------------------------------- /src/odr_violation_struct_ret_lib.cpp: -------------------------------------------------------------------------------- 1 | struct Point { 2 | float y; 3 | float x; 4 | }; 5 | 6 | Point foo() { 7 | static constexpr float kDefaultX = 1.0F; 8 | static constexpr float kDefaultY = 2.0F; 9 | 10 | Point p{}; 11 | p.x = kDefaultX; 12 | p.y = kDefaultY; 13 | return p; 14 | } 15 | -------------------------------------------------------------------------------- /src/preincrement_plus_value.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/w/cpp/language/eval_order 3 | Undefined behavior 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | int main() { 10 | int i = 0; 11 | i = ++i + i; 12 | std::cout << i << '\n'; 13 | return EXIT_SUCCESS; 14 | } 15 | -------------------------------------------------------------------------------- /src/preincrement_plus_postincrement.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/w/cpp/language/eval_order 3 | Undefined behavior 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | int main() { 10 | int i = 0; 11 | i = ++i + i++; 12 | std::cout << i << '\n'; 13 | return EXIT_SUCCESS; 14 | } 15 | -------------------------------------------------------------------------------- /src/divide_by_zero.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | C++ 17 working draft 3 | 8.5.5.4 4 | If the second operand of / or % is zero the behavior is undefined 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | int main() { 12 | const int32_t a = 1; 13 | std::cout << a / 0 << '\n'; 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_printf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/book/uninitialized 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | int32_t a; 10 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 11 | printf("%d\n", a); 12 | return EXIT_SUCCESS; 13 | } 14 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_func_arg.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/book/uninitialized 3 | */ 4 | #include 5 | #include 6 | 7 | void maybe_set_char_ptr(char ** /*unused*/) {} 8 | 9 | int main() { 10 | char *char_ptr; 11 | maybe_set_char_ptr(&char_ptr); 12 | std::puts(char_ptr); 13 | return EXIT_SUCCESS; 14 | } 15 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_return.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | C++17 working draft 3 | 9.6.3.2 4 | "flowing off the end of a function other than main (6.8.3.1) results in 5 | undefined behavior." 6 | */ 7 | #include 8 | #include 9 | 10 | char *get_char_ptr() {} 11 | 12 | int main() { 13 | std::puts(get_char_ptr()); 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /src/non_trivial_destructor_and_global.cpp: -------------------------------------------------------------------------------- 1 | #include "non_trivial_destructor_and_global.h" 2 | 3 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 4 | int global_int = 0; 5 | 6 | NonTrivialDestructor::~NonTrivialDestructor() { ++global_int; } 7 | 8 | NonTrivialDestructor *new_non_trivial_destructor_ptr() { 9 | return new NonTrivialDestructor(); 10 | } 11 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_if.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/book/uninitialized 3 | */ 4 | #include 5 | #include 6 | 7 | int main() { 8 | bool b; 9 | if (b) { 10 | std::cout << "uninitialized value is true" << '\n'; 11 | } else { 12 | std::cout << "uninitialized value is false" << '\n'; 13 | } 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /src/std_vector_reserve_set_read.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | http://eel.is/c++draft/vector.data 3 | Returns: A pointer such that [data(), data() + size()) is a valid range. 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | std::vector v; 11 | v.reserve(1); 12 | v[0] = 'a'; 13 | std::cout << v[0] << '\n'; 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /src/stack_overflow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace { 6 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 7 | uint32_t global = 1; 8 | 9 | uint32_t call_self() { 10 | global = call_self() + 1; 11 | return global; 12 | } 13 | } // namespace 14 | 15 | int main() { 16 | std::cout << call_self() << '\n'; 17 | return EXIT_SUCCESS; 18 | } 19 | -------------------------------------------------------------------------------- /src/access_after_realloc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/w/cpp/language/ub 3 | Access to pointer passed to realloc 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | int main() { 10 | auto *p1 = static_cast(std::malloc(sizeof(int))); 11 | auto *p2 = static_cast(std::realloc(p1, sizeof(int))); 12 | std::cout << *p1 << *p2 << '\n'; 13 | free(p2); 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /src/automatic_variable_over_stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | static constexpr int kArraySize = 10000000; 7 | std::array large_var{}; 8 | large_var[0] = static_cast(1); 9 | large_var[kArraySize - 1] = static_cast(2); 10 | std::cout << large_var[0] << large_var[kArraySize - 1] << '\n'; 11 | return EXIT_SUCCESS; 12 | } 13 | -------------------------------------------------------------------------------- /src/reading_uninitialized_value_partial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/book/uninitialized 3 | */ 4 | #include 5 | #include 6 | 7 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 8 | bool global_var = false; 9 | 10 | int main() { 11 | const char *char_ptr; 12 | if (global_var) { 13 | char_ptr = "properly initialized"; 14 | } 15 | std::puts(char_ptr); 16 | return EXIT_SUCCESS; 17 | } 18 | -------------------------------------------------------------------------------- /src/large_double_to_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | C++ working draft 3 | 7.10.2 4 | If the value being converted is outside the range of values that can be 5 | represented, the behavior is undefined. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int main() { 13 | static constexpr double kLargeDouble = 1e3; 14 | std::cout << static_cast(static_cast(kLargeDouble)) << '\n'; 15 | return EXIT_SUCCESS; 16 | } 17 | -------------------------------------------------------------------------------- /src/shifting_more_than_width.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | C++17 working draft 3 | 8.5.7.1 4 | The behavior is undefined if the right operand is negative, 5 | or greater than or equal to the length in bits of the 6 | promoted left operand 7 | */ 8 | #include 9 | #include 10 | #include 11 | 12 | int main() { 13 | static constexpr uint32_t kU = 0U; 14 | static constexpr int kShift = 33; 15 | std::cout << (kU << kShift) << '\n'; 16 | return EXIT_SUCCESS; 17 | } 18 | -------------------------------------------------------------------------------- /src/virtual_call_in_constructor_lib.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Parent { 4 | public: 5 | Parent(); 6 | ~Parent() = default; 7 | Parent(const Parent &) = default; 8 | Parent &operator=(const Parent &) = default; 9 | Parent(Parent &&) = default; 10 | Parent &operator=(Parent &&) = default; 11 | 12 | virtual void Foo() = 0; 13 | 14 | private: 15 | void Helper(); 16 | }; 17 | 18 | class Child : public Parent { 19 | public: 20 | void Foo() override; 21 | }; 22 | -------------------------------------------------------------------------------- /src/virtual_call_in_destructor_lib.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Parent { 4 | public: 5 | Parent() = default; 6 | virtual ~Parent(); 7 | Parent(const Parent &) = default; 8 | Parent &operator=(const Parent &) = default; 9 | Parent(Parent &&) = default; 10 | Parent &operator=(Parent &&) = default; 11 | 12 | virtual void Foo() = 0; 13 | 14 | private: 15 | void Helper(); 16 | }; 17 | 18 | class Child : public Parent { 19 | public: 20 | void Foo() override; 21 | }; 22 | -------------------------------------------------------------------------------- /src/read_from_old_type.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://en.cppreference.com/w/cpp/language/ub 3 | Invalid scalar 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | int main() { 10 | bool boolean = true; 11 | auto *const p_boolean = reinterpret_cast(&boolean); 12 | static constexpr unsigned char kModifiedValue = 10; 13 | *p_boolean = kModifiedValue; 14 | // reading from b is now UB 15 | const bool out_bool = boolean; 16 | std::cout << out_bool << '\n'; 17 | return EXIT_SUCCESS; 18 | } 19 | -------------------------------------------------------------------------------- /src/initialize_std_string_with_nullptr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | http://www.cplusplus.com/reference/string/string/string/ 3 | 4 | from c-string (4) string (const char* s); 5 | ... 6 | If s is a null pointer, ... it causes undefined behavior. 7 | */ 8 | #include 9 | #include 10 | #include 11 | 12 | const char *get_c_str() { return nullptr; } 13 | 14 | int main() { 15 | const char *const c_str = get_c_str(); 16 | const std::string s(c_str); 17 | std::cout << s << '\n'; 18 | return EXIT_SUCCESS; 19 | } 20 | -------------------------------------------------------------------------------- /src/virtual_call_in_constructor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Parent { 5 | public: 6 | Parent() { Foo(); } 7 | virtual ~Parent() = default; 8 | Parent(const Parent &) = default; 9 | Parent &operator=(const Parent &) = default; 10 | Parent(Parent &&) = default; 11 | Parent &operator=(Parent &&) = default; 12 | 13 | virtual void Foo() = 0; 14 | }; 15 | 16 | class Child : public Parent { 17 | public: 18 | void Foo() override { std::cout << "here\n"; } 19 | }; 20 | 21 | int main() { 22 | Child c; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/virtual_call_in_destructor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Parent { 5 | public: 6 | Parent() = default; 7 | virtual ~Parent() { Foo(); } 8 | Parent(const Parent &) = default; 9 | Parent &operator=(const Parent &) = default; 10 | Parent(Parent &&) = default; 11 | Parent &operator=(Parent &&) = default; 12 | 13 | virtual void Foo() = 0; 14 | }; 15 | 16 | class Child : public Parent { 17 | public: 18 | void Foo() override { std::cout << "here\n"; } 19 | }; 20 | 21 | int main() { 22 | const Child c; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/strptime_mktime_unitialized.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://stackoverflow.com/a/24185697 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | const char *const kTime = "2019"; 12 | const char *const kFormat = "%Y"; 13 | tm tmp_time; 14 | // included in ctime 15 | // NOLINTNEXTLINE(misc-include-cleaner) 16 | strptime(kTime, kFormat, &tmp_time); 17 | // proper initialization 18 | // tmp_time.tm_isdst = -1; 19 | const time_t time = mktime(&tmp_time); 20 | std::cout << static_cast(time) << '\n'; 21 | return EXIT_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /src/virtual_call_in_constructor_helper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Parent { 5 | public: 6 | Parent() { Helper(); } 7 | virtual ~Parent() = default; 8 | Parent(const Parent &) = default; 9 | Parent &operator=(const Parent &) = default; 10 | Parent(Parent &&) = default; 11 | Parent &operator=(Parent &&) = default; 12 | 13 | virtual void Foo() = 0; 14 | 15 | private: 16 | void Helper() { Foo(); } 17 | }; 18 | 19 | class Child : public Parent { 20 | public: 21 | void Foo() override { std::cout << "here\n"; } 22 | }; 23 | 24 | int main() { 25 | Child c; 26 | return EXIT_SUCCESS; 27 | } 28 | -------------------------------------------------------------------------------- /src/virtual_call_in_destructor_helper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Parent { 5 | public: 6 | Parent() = default; 7 | virtual ~Parent() { Helper(); } 8 | Parent(const Parent &) = default; 9 | Parent &operator=(const Parent &) = default; 10 | Parent(Parent &&) = default; 11 | Parent &operator=(Parent &&) = default; 12 | 13 | virtual void Foo() = 0; 14 | 15 | private: 16 | void Helper() { Foo(); } 17 | }; 18 | 19 | class Child : public Parent { 20 | public: 21 | void Foo() override { std::cout << "here\n"; } 22 | }; 23 | 24 | int main() { 25 | const Child c; 26 | return EXIT_SUCCESS; 27 | } 28 | -------------------------------------------------------------------------------- /src/operator_star_on_empty_optional.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | https://eel.is/c++draft/optional.observe#1 3 | constexpr const T* operator->() const; 4 | constexpr T* operator->(); 5 | Preconditions: *this contains a value. 6 | 7 | https://en.cppreference.com/w/cpp/utility/optional/operator* 8 | The behavior is undefined if *this does not contain a value. 9 | 10 | Related news story 11 | https://arstechnica.com/gadgets/2021/07/google-pushed-a-one-character-typo-to-production-bricking-chrome-os-devices/ 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | int main() { 19 | std::optional foo; 20 | std::cout << *foo << '\n'; 21 | return EXIT_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /src/odr_violation_function.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | CppCon 2019: Louis Dionne “The C++ ABI From the Ground Up” 3 | https://youtu.be/DZ93lP1I7wU?t=1651 4 | 5 | One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined. 6 | https://en.cppreference.com/w/cpp/language/definition 7 | */ 8 | 9 | #include 10 | 11 | #include "odr_violation_function_lib.h" 12 | 13 | int foo() { return 1; } 14 | 15 | int main() { 16 | std::cout << foo() << '\n'; 17 | return EXIT_SUCCESS; 18 | } 19 | -------------------------------------------------------------------------------- /src/malloc_cast_pod_struct.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Unlike in C, however, objects with trivial default constructors cannot be 3 | created by simply reinterpreting suitably aligned storage, such as memory 4 | allocated with std::malloc: placement-new is required to formally introduce a 5 | new object and avoid potential undefined behavior. 6 | https://en.cppreference.com/w/cpp/language/default_constructor#Trivial_default_constructor 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | struct MyPod { 13 | int x; 14 | }; 15 | 16 | int main() { 17 | void *raw_ptr = malloc(sizeof(MyPod)); 18 | auto *const my_pod = static_cast(raw_ptr); 19 | my_pod->x = 1; 20 | std::cout << my_pod->x << '\n'; 21 | free(raw_ptr); 22 | return EXIT_SUCCESS; 23 | } 24 | -------------------------------------------------------------------------------- /src/reinterpret_cast_int32_to_float.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://eel.is/c++draft/expr#basic.lval-11 3 | 7.2.1.11 4 | # 5 | If a program attempts to access ([defns.access]) the stored value of an object 6 | through a glvalue whose type is not similar ([conv.qual]) to one of the 7 | following types the behavior is undefined:52 8 | 9 | (11.1) 10 | the dynamic type of the object, 11 | (11.2) 12 | a type that is the signed or unsigned type corresponding to the dynamic type 13 | of the object, or (11.3) a char, unsigned char, or std​::​byte type. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | const int32_t a = 1; 22 | std::cout << *reinterpret_cast(&a) << '\n'; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/reinterpret_cast_float_to_int32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://eel.is/c++draft/expr#basic.lval-11 3 | 7.2.1.11 4 | # 5 | If a program attempts to access ([defns.access]) the stored value of an object 6 | through a glvalue whose type is not similar ([conv.qual]) to one of the 7 | following types the behavior is undefined:52 8 | 9 | (11.1) 10 | the dynamic type of the object, 11 | (11.2) 12 | a type that is the signed or unsigned type corresponding to the dynamic type 13 | of the object, or (11.3) a char, unsigned char, or std​::​byte type. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | const float a = 1.0F; 22 | std::cout << *reinterpret_cast(&a) << '\n'; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/reinterpret_cast_int32_to_uint32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://eel.is/c++draft/expr#basic.lval-11 3 | 7.2.1.11 4 | # 5 | If a program attempts to access ([defns.access]) the stored value of an object 6 | through a glvalue whose type is not similar ([conv.qual]) to one of the 7 | following types the behavior is undefined:52 8 | 9 | (11.1) 10 | the dynamic type of the object, 11 | (11.2) 12 | a type that is the signed or unsigned type corresponding to the dynamic type 13 | of the object, or (11.3) a char, unsigned char, or std​::​byte type. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | const int32_t a = 1; 22 | std::cout << *reinterpret_cast(&a) << '\n'; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/reinterpret_cast_uint32_to_int32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://eel.is/c++draft/expr#basic.lval-11 3 | 7.2.1.11 4 | # 5 | If a program attempts to access ([defns.access]) the stored value of an object 6 | through a glvalue whose type is not similar ([conv.qual]) to one of the 7 | following types the behavior is undefined:52 8 | 9 | (11.1) 10 | the dynamic type of the object, 11 | (11.2) 12 | a type that is the signed or unsigned type corresponding to the dynamic type 13 | of the object, or (11.3) a char, unsigned char, or std​::​byte type. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | const uint32_t a = 1; 22 | std::cout << *reinterpret_cast(&a) << '\n'; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/out_of_bounds_pointer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | C++17 working draft 3 | 8.5.6.4 4 | If the expression P points to element x[i] of an array object x with n 5 | elements,86 the expressions P + J and J + P (where J has the value j) 6 | point to the (possibly-hypothetical) element x[i + j] if 0 ≤ i + j ≤ n; 7 | otherwise, the behavior is undefined. Likewise, the expression P - J 8 | points to the (possibly-hypothetical) element x[i − j] 9 | if 0 ≤ i − j ≤ n; otherwise, the behavior is undefined. 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main() { 17 | static constexpr int kArraySize = 10; 18 | std::array arr{}; 19 | std::cout << static_cast(arr.data() - 1) << '\n'; 20 | return EXIT_SUCCESS; 21 | } 22 | -------------------------------------------------------------------------------- /src/bad_alignment.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The C Standard, 6.3.2.3, paragraph 7 3 | 4 | A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | struct SomeChars { 13 | static constexpr int kFourCharsSize = 4; 14 | char single_char; 15 | std::array four_chars; 16 | }; 17 | 18 | int main() { 19 | SomeChars some_chars = {}; 20 | some_chars.four_chars[0] = '1'; 21 | const int32_t a = *reinterpret_cast(some_chars.four_chars.data()); 22 | std::cout << a << '\n'; 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /src/odr_violation_struct_ret.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | CppCon 2019: Louis Dionne “The C++ ABI From the Ground Up” 3 | https://youtu.be/DZ93lP1I7wU?t=1000 4 | 5 | One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined. 6 | https://en.cppreference.com/w/cpp/language/definition 7 | */ 8 | 9 | #include 10 | 11 | #include "odr_violation_struct_ret_lib.h" 12 | 13 | struct Point { 14 | float x; 15 | float y; 16 | }; 17 | 18 | int main() { 19 | const Point p(foo()); 20 | std::cout << p.x << ", " << p.y << '\n'; 21 | return EXIT_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /src/reinterpret_cast_bad_size.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://eel.is/c++draft/expr#basic.lval-11 3 | 7.2.1.11 4 | # 5 | If a program attempts to access ([defns.access]) the stored value of an object 6 | through a glvalue whose type is not similar ([conv.qual]) to one of the 7 | following types the behavior is undefined:52 8 | 9 | (11.1) 10 | the dynamic type of the object, 11 | (11.2) 12 | a type that is the signed or unsigned type corresponding to the dynamic type 13 | of the object, or (11.3) a char, unsigned char, or std​::​byte type. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | int main() { 23 | const std::array a{}; 24 | std::cout << *reinterpret_cast(&a) << '\n'; 25 | return EXIT_SUCCESS; 26 | } 27 | -------------------------------------------------------------------------------- /src/reinterpret_cast_unaligned_bytes_to_uint32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://eel.is/c++draft/expr#basic.lval-11 3 | 7.2.1.11 4 | # 5 | If a program attempts to access ([defns.access]) the stored value of an object 6 | through a glvalue whose type is not similar ([conv.qual]) to one of the 7 | following types the behavior is undefined:52 8 | 9 | (11.1) 10 | the dynamic type of the object, 11 | (11.2) 12 | a type that is the signed or unsigned type corresponding to the dynamic type 13 | of the object, or (11.3) a char, unsigned char, or std​::​byte type. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | int main() { 23 | const std::array a{}; 24 | std::cout << *reinterpret_cast(&a) << '\n'; 25 | return EXIT_SUCCESS; 26 | } 27 | -------------------------------------------------------------------------------- /src/delete_incomplete_type.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | http://eel.is/c++draft/expr.delete 3 | 4 | 7 Expressions 5 | 7.6 Compound expressions 6 | 7.6.2 Unary expressions 7 | 7.6.2.8 Delete 8 | 9 | If the object being deleted has incomplete class type at the point of deletion 10 | and the complete class has a non-trivial destructor or a deallocation function, 11 | the behavior is undefined. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | // intentionally missing 18 | //#include "non_trivial_destructor_and_global.h" 19 | 20 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 21 | extern int global_int; 22 | class NonTrivialDestructor; 23 | NonTrivialDestructor *new_non_trivial_destructor_ptr(); 24 | 25 | void foo() { 26 | const NonTrivialDestructor *a = new_non_trivial_destructor_ptr(); 27 | delete a; 28 | } 29 | 30 | int main() { 31 | foo(); 32 | std::cout << global_int << '\n'; 33 | return EXIT_SUCCESS; 34 | } 35 | -------------------------------------------------------------------------------- /src/bad_identifier_name.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | http://eel.is/c++draft/lex.name#3 3 | 5 Lexical conventions [lex] 4 | 5.10 Identifiers [lex.name] 5 | 3. In addition, some identifiers are reserved for use by C++ implementations and 6 | shall not be used otherwise; no diagnostic is required. (3.1) Each identifier 7 | that contains a double underscore __ or begins with an underscore followed by an 8 | uppercase letter is reserved to the implementation for any use. (3.2) Each 9 | identifier that begins with an underscore is reserved to the implementation for 10 | use as a name in the global namespace. 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | const int _underscore_global = 0; 17 | 18 | int main() { 19 | const int __double_underscores_in_front = 1; 20 | const int double_underscores__in_middle = 2; 21 | const int double_underscores_at_end__ = 3; 22 | const int _Undercore_and_uppercase_char = 4; 23 | std::cout << _underscore_global << __double_underscores_in_front 24 | << double_underscores__in_middle << double_underscores_at_end__ 25 | << _Undercore_and_uppercase_char << '\n'; 26 | return EXIT_SUCCESS; 27 | } 28 | -------------------------------------------------------------------------------- /src/sort_comp_reflexive_int_less_equal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | 18 Concepts Library 3 | 18.7 Callable Concepts 4 | 18.7.7 Concept strict_weak_order 5 | 2 The term strict refers to the requirement of an irreflexive relation (!comp(x, 6 | x) for all x), and the term weak to requirements that are not as strong as those 7 | for a total ordering, but stronger than those for a partial ordering. If we 8 | define equiv(a, b) as !comp(a, b) && !comp(b, a), then the requirements are that 9 | comp and equiv both be transitive relations: 10 | 11 | https://eel.is/c++draft/concept.strictweakorder#2 12 | 13 | 1 <= 1 == true -> reflexive 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | int main() { 23 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 24 | std::vector my_vec{{5, 3, 2, 1, 7}}; 25 | std::sort(my_vec.begin(), my_vec.end(), std::less<>()); 26 | for (const int value : my_vec) { 27 | // Avoid iostream because a lack of instrumentation may produce false 28 | // positives for libc++ with memory sanitizer 29 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 30 | printf("%d, ", value); 31 | } 32 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 33 | printf("\n"); 34 | return EXIT_SUCCESS; 35 | } 36 | -------------------------------------------------------------------------------- /ubuntu_docker_generate_results.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Setup noble with proper tools 3 | 4 | tmpfile=$(mktemp ub-docker-script.XXXXXX) 5 | exec 3>"$tmpfile" 6 | 7 | cat >&3 < /tmp/update.txt 2>&1 12 | apt -qq -o Dpkg::Use-Pty=0 install adduser clang clang-tidy cmake cppcheck g++ parallel perl python3 valgrind -y > /tmp/install.txt 2>&1 13 | deluser --remove-home ubuntu 14 | adduser --disabled-password --uid $(id -u) --gecos "" $(whoami) > /tmp/add_user.txt 2>&1 15 | if [[ \$* == *--interactive* ]]; then 16 | usermod -aG sudo $(whoami) 17 | apt -qq -o Dpkg::Use-Pty=0 install man sudo vim -y >> /tmp/install.txt 2>&1 18 | fi 19 | mkdir /home/$(whoami)/.parallel 20 | touch /home/$(whoami)/.parallel/will-cite 21 | mkdir /home/$(whoami)/.parallel/semaphores 22 | chown -R $(whoami):$(whoami) /home/$(whoami)/.parallel 23 | if [[ \$* != *--interactive* ]]; then 24 | su - $(whoami) -c 'cd $(pwd) && ./generate_results.bash' 25 | else 26 | su - $(whoami) -c "cd $(pwd)" 27 | fi 28 | EOL 29 | 30 | cat "$tmpfile" 31 | chmod +x "$tmpfile" 32 | 33 | if [[ $* == *--interactive* ]]; then 34 | INNER_FLAG=--interactive 35 | DOCKER_FLAG=-it 36 | fi 37 | 38 | docker run \ 39 | $DOCKER_FLAG \ 40 | --rm \ 41 | --cap-add SYS_PTRACE \ 42 | --mount type=bind,source=$(pwd),target=$(pwd) \ 43 | ubuntu:noble-20240605 \ 44 | /bin/bash -x $(pwd)/"$tmpfile" $INNER_FLAG 45 | rm "$tmpfile" 46 | 47 | -------------------------------------------------------------------------------- /src/sort_comp_reflexive_double_nan.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | 18 Concepts Library 3 | 18.7 Callable Concepts 4 | 18.7.7 Concept strict_weak_order 5 | 2 The term strict refers to the requirement of an irreflexive relation (!comp(x, 6 | x) for all x), and the term weak to requirements that are not as strong as those 7 | for a total ordering, but stronger than those for a partial ordering. If we 8 | define equiv(a, b) as !comp(a, b) && !comp(b, a), then the requirements are that 9 | comp and equiv both be transitive relations: 10 | 11 | https://eel.is/c++draft/concept.strictweakorder#2 12 | 13 | 1.0 < NaN == false 14 | NaN < 1.0 == false 15 | but 1 != NaN 16 | So < fails to define equals for NaN and other values 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | int main() { 27 | // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) 28 | std::vector my_vec{{-1.0, std::nan(""), -2.0, 0.0, std::nan("")}}; 29 | std::sort(my_vec.begin(), my_vec.end()); 30 | for (const double value : my_vec) { 31 | // Avoid iostream because a lack of instrumentation may produce false 32 | // positives for libc++ with memory sanitizer 33 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 34 | printf("%f, ", value); 35 | } 36 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 37 | printf("\n"); 38 | 39 | return EXIT_SUCCESS; 40 | } 41 | -------------------------------------------------------------------------------- /generate_results.ps1: -------------------------------------------------------------------------------- 1 | if (-not (Test-Path build)) { 2 | md build 3 | } 4 | cd build 5 | cmake .. -G "Visual Studio 17 2022" -A x64 6 | 7 | function Build-And-Run($Config) { 8 | echo "Build $Config" 9 | cmake --build . --config $Config 1> warnings_enc.txt 10 | Get-Content warnings_enc.txt | Set-Content -Encoding utf8 warnings.txt 11 | if (Test-Path $Config/warnings.txt) { 12 | rm $Config/warnings.txt 13 | } 14 | mv warnings.txt "$Config/warnings.txt" 15 | cd $Config 16 | echo "Run $Config" 17 | Run-All-Programs 18 | cd .. 19 | } 20 | 21 | function Run-All-Programs() { 22 | if (Test-Path results.txt) { 23 | rm results.txt 24 | } 25 | Get-ChildItem -recurse -include "*.exe" | 26 | Foreach-Object { 27 | $pinfo = New-Object System.Diagnostics.ProcessStartInfo 28 | $pinfo.FileName = $_.FullName 29 | $p = New-Object System.Diagnostics.Process 30 | $p.StartInfo = $pinfo 31 | $p.Start() | Out-Null 32 | $wait_status=$p.WaitForExit(1000) 33 | if ($wait_status -ne "True") {echo $p.kill()} 34 | Add-Content -path results.txt -Value "$([io.path]::GetFileNameWithoutExtension($_.FullName)) $($p.ExitCode)" 35 | } 36 | } 37 | 38 | Build-And-Run -Config Debug 39 | Build-And-Run -Config RelWithDebInfo 40 | 41 | cd .. 42 | 43 | echo "Compiler warnings" 44 | python associate_warnings.py --cpp_dir=src --out_file="build/Debug/warnings_table.txt" --warnings_file="build/Debug/warnings.txt" 45 | python associate_warnings.py --cpp_dir=src --out_file="build/RelWithDebInfo/warnings_table.txt" --warnings_file="build/RelWithDebInfo/warnings.txt" 46 | echo "MSVC Debug Compiler Warnings Start" 47 | type build\Debug\warnings_table.txt 48 | echo "MSVC Debug Compiler Warnings End" 49 | echo "MSVC RelWithDebInfo Compiler Warnings Start" 50 | type build\RelWithDebInfo\warnings_table.txt 51 | echo "MSVC RelWithDebInfo Compiler Warnings End" 52 | echo "Runtime Results" 53 | echo "MSVC Debug Crashes Start" 54 | type build\Debug\results.txt 55 | echo "MSVC Debug Crashes End" 56 | echo "MSVC RelWithDebInfo Crashes Start" 57 | type build\RelWithDebInfo\results.txt 58 | echo "MSVC RelWithDebInfo Crashes End" 59 | -------------------------------------------------------------------------------- /src/empty_deq_begin.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQWm8GA6ZAB36kqqBgQDKyJvRABGACzDRBAKoBnTAAUAHiADkABj2kAViABspWkwahkAUgBMAISfPSG%2BsgJ5RlRugAwqi0AK4sDCAAzAAcpAEAMtyYAHLhAEaYxHKOpPyoaoS%2BDMFhEdFx%2BYU%2BokkMqRlZOR6YXjUM4gRMxASl4ZGxLW3Fnd0EdQ0smdmyuWpdPX3lg/NjE2lTTbMAlB6oocTI7HpOUdzIYVgA1PZRgcjz%2BGK32PYGAIKn55eYN3cPBHQtDw6Reb0%2BjjODAuoWut0CWAAjqFMGCPl9oT8/oFfPNiJhWGjPh9uAQrpxuBBtjcAOyuD5XRlXNAMeaYbT8YhXR4gECk8zyAD6ZIA1gARZTYbRHTDoAAqCDwagAatIUX8xVdZAYdbqdbd6cT3kzuYDeUiUfDSS8rpgWPwCABPQVIg3gk08vliAXC5n7MRZDVXAxu9EMpkAd0V9CuEAAVHaHc6kTxMsBKdT4Vqbo5zE5zH7QgGuVnxZLpZhZQqlaqwphM3T3SamW43GgiwQsqHjS2aWKm4zPe2yfCs05HO3i0Hx9is5POyW7lmwCcAKyBBgr7sDq74ggHBhXbAADQAknLBeIVIFAthxOJt33wXpdrR9KvjJFDMZUBwuLwBCEAh9CMbZdgQAksGyKlSBFaIoh4KIkOQlCUMsN89HkYwWDkHVSC/IxSF/PRjDUEADFIYDv12OBYBgRAUFQe06CychKDQZj6GyYBZFXXIaFoBcyIgdIQOMdJuG6R19FkcTJOIR0AHl0hMTBvBk4wOLYMRFIYWhpO/UgsHSUJgECaRaDIvRZKMu0bGAGRDPwfFvDwAA3TArMI9k1NCTsNPIAMMMI4F0mIKTgiwMTKOIPAcOs4wPOIdICkwMU7NsYFbDE3YqGsYAVTwTAI0U/hGACkQxEkaR2AUJQxHULRdEMsxZCseyUFbFwrBBMjIF2VAHWKKyfyS2KsD6mDPDU9p/AYIIQn6OR4nm9ZGhmPICiKUQlkiNqqm2hg1s2Dbptc0RRkWRbyjas72ku8Zkg2aZltWK6yj2jwFke%2Bpnq2XY1H2Q52HMV930/aLiKubQYnMABaAUrmAZBkC1VceEcWNcEIEgcyiUHjCo0DwMgpoYLgpDENQ6mkPQ/QsNIHDVwogif30UjyMonLSFohifOQPySDYiBugKzQbFacQEFQCMvxsjj%2BDoJh2nF%2BpaClmXWdIBWWO42Q6p1riUlYY5NKYxWuMUvyNdl6L%2BfeYgCvZ%2BJtDUzonmdyqJCkGQ6q9xqdGi1r2uyhwXDcHr0kmgahtEEaiLGvAJvgXZiA7OLMDlVAQmjvYDiOCwvqeVXJel22EpiytOYjcL%2BA0sG9A/fDIf0KVfKILkYfhxHkdR/WeHkWNAi69wj3wDu8YJrnqJJpgoMoBuGaZlmW5IjxOaJl9dgphCaZpum9CiCHDOIwnud5i%2BkH5wWyAoEXHbUEv1bLuWzc45Xiifm2tcNpoLns2YeFf7EGNmwZ2wCrYSBfnbV2yAHZOzXvzd23BPbKGqr7RQ/sNCBxaiAXI1hQ4j0jrnQa7R46oETsnfqpA05iAzlnHOKc87A0Lo8bgX9oEVxrkwOuCUG5Ny1sRNuAsJ5dwRoPf%2BtgtSOB4AYWRQ8iFjxxiWSEU9N5gVgvBKme8UJWHpthOQABOHgMRZiyBpKuWIURmYGHkLkQRzsyIUXUTzeiEAkDAOFsAlABDgCOH1hRASQlKCiUMhJZgCkArhKkspVS6kK5aUYAQXS%2BlorGVMuZWglkApYE4JlY4hFnIzXcp5GB7djg2VJK0aKoVwoKUigUwmsV4o2SSilDQ6U8kOW4KAaiwh8qFWKqVcqFcvboNqpg5QAdmqETMPgjqYdXDdVCiQ2OrJnYUKyONUp1C7rFDmgtD6y1EhPXWstA67RdrnK2u0Y6L1bqtGKRdb6VyHnDGeWsU5J1XovOup9N6P1Jj3IBkDAuoM9GN2PoRKGYjEaSOAFcfxPBZDyIgNjCepw1E5VnvPGCGEl54JiCYwx/iDCyHMIY2IMRYiyCiM3E%2BjiN7nzcUgIgIRhaiysnDZAEFkAijULcMUcZSBwyoKEHlhQmBwywFQJgoRBJw1FuEJJagRWATQPiYAoQk6tGSGoOGmselwzYCwEgjo1WCA1ZgLVOqsqeThpyVAcMnRlThviKpxBOSYAINypg8wLX8CtTarAdr9UMCdZwLJqBkAisVIBOG4bjUWWjSK01UEGB4AAF6YDhqEDQzrwp0CNXuA8zrHRlRFWKiVeApUyrlQqpV2kCD6p9pZEVWS3IsFCsgOGwq3WQSYBJYETo4Y6roTQLIcN6C2AIAgEV0gFxSrxOKn1/AmB8sVcCYADB52CSyFKosxAQi0CndnfgahjCco4ZraKwDQHHFhRI3xiKUUou8uPEgSdC5jJ9hM%2BqqhsEzOMHMxmoh12oHRSQAAEn65wlYGDvEFsM%2Bo6AAqmuYGgSDxBkNobA2gZBr8i4oLXmwhg17y42TZbQU8qH4U%2BHQI6AgtCRSkG4bw2S/CoVsz0PC51SdHSxiY0WEU1JH3MmfUit9WMP0qPxqQK4wROKBlOI4bYZ8Z4QoJauFFjhDGrhpI4XThnzC8QsfS6FjLnHYs0ZTHRqEIVH3M9x9TxMIWOC40RZ26jdhJUKH4eQQA%3D 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | constexpr std::int64_t kDontExceedThisValue = 100000000; 12 | 13 | std::deque empty_deq; 14 | std::int64_t counter = 0; 15 | 16 | while (*empty_deq.begin() < 1 && counter < kDontExceedThisValue) { 17 | ++counter; 18 | } 19 | std::cout << "counter = " << counter << '\n'; 20 | 21 | return EXIT_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /associate_warnings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding=utf-8 3 | 4 | import argparse 5 | import os 6 | 7 | 8 | def parse_args(): 9 | parser = argparse.ArgumentParser( 10 | description='Associate tests to warnings.') 11 | parser.add_argument('--cpp_dir') 12 | parser.add_argument('--out_file', type=argparse.FileType('w'), 13 | default="warnings_table.txt") 14 | parser.add_argument('--warnings_file', type=argparse.FileType('r'), 15 | default="warnings.txt", 16 | help='warnings files to read') 17 | return parser.parse_args() 18 | 19 | 20 | def get_cpp_files(path, extension): 21 | output = [] 22 | for (dirpath, dirnames, filenames) in os.walk(path): 23 | for filename in filenames: 24 | if len(filename) > len(extension) and \ 25 | extension in filename and filename not in output: 26 | output.append(dirpath + "/" + filename) 27 | return output 28 | 29 | 30 | def parse_warnings(file_handle, test_names): 31 | warnings_dict = {} 32 | msvc = False 33 | for test_name in test_names: 34 | warnings_dict[test_name] = "" 35 | msvc_triggered = False 36 | for l in file_handle: 37 | for test_name in test_names: 38 | if test_name in l.replace("\\", "/"): 39 | warning = "" 40 | msvc_trigger = ": warning C" 41 | if msvc_trigger in l: 42 | msvc = True 43 | warning = l[l.find(msvc_trigger) + 44 | len(msvc_trigger):].split()[0][:-1] 45 | msvc_triggered = True 46 | start_bracket = l.rfind("[") 47 | end_bracket = l.rfind("]") 48 | # clang, cppcheck, gcc 49 | if start_bracket > 0 and end_bracket > -1 and start_bracket < end_bracket and not msvc_triggered: 50 | warning = l[start_bracket+1:end_bracket] 51 | if len(warning) > 0: 52 | if warning in warnings_dict[test_name]: 53 | break 54 | if warnings_dict[test_name] == "1": 55 | warnings_dict[test_name] = "" 56 | elif "" != warnings_dict[test_name]: 57 | warnings_dict[test_name] += "," 58 | warnings_dict[test_name] += warning 59 | break 60 | elif warnings_dict[test_name] == "" and ("warning" in l.lower() or "error" in l.lower()) and not "/errorReport" in l: 61 | warnings_dict[test_name] = "1" 62 | 63 | # handle the fact that it does not compile 64 | if msvc: 65 | del warnings_dict["src/reading_uninitialized_value_return.cpp"] 66 | del warnings_dict["src/strptime_mktime_unitialized.cpp"] 67 | 68 | return warnings_dict 69 | 70 | 71 | def write_file(warnings_dict, out_file): 72 | for key, value in warnings_dict.items(): 73 | short_name = key[key.rfind("/")+1:key.rfind(".")] 74 | out_file.write(short_name + " " + value + "\n") 75 | 76 | 77 | if __name__ == "__main__": 78 | args = parse_args() 79 | extension = ".cpp" 80 | test_names = get_cpp_files(args.cpp_dir, extension) 81 | warnings_dict = parse_warnings(args.warnings_file, test_names) 82 | write_file(warnings_dict, args.out_file) 83 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7.2) 2 | project(undefined_behavior_study) 3 | 4 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" 5 | OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -Wall -Wextra -Wpedantic") 7 | elseif(MSVC) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++20") 9 | endif() 10 | 11 | set(executables 12 | access_after_realloc 13 | array_out_of_bounds 14 | automatic_variable_over_stack 15 | bad_alignment 16 | bad_identifier_name 17 | delete_incomplete_type 18 | dereferencing_nullptr 19 | divide_by_zero 20 | empty_deq_begin 21 | initialize_std_string_with_nullptr 22 | large_double_to_int 23 | malloc_cast_pod_struct 24 | mutate_const_value 25 | no_undefined_behavior 26 | odr_violation_function 27 | odr_violation_struct_ret 28 | operator_star_on_empty_optional 29 | out_of_bounds_pointer 30 | preincrement_plus_postincrement 31 | preincrement_plus_value 32 | read_from_old_type 33 | reading_uninitialized_value_add 34 | reading_uninitialized_value_cout 35 | reading_uninitialized_value_func_arg 36 | reading_uninitialized_value_if 37 | reading_uninitialized_value_lib_call_cref 38 | reading_uninitialized_value_partial 39 | reading_uninitialized_value_printf 40 | reference_out_of_scope 41 | reinterpret_cast_bad_size 42 | reinterpret_cast_float_to_int32 43 | reinterpret_cast_int32_to_float 44 | reinterpret_cast_int32_to_uint32 45 | reinterpret_cast_uint32_to_int32 46 | reinterpret_cast_unaligned_bytes_to_uint32 47 | shifting_more_than_width 48 | signed_integer_overflow 49 | sort_comp_reflexive_double_nan 50 | sort_comp_reflexive_int_less_equal 51 | stack_overflow 52 | std_vector_reserve_set_read 53 | virtual_call_in_constructor_helper 54 | virtual_call_in_constructor_link 55 | virtual_call_in_destructor_helper 56 | virtual_call_in_destructor_link) 57 | 58 | # Only build these files on compilers that will successfully compile them 59 | if(NOT MSVC) 60 | list(APPEND executables reading_uninitialized_value_return 61 | strptime_mktime_unitialized) 62 | endif() 63 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 64 | list(APPEND executables virtual_call_in_destructor) 65 | list(APPEND executables virtual_call_in_constructor) 66 | endif() 67 | 68 | foreach(executable ${executables}) 69 | add_executable(${executable} src/${executable}.cpp) 70 | endforeach() 71 | 72 | add_library(non_trivial_destructor_and_global_lib src/non_trivial_destructor_and_global.cpp) 73 | add_library(odr_violation_function_lib src/odr_violation_function_lib.cpp) 74 | add_library(odr_violation_struct_ret_lib src/odr_violation_struct_ret_lib.cpp) 75 | add_library(reading_uninitialized_value_lib 76 | src/reading_uninitialized_value_lib.cpp) 77 | add_library(virtual_call_in_destructor_lib 78 | src/virtual_call_in_destructor_lib.cpp) 79 | add_library(virtual_call_in_constructor_lib 80 | src/virtual_call_in_constructor_lib.cpp) 81 | 82 | target_link_libraries(delete_incomplete_type PRIVATE non_trivial_destructor_and_global_lib) 83 | target_link_libraries(odr_violation_function PRIVATE odr_violation_function_lib) 84 | target_link_libraries(odr_violation_struct_ret 85 | PRIVATE odr_violation_struct_ret_lib) 86 | target_link_libraries(reading_uninitialized_value_lib_call_cref 87 | PRIVATE reading_uninitialized_value_lib) 88 | target_link_libraries(virtual_call_in_destructor_link 89 | PRIVATE virtual_call_in_destructor_lib) 90 | target_link_libraries(virtual_call_in_constructor_link 91 | PRIVATE virtual_call_in_constructor_lib) 92 | -------------------------------------------------------------------------------- /download_msvc_files.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding=utf-8 3 | 4 | import argparse 5 | import os 6 | import urllib.request 7 | 8 | 9 | def parse_args(): 10 | parser = argparse.ArgumentParser(description='download and place files.') 11 | parser.add_argument('--output_static_analysis_debug', type=str, 12 | default="debug/warnings_table.txt") 13 | parser.add_argument('--output_static_analysis_relwithdebinfo', type=str, 14 | default="rel_with_deb_info/warnings_table.txt") 15 | parser.add_argument('--output_runtime_debug', type=str, 16 | default="debug/results.txt") 17 | parser.add_argument('--output_runtime_relwithdebinfo', type=str, 18 | default="rel_with_deb_info/results.txt") 19 | parser.add_argument('--text_url', type=str, 20 | default="https://ci.appveyor.com/api/buildjobs/nrx951uoxtvm9eov/log", 21 | help='msvc text file') 22 | return parser.parse_args() 23 | 24 | 25 | def check_close_file(file_writing, file_being_written, no_timestamp): 26 | if no_timestamp == b"MSVC Debug Compiler Warnings End\r\n": 27 | file_writing = False 28 | file_being_written.close() 29 | if no_timestamp == b"MSVC RelWithDebInfo Compiler Warnings End\r\n": 30 | file_writing = False 31 | file_being_written.close() 32 | if no_timestamp == b"MSVC Debug Crashes End\r\n": 33 | file_writing = False 34 | file_being_written.close() 35 | if no_timestamp == b"MSVC RelWithDebInfo Crashes End\r\n": 36 | file_writing = False 37 | file_being_written.close() 38 | return (file_writing, file_being_written) 39 | 40 | 41 | def check_file_open(file_writing, file_being_written, no_timestamp, args): 42 | if no_timestamp == b"MSVC Debug Compiler Warnings Start\r\n": 43 | file_writing = True 44 | mkdir(args.output_static_analysis_debug) 45 | file_being_written = open(args.output_static_analysis_debug, 'w') 46 | if no_timestamp == b"MSVC RelWithDebInfo Compiler Warnings Start\r\n": 47 | file_writing = True 48 | mkdir(args.output_static_analysis_relwithdebinfo) 49 | file_being_written = open( 50 | args.output_static_analysis_relwithdebinfo, 'w') 51 | if no_timestamp == b"MSVC Debug Crashes Start\r\n": 52 | file_writing = True 53 | mkdir(args.output_runtime_debug) 54 | file_being_written = open(args.output_runtime_debug, 'w') 55 | if no_timestamp == b"MSVC RelWithDebInfo Crashes Start\r\n": 56 | file_writing = True 57 | mkdir(args.output_runtime_relwithdebinfo) 58 | file_being_written = open(args.output_runtime_relwithdebinfo, 'w') 59 | 60 | return (file_writing, file_being_written) 61 | 62 | 63 | def write_file(file_writing, file_being_written, no_timestamp, args): 64 | file_writing, file_being_written = check_close_file( 65 | file_writing, file_being_written, no_timestamp) 66 | if file_writing: 67 | file_being_written.write(no_timestamp.decode("utf-8")) 68 | file_writing, file_being_written = check_file_open( 69 | file_writing, file_being_written, no_timestamp, args) 70 | return (file_writing, file_being_written) 71 | 72 | 73 | def mkdir(filepath): 74 | os.makedirs(os.path.dirname(filepath), exist_ok=True) 75 | 76 | 77 | if __name__ == "__main__": 78 | args = parse_args() 79 | file_writing = False 80 | static_analysis_debug = 0 81 | static_analysis_relwithdebinfo = 0 82 | runtime_debug = 0 83 | runtime_relwithdebinfo = 0 84 | file_being_written = 0 85 | with urllib.request.urlopen(args.text_url) as msvc_text: 86 | for l in msvc_text: 87 | if len(l) < 11: 88 | print("file should have a timestamp like \"[00:01:35] \"") 89 | exit(1) 90 | no_timestamp = l[11:] 91 | file_writing, file_being_written = write_file( 92 | file_writing, file_being_written, no_timestamp, args) 93 | -------------------------------------------------------------------------------- /generate_results.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT_DIR=$(pwd) 4 | PATH=${PATH}:${ROOT_DIR} 5 | SRC_DIR=${ROOT_DIR}/src 6 | 7 | mkdir -p build 8 | cd build 9 | 10 | function my_time { 11 | echo -n "$1 " 12 | # BSD date doesn't provide sub second measurements 13 | before=$(python3 -c "import time; print(time.time())") 14 | $@ 15 | if [ "$?" -ne "0" ] 16 | then 17 | python3 -c "import time; print(str(time.time() - ${before}) + 's')" 18 | fi 19 | } 20 | 21 | mkdir -p clang-tidy 22 | cd clang-tidy 23 | export CXX=clang++ 24 | cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE ../.. > cmake.txt 25 | cp compile_commands.json ../.. 26 | clang-tidy --quiet -checks=*,-fuchsia-default-arguments,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-no-malloc,-hicpp-no-malloc,-modernize-use-trailing-return-type,-fuchsia-default-arguments-calls,-llvmlibc-*,-readability-identifier-length,-altera-struct-pack-align,-altera-unroll-loops ${SRC_DIR}/*.cpp 1> warnings.txt 27 | rm ../../compile_commands.json 28 | associate_warnings.py --cpp_dir=${SRC_DIR} 29 | cd .. 30 | 31 | mkdir -p cppcheck 32 | cd cppcheck 33 | cppcheck ${SRC_DIR}/*.cpp 1> cppcheck.txt 2> warnings.txt 34 | associate_warnings.py --cpp_dir=${SRC_DIR} 35 | cd .. 36 | 37 | mkdir -p gcc/debug 38 | cd gcc/debug 39 | 40 | function run_executable { 41 | $(timeout 1 ./${1} > intermediate_results/${1}_output.txt 2>&1) 42 | echo ${1} $? > intermediate_results/${1}_result.txt 43 | } 44 | export -f run_executable 45 | 46 | function run_executable_with_valgrind { 47 | $(timeout 5 valgrind --error-exitcode=1 ./${1} > intermediate_results/${1}_valgrind_output.txt 2>&1) 48 | echo ${1} $? > intermediate_results/${1}_valgrind_result.txt 49 | } 50 | export -f run_executable_with_valgrind 51 | 52 | function run_folder { 53 | with_valgrind=${1} 54 | declare -a executable_files 55 | executables_count=0 56 | for file in `ls -1` ; do 57 | if [ -x $file ] && [ -f $file ] ; then 58 | executable_files[executables_count]=$file 59 | let "executables_count++" 60 | fi 61 | done 62 | mkdir -p intermediate_results 63 | [[ "$with_valgrind" = true ]] && multiplier=2 || multiplier=1 64 | num_jobs=$(($executables_count*$multiplier)) 65 | for (( i=0; i<=$(( $executables_count -1 )); i++ )) 66 | do 67 | echo -ne "kicking off $(($i*$multiplier+1))/$num_jobs\r" 68 | sem -j+0 run_executable ${executable_files[$i]} 69 | if [ "$with_valgrind" = true ] ; then 70 | echo -ne "kicking off $(($i*$multiplier+2))/$num_jobs\r" 71 | sem -j+0 run_executable_with_valgrind ${executable_files[$i]} 72 | fi 73 | done 74 | echo -ne '\n' 75 | sem --wait 76 | rm -f runtime_results.txt 77 | if [ "$with_valgrind" = true ] ; then 78 | rm -f valgrind_results.txt 79 | fi 80 | for file in "${executable_files[@]}" ; do 81 | cat intermediate_results/${file}_result.txt >> runtime_results.txt 82 | if [ "$with_valgrind" = true ] ; then 83 | cat intermediate_results/${file}_valgrind_result.txt >> valgrind_results.txt 84 | fi 85 | done 86 | } 87 | 88 | echo "gcc debug" 89 | export CXX='g++' 90 | cmake ../../.. -DCMAKE_BUILD_TYPE=Debug > cmake.txt 91 | make -j $(nproc) 1> make.txt 2> warnings.txt 92 | associate_warnings.py --cpp_dir=${SRC_DIR} 93 | run_folder true 94 | 95 | cd .. 96 | mkdir -p rel_with_deb_info 97 | cd rel_with_deb_info 98 | echo "gcc rel with deb info" 99 | cmake ../../.. -DCMAKE_BUILD_TYPE=RelWithDebInfo > cmake.txt 100 | make -j $(nproc) 1> make.txt 2> warnings.txt 101 | associate_warnings.py --cpp_dir=${SRC_DIR} 102 | run_folder true 103 | 104 | cd ../.. 105 | mkdir -p clang/debug 106 | cd clang/debug 107 | export CXX=clang++ 108 | echo "clang debug" 109 | cmake ../../.. -DCMAKE_BUILD_TYPE=Debug > cmake.txt 110 | make -j $(nproc) 1> make.txt 2> warnings.txt 111 | associate_warnings.py --cpp_dir=${SRC_DIR} 112 | run_folder false 113 | 114 | cd .. 115 | mkdir -p rel_with_deb_info 116 | cd rel_with_deb_info 117 | echo "clang rel with deb info" 118 | cmake ../../.. -DCMAKE_BUILD_TYPE=RelWithDebInfo > cmake.txt 119 | make -j $(nproc) 1> make.txt 2> warnings.txt 120 | associate_warnings.py --cpp_dir=${SRC_DIR} 121 | run_folder false 122 | 123 | cd ../.. 124 | 125 | fsanitize_build() { 126 | mkdir -p $2/debug 127 | cd $2/debug 128 | if [ "$1" == "gcc" ]; then 129 | export CXX='g++' 130 | else 131 | export CXX=$1++ 132 | fi 133 | echo $1 $2 debug 134 | cmake ../../../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=$2 -fno-sanitize-recover=$2" > cmake.txt 135 | make -j $(nproc) 1> make.txt 2> warnings.txt 136 | associate_warnings.py --cpp_dir=${SRC_DIR} 137 | run_folder false 138 | 139 | cd .. 140 | mkdir -p rel_with_deb_info 141 | cd rel_with_deb_info 142 | echo $1 $2 rel with deb info 143 | cmake ../../../.. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_FLAGS="-fsanitize=$2 -fno-sanitize-recover=$2" > cmake.txt 144 | make -j $(nproc) 1> make.txt 2> warnings.txt 145 | associate_warnings.py --cpp_dir=${SRC_DIR} 146 | run_folder false 147 | cd ../.. 148 | } 149 | 150 | mkdir -p clang_fsanitize 151 | cd clang_fsanitize 152 | 153 | fsanitize_build clang address 154 | fsanitize_build clang undefined 155 | fsanitize_build clang address,undefined 156 | 157 | cd .. 158 | 159 | mkdir -p gcc_fsanitize 160 | cd gcc_fsanitize 161 | 162 | fsanitize_build gcc address 163 | fsanitize_build gcc leak 164 | fsanitize_build gcc undefined 165 | fsanitize_build gcc address,leak,undefined 166 | 167 | cd .. 168 | 169 | mkdir -p msvc 170 | cd msvc 171 | ../../download_msvc_files.py 172 | cd ../.. 173 | 174 | #print results 175 | echo 176 | echo 177 | echo VERSIONS 178 | echo 179 | echo linux kernel 180 | uname -a 181 | echo 182 | echo gcc 183 | gcc --version 184 | echo 185 | echo valgrind 186 | valgrind --version 187 | echo 188 | echo clang++ 189 | clang++ --version 190 | echo 191 | echo clang-tidy 192 | clang-tidy --version 193 | echo 194 | echo cppcheck 195 | cppcheck --version 196 | echo 197 | echo parallell 198 | parallel --version 199 | echo 200 | echo bash 201 | bash --version 202 | echo 203 | echo python3 204 | python3 --version 205 | 206 | echo 207 | 208 | export LC_CTYPE=C.UTF-8 209 | print_results.py 210 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /print_results.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding=utf-8 3 | 4 | import csv 5 | import os 6 | from collections import defaultdict 7 | from enum import IntEnum 8 | 9 | cool_x = "❌" 10 | cool_check = "✔️" 11 | 12 | ignore_targets = [ 13 | 'no_undefined_behavior', 14 | 'reading_uninitialized_value_lib'] 15 | 16 | 17 | class DetectionType(IntEnum): 18 | COMPILER_WARNING = 1 19 | STANDALONE_STATIC_ANALYSIS = 2 20 | RUNTIME_CRASH = 3 21 | EXTRA_DYNAMIC_ANALYSIS = 4 22 | 23 | 24 | def print_debug_release_legend(): 25 | print("Debug (unoptimized) / RelWithDebInfo (optimized)\n") 26 | 27 | 28 | def read_static_analysis(): 29 | results = {} 30 | 31 | for root, subdirs, files in os.walk('.'): 32 | for f in files: 33 | if f.find("warnings_table.txt") != -1: 34 | filename = root + "/" + f 35 | results[filename] = csv.reader( 36 | open(root + "/" + f), delimiter=' ') 37 | 38 | return results 39 | 40 | 41 | def process_static_analysis_results(results): 42 | output_table = defaultdict(lambda: defaultdict(lambda: defaultdict(str))) 43 | 44 | for filename, csv in results.items(): 45 | tool = "" 46 | if "clang" in filename: 47 | if "tidy" in filename: 48 | tool = "clang-tidy" 49 | elif "/clang/": 50 | tool = "clang" 51 | else: 52 | # skip dynamic analysis warnings 53 | continue 54 | elif "gcc" in filename: 55 | tool = "gcc" 56 | elif "cppcheck" in filename: 57 | tool = "cppcheck" 58 | elif "msvc" in filename: 59 | tool = "msvc" 60 | else: 61 | print("couldn't find tool for", filename) 62 | exit(1) 63 | 64 | debug_mode = -1 65 | if "debug" in filename: 66 | debug_mode = 1 67 | if "rel_with_deb_info" in filename: 68 | debug_mode = 0 69 | 70 | for row in csv: 71 | if row[0] in ignore_targets: 72 | # Allow cppcheck to be correct one file over 73 | if ("cppcheck" in filename and 74 | row[0] == "reading_uninitialized_value_lib" and 75 | row[1] == "ctuuninitvar"): 76 | continue 77 | # Consider warnings in known good files an internal error 78 | if len(row) > 0 and row[1] != "": 79 | print("static analysis is broken in", filename, row) 80 | exit(1) 81 | continue 82 | if len(row) == 2: 83 | result = row[1] 84 | elif len(row) > 2: 85 | print("unknown data:", filename, row) 86 | exit(1) 87 | else: 88 | result = "" 89 | test_name = row[0].replace("_", " ") 90 | # Clang warnings are different with dynamic analysis 91 | if len(output_table[tool][test_name][debug_mode]) == 0 or ( 92 | output_table[tool][test_name][debug_mode] == "1" and len(result) > 0): 93 | output_table[tool][test_name][debug_mode] = result 94 | 95 | return output_table 96 | 97 | 98 | def print_compiler_warnings(output_table): 99 | print("### 1.1.Compiler Warnings") 100 | print("Compiler | Undefined Behavior Type | Warning | Warning Opt | Name") 101 | print("--- | --- | --- | --- | ---") 102 | for compiler, rest_0 in sorted(output_table.items()): 103 | for test, rest_1 in sorted(rest_0.items()): 104 | rest_1_dict = dict(rest_1) 105 | if -1 in rest_1_dict: 106 | continue 107 | if 0 not in rest_1_dict: 108 | print('error 0 not in rest_1_dict', rest_1_dict) 109 | warning_opt = cool_check if len(rest_1_dict[0]) > 0 else cool_x 110 | if 1 not in rest_1_dict: 111 | print('error 1 not in rest_1_dict', rest_1_dict) 112 | warning_unopt = cool_check if len(rest_1_dict[1]) > 0 else cool_x 113 | warning_name = "" 114 | if len(rest_1_dict[0]) > 0: 115 | warning_name = rest_1_dict[0] 116 | elif len(rest_1_dict[1]) > 0: 117 | warning_name = rest_1_dict[1] 118 | else: 119 | warning_name = "n/a" 120 | print(compiler, "|", test, "|", warning_unopt, 121 | "|", warning_opt, "|", warning_name) 122 | 123 | 124 | def print_tool_static_analysis(output_table): 125 | print("### 1.2.Static Analyzers") 126 | print("Tool | Undefined Behavior Type | Warning | Name") 127 | print("--- | --- | --- | ---") 128 | for tool, rest_0 in sorted(output_table.items()): 129 | for test, rest_1 in sorted(rest_0.items()): 130 | if -1 not in dict(rest_1): 131 | continue 132 | warning = rest_1[-1] 133 | result = cool_check if len(warning) > 0 else cool_x 134 | warning_name = "" 135 | if len(warning) > 0 and warning != "1": 136 | warning_name = warning 137 | else: 138 | warning_name = "n/a" 139 | print(tool, "|", test, "|", result, "|", warning_name) 140 | 141 | 142 | def print_static_analysis_summary(output_table): 143 | print("### 1.3.Static Analysis Summary") 144 | print_debug_release_legend() 145 | summary_table = defaultdict( 146 | lambda: defaultdict( 147 | lambda: defaultdict( 148 | lambda: defaultdict(bool)))) 149 | tool_line = "Undefined Behavior Type" 150 | tool_table_line = "---" 151 | tools = [] 152 | for tool, rest_0 in sorted(output_table.items()): 153 | tools.append(tool) 154 | tool_line += " | " + tool 155 | tool_table_line += " | ---" 156 | for test, rest_1 in sorted(rest_0.items()): 157 | warning_result = -1 158 | for optimization, warning in sorted(rest_1.items()): 159 | summary_table[test][tool][optimization] = len(warning) > 0 160 | 161 | print(tool_line) 162 | print(tool_table_line) 163 | 164 | for test, rest_0 in sorted(summary_table.items()): 165 | output_line = test 166 | tool_index = 0 167 | for tool, rest_1 in sorted(rest_0.items()): 168 | while tool != tools[tool_index]: 169 | tool_index += 1 170 | output_line += " | n/a" 171 | tool_index += 1 172 | output_line += " | " 173 | if -1 in rest_1: 174 | output_line += detection_to_str(rest_1[-1]) 175 | else: 176 | assert(0 in rest_1) 177 | assert(1 in rest_1) 178 | output_line += detections_to_str(rest_1[1], rest_1[0]) 179 | while tool_index < len(tools): 180 | tool_index += 1 181 | output_line += " | n/a" 182 | print(output_line) 183 | 184 | 185 | def read_runtime_results(): 186 | results = {} 187 | 188 | for root, subdirs, files in os.walk('.'): 189 | for f in files: 190 | if f.find("results.txt") != -1: 191 | filename = root + "/" + f 192 | results[filename] = csv.reader( 193 | open(root + "/" + f), delimiter=' ') 194 | 195 | return results 196 | 197 | 198 | def process_runtime_results(runtime_results): 199 | output_table = defaultdict(lambda: defaultdict( 200 | lambda: defaultdict(lambda: defaultdict(str)))) 201 | 202 | for filename, csv in runtime_results.items(): 203 | if "valgrind" in filename: 204 | analyzer = "valgrind" 205 | elif "sanitize" in filename: 206 | analyzer = "" 207 | known_analyzers = ['address', 'leak', 'memory', 'undefined'] 208 | for known_analyzer in known_analyzers: 209 | if known_analyzer in filename: 210 | if len(analyzer) > 0: 211 | analyzer += ',' 212 | analyzer += known_analyzer 213 | else: 214 | analyzer = "" 215 | if "gcc" in filename: 216 | compiler = "gcc" 217 | elif "msvc" in filename: 218 | compiler = "msvc" 219 | else: 220 | compiler = "clang" 221 | if filename.find("debug") != -1: 222 | debug_mode = 1 223 | else: 224 | debug_mode = 0 225 | for row in csv: 226 | if row[0] in ignore_targets: 227 | if row[1] != "0": 228 | print(filename, "broken", row) 229 | exit(1) 230 | continue 231 | output_table[compiler][analyzer][row[0].replace( 232 | "_", " ")][str(debug_mode)] = int(row[1]) 233 | return output_table 234 | 235 | 236 | def detection_to_str(detection): 237 | if detection: 238 | return cool_check 239 | else: 240 | return cool_x 241 | 242 | 243 | def detections_to_str(d, r): 244 | if d and r: 245 | return cool_check 246 | elif not d and not r: 247 | return cool_x 248 | else: 249 | left = detection_to_str(d) 250 | right = detection_to_str(r) 251 | return left + '/' + right 252 | 253 | 254 | def return_codes_to_str(return_code_d, return_code_r): 255 | return detections_to_str(return_code_d != 0, return_code_r != 0) 256 | 257 | 258 | def print_runtime_crashes(output_table): 259 | print("## 2.Runtime Crashes") 260 | print("### 2.1.Runtime Crashes Return Codes") 261 | print("Compiler | Undefined Behavior Type | Debug | RelWithDebInfo") 262 | print("--- | --- | --- | ---") 263 | no_tool_test_table = defaultdict( 264 | lambda: defaultdict(lambda: defaultdict(str))) 265 | compilers = [] 266 | for compiler, rest_0 in sorted(output_table.items()): 267 | for tool, rest_1 in sorted(rest_0.items()): 268 | if tool != "": 269 | continue 270 | compilers.append(compiler) 271 | for test, rest_2 in sorted(rest_1.items()): 272 | no_tool_test_table[test][compiler]["1"] = rest_2["1"] 273 | no_tool_test_table[test][compiler]["0"] = rest_2["0"] 274 | print(compiler + " | " + test + " | " + 275 | str(rest_2["1"]) + " | " + str(rest_2["0"])) 276 | 277 | print("") 278 | print("### 2.2.Runtime Crashes Summary") 279 | print_debug_release_legend() 280 | tool_print_line = "Undefined Behavior" 281 | tool_delim_print_line = "---" 282 | tool_print_line_r = "" 283 | for compiler in compilers: 284 | tool_print_line += " | " + compiler 285 | tool_delim_print_line += " | ---" 286 | print(tool_print_line) 287 | print(tool_delim_print_line) 288 | for test, rest_0 in sorted(no_tool_test_table.items()): 289 | line = test 290 | line_r = "" 291 | compiler_index = 0 292 | for compiler, rest_1 in sorted(rest_0.items()): 293 | while compiler != compilers[compiler_index]: 294 | compiler_index += 1 295 | line += " | n/a" 296 | line_r += " | n/a" 297 | compiler_index += 1 298 | line += ' | ' 299 | line += return_codes_to_str(rest_1["1"], rest_1["0"]) 300 | while compiler_index < len(compilers): 301 | compiler_index += 1 302 | line += " | n/a" 303 | print(line) 304 | 305 | 306 | def print_dynamic_analysis(output_table): 307 | print("## 3.Extra Dynamic Analysis") 308 | print("### 3.1.Extra Dynamic Analysis Return Codes") 309 | print("Compiler | Tool | Undefined Behavior Type | Debug | RelWithDebInfo") 310 | print("--- | --- | --- | --- | ---") 311 | tool_test_table = defaultdict(lambda: defaultdict( 312 | lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(str))))) 313 | clang_tools = [] 314 | gcc_tools = [] 315 | for compiler, rest_0 in sorted(output_table.items()): 316 | for tool, rest_1 in sorted(rest_0.items()): 317 | if tool != "": 318 | if compiler == "clang": 319 | clang_tools.append(tool) 320 | else: 321 | gcc_tools.append(tool) 322 | for test, rest_2 in sorted(rest_1.items()): 323 | tool_test_table[test][compiler][tool]["1"] = rest_2["1"] 324 | tool_test_table[test][compiler][tool]["0"] = rest_2["0"] 325 | print(compiler + " | " + tool + " | " + test + " | " + 326 | str(rest_2["1"]) + " | " + str(rest_2["0"])) 327 | 328 | def print_extra_dynamic_analysis_by_compiler( 329 | target_compiler, header_str, tools): 330 | print("") 331 | maybe_valgrind = "" 332 | print( 333 | "### " + 334 | header_str + 335 | "Extra Dynamic Analysis Summary " + 336 | target_compiler.capitalize()) 337 | print_debug_release_legend() 338 | dynamic_analysis_summary_row = "--- |" * len(tools) + " ---" 339 | print("Undefined Behavior Type" + 340 | ''.join([' | ' + str(x) for x in tools])) 341 | print(dynamic_analysis_summary_row) 342 | for test, rest_0 in sorted(tool_test_table.items()): 343 | line = test 344 | for tool in tools: 345 | line += " | " 346 | if target_compiler in rest_0 and tool in rest_0[target_compiler]: 347 | line += return_codes_to_str( 348 | rest_0[target_compiler][tool]["1"], 349 | rest_0[target_compiler][tool]["0"]) 350 | else: 351 | line += "n/a" 352 | print(line) 353 | 354 | print_extra_dynamic_analysis_by_compiler("clang", "3.2.1.", clang_tools) 355 | print_extra_dynamic_analysis_by_compiler("gcc", "3.2.2.", gcc_tools) 356 | 357 | 358 | def print_runtime_results(): 359 | runtime_results = read_runtime_results() 360 | output_table = process_runtime_results(runtime_results) 361 | print_runtime_crashes(output_table) 362 | print("") 363 | print("") 364 | print_dynamic_analysis(output_table) 365 | return output_table 366 | 367 | 368 | def print_static_analysis_results(): 369 | static_analysis_results = read_static_analysis() 370 | output_table = process_static_analysis_results(static_analysis_results) 371 | print("## 1.Static Analysis") 372 | print_compiler_warnings(output_table) 373 | print("") 374 | print_tool_static_analysis(output_table) 375 | print("") 376 | print_static_analysis_summary(output_table) 377 | return output_table 378 | 379 | 380 | def print_overall_results(static_analysis, runtime_analysis): 381 | print("### 4.Overall Summary") 382 | print("Undefined Behavior Type | Compiler Warning | Standalone Static Analysis | Runtime Crash | Extra Dynamic Analsyis") 383 | print("--- | --- | --- | --- | ---") 384 | table = defaultdict(lambda: defaultdict(bool)) 385 | 386 | for tool, rest_0 in static_analysis.items(): 387 | for test, rest_1 in rest_0.items(): 388 | for optimization, result in rest_1.items(): 389 | if tool == "clang" or tool == "gcc" or tool == "msvc": 390 | detection_type = DetectionType.COMPILER_WARNING 391 | else: 392 | detection_type = DetectionType.STANDALONE_STATIC_ANALYSIS 393 | table[test][detection_type] = table[test][detection_type] or len( 394 | result) > 0 395 | 396 | for compiler, rest_0 in dynamic_analysis.items(): 397 | for tool, rest_1 in rest_0.items(): 398 | for test, rest_2 in rest_1.items(): 399 | for optimization, result in rest_2.items(): 400 | if len(tool) == 0: 401 | detection_type = DetectionType.RUNTIME_CRASH 402 | else: 403 | detection_type = DetectionType.EXTRA_DYNAMIC_ANALYSIS 404 | table[test][detection_type] = 0 != result or table[test][detection_type] 405 | 406 | for test, rest_0 in sorted(table.items()): 407 | line = test 408 | for detection_type in DetectionType: 409 | line += ' | ' 410 | if detection_type in rest_0: 411 | line += detection_to_str(rest_0[detection_type]) 412 | else: 413 | line += 'n/a' 414 | print(line) 415 | 416 | 417 | if __name__ == "__main__": 418 | static_analysis = print_static_analysis_results() 419 | print("") 420 | print("") 421 | dynamic_analysis = print_runtime_results() 422 | print("") 423 | print("") 424 | print_overall_results(static_analysis, dynamic_analysis) 425 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Undefined Behavior Study 2 | A study of undefined behavior on various platforms, compilers, and tools. 3 | Some examples were inspired by https://www.nayuki.io/page/undefined-behavior-in-c-and-cplusplus-programs. There are some highlights in the video below. 4 | 5 | [![Explanation Video](https://user-images.githubusercontent.com/10720055/181924542-7395c433-4256-4e76-81c1-1c610550c086.jpg)](https://www.youtube.com/watch?v=EkZLN_D1BwU) 6 | 7 | 8 | ## Automated Results 9 | 10 | Linux 11 | [![Build Status](https://app.travis-ci.com/geoffviola/undefined_behavior_study.svg?token=n7xWtQG4q8zpsz5mSNsp&branch=master)](https://app.travis-ci.com/geoffviola/undefined_behavior_study) 12 | 13 | Windows 14 | [![Build status](https://ci.appveyor.com/api/projects/status/65bhemledj07s8jt?svg=true)](https://ci.appveyor.com/project/geoffviola/undefined-behavior-study) 15 | 16 | ## 1.Static Analysis 17 | ### 1.1.Compiler Warnings 18 | Compiler | Undefined Behavior Type | Warning | Warning Opt | Name 19 | --- | --- | --- | --- | --- 20 | clang | access after realloc | ❌ | ❌ | n/a 21 | clang | array out of bounds | ❌ | ❌ | n/a 22 | clang | automatic variable over stack | ❌ | ❌ | n/a 23 | clang | bad alignment | ❌ | ❌ | n/a 24 | clang | bad identifier name | ❌ | ❌ | n/a 25 | clang | delete incomplete type | ✔️ | ✔️ | -Wdelete-incomplete 26 | clang | dereferencing nullptr | ❌ | ❌ | n/a 27 | clang | divide by zero | ✔️ | ✔️ | -Wdivision-by-zero 28 | clang | initialize std string with nullptr | ❌ | ❌ | n/a 29 | clang | large double to int | ❌ | ❌ | n/a 30 | clang | malloc cast pod struct | ❌ | ❌ | n/a 31 | clang | mutate const value | ❌ | ❌ | n/a 32 | clang | non trivial destructor and global | ❌ | ❌ | n/a 33 | clang | odr violation function | ❌ | ❌ | n/a 34 | clang | odr violation function lib | ❌ | ❌ | n/a 35 | clang | odr violation struct ret | ❌ | ❌ | n/a 36 | clang | odr violation struct ret lib | ❌ | ❌ | n/a 37 | clang | operator star on empty optional | ❌ | ❌ | n/a 38 | clang | out of bounds pointer | ❌ | ❌ | n/a 39 | clang | preincrement plus postincrement | ✔️ | ✔️ | -Wunsequenced 40 | clang | preincrement plus value | ✔️ | ✔️ | -Wunsequenced 41 | clang | read from old type | ❌ | ❌ | n/a 42 | clang | reading uninitialized value add | ✔️ | ✔️ | -Wuninitialized 43 | clang | reading uninitialized value cout | ✔️ | ✔️ | -Wuninitialized 44 | clang | reading uninitialized value func arg | ❌ | ❌ | n/a 45 | clang | reading uninitialized value if | ✔️ | ✔️ | -Wuninitialized 46 | clang | reading uninitialized value lib call cref | ✔️ | ✔️ | -Wuninitialized-const-reference 47 | clang | reading uninitialized value partial | ❌ | ❌ | n/a 48 | clang | reading uninitialized value printf | ✔️ | ✔️ | -Wuninitialized 49 | clang | reading uninitialized value return | ✔️ | ✔️ | -Wreturn-type 50 | clang | reference out of scope | ✔️ | ✔️ | -Wreturn-stack-address 51 | clang | reinterpret cast bad size | ❌ | ❌ | n/a 52 | clang | reinterpret cast float to int32 | ❌ | ❌ | n/a 53 | clang | reinterpret cast int32 to float | ❌ | ❌ | n/a 54 | clang | reinterpret cast int32 to uint32 | ❌ | ❌ | n/a 55 | clang | reinterpret cast uint32 to int32 | ❌ | ❌ | n/a 56 | clang | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | n/a 57 | clang | shifting more than width | ✔️ | ✔️ | -Wshift-count-overflow 58 | clang | signed integer overflow | ❌ | ❌ | n/a 59 | clang | sort comp reflexive | ❌ | ❌ | n/a 60 | clang | stack overflow | ✔️ | ✔️ | -Winfinite-recursion 61 | clang | std vector reserve set read | ❌ | ❌ | n/a 62 | clang | strptime mktime unitialized | ❌ | ❌ | n/a 63 | clang | virtual call in constructor | ✔️ | ✔️ | -Wcall-to-pure-virtual-from-ctor-dtor 64 | clang | virtual call in constructor helper | ❌ | ❌ | n/a 65 | clang | virtual call in constructor lib | ❌ | ❌ | n/a 66 | clang | virtual call in constructor link | ❌ | ❌ | n/a 67 | clang | virtual call in destructor | ✔️ | ✔️ | -Wcall-to-pure-virtual-from-ctor-dtor 68 | clang | virtual call in destructor helper | ❌ | ❌ | n/a 69 | clang | virtual call in destructor lib | ❌ | ❌ | n/a 70 | clang | virtual call in destructor link | ❌ | ❌ | n/a 71 | gcc | access after realloc | ✔️ | ✔️ | -Wuse-after-free 72 | gcc | array out of bounds | ❌ | ✔️ | -Warray-bounds= 73 | gcc | automatic variable over stack | ❌ | ❌ | n/a 74 | gcc | bad alignment | ❌ | ❌ | n/a 75 | gcc | bad identifier name | ❌ | ❌ | n/a 76 | gcc | delete incomplete type | ✔️ | ✔️ | -Wdelete-incomplete 77 | gcc | dereferencing nullptr | ❌ | ❌ | n/a 78 | gcc | divide by zero | ✔️ | ✔️ | -Wdiv-by-zero 79 | gcc | initialize std string with nullptr | ❌ | ❌ | n/a 80 | gcc | large double to int | ❌ | ❌ | n/a 81 | gcc | malloc cast pod struct | ❌ | ❌ | n/a 82 | gcc | mutate const value | ❌ | ❌ | n/a 83 | gcc | non trivial destructor and global | ❌ | ❌ | n/a 84 | gcc | odr violation function | ❌ | ❌ | n/a 85 | gcc | odr violation function lib | ❌ | ❌ | n/a 86 | gcc | odr violation struct ret | ❌ | ❌ | n/a 87 | gcc | odr violation struct ret lib | ❌ | ❌ | n/a 88 | gcc | operator star on empty optional | ❌ | ❌ | n/a 89 | gcc | out of bounds pointer | ❌ | ✔️ | -Warray-bounds= 90 | gcc | preincrement plus postincrement | ✔️ | ✔️ | -Wsequence-point 91 | gcc | preincrement plus value | ✔️ | ✔️ | -Wsequence-point 92 | gcc | read from old type | ❌ | ❌ | n/a 93 | gcc | reading uninitialized value add | ✔️ | ✔️ | -Wuninitialized 94 | gcc | reading uninitialized value cout | ✔️ | ✔️ | -Wuninitialized 95 | gcc | reading uninitialized value func arg | ❌ | ✔️ | -Wuninitialized 96 | gcc | reading uninitialized value if | ✔️ | ✔️ | -Wuninitialized 97 | gcc | reading uninitialized value lib call cref | ✔️ | ✔️ | -Wmaybe-uninitialized 98 | gcc | reading uninitialized value partial | ❌ | ❌ | n/a 99 | gcc | reading uninitialized value printf | ✔️ | ✔️ | -Wuninitialized 100 | gcc | reading uninitialized value return | ✔️ | ✔️ | -Wreturn-type 101 | gcc | reference out of scope | ✔️ | ✔️ | -Wreturn-local-addr 102 | gcc | reinterpret cast bad size | ✔️ | ✔️ | -Wuninitialized,-Warray-bounds= 103 | gcc | reinterpret cast float to int32 | ❌ | ✔️ | -Wstrict-aliasing,-Wuninitialized 104 | gcc | reinterpret cast int32 to float | ❌ | ✔️ | -Wstrict-aliasing,-Wuninitialized 105 | gcc | reinterpret cast int32 to uint32 | ❌ | ❌ | n/a 106 | gcc | reinterpret cast uint32 to int32 | ❌ | ❌ | n/a 107 | gcc | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | n/a 108 | gcc | shifting more than width | ✔️ | ✔️ | -Wshift-count-overflow 109 | gcc | signed integer overflow | ❌ | ❌ | n/a 110 | gcc | sort comp reflexive | ❌ | ❌ | n/a 111 | gcc | stack overflow | ✔️ | ✔️ | -Winfinite-recursion 112 | gcc | std vector reserve set read | ❌ | ❌ | n/a 113 | gcc | strptime mktime unitialized | ❌ | ❌ | n/a 114 | gcc | virtual call in constructor | ❌ | ❌ | n/a 115 | gcc | virtual call in constructor helper | ❌ | ❌ | n/a 116 | gcc | virtual call in constructor lib | ❌ | ❌ | n/a 117 | gcc | virtual call in constructor link | ❌ | ❌ | n/a 118 | gcc | virtual call in destructor | ❌ | ❌ | n/a 119 | gcc | virtual call in destructor helper | ❌ | ❌ | n/a 120 | gcc | virtual call in destructor lib | ❌ | ❌ | n/a 121 | gcc | virtual call in destructor link | ❌ | ❌ | n/a 122 | msvc | access after realloc | ❌ | ❌ | n/a 123 | msvc | array out of bounds | ❌ | ❌ | n/a 124 | msvc | automatic variable over stack | ❌ | ❌ | n/a 125 | msvc | bad alignment | ❌ | ❌ | n/a 126 | msvc | bad identifier name | ❌ | ❌ | n/a 127 | msvc | delete incomplete type | ✔️ | ✔️ | 4150 128 | msvc | dereferencing nullptr | ❌ | ❌ | n/a 129 | msvc | divide by zero | ✔️ | ✔️ | 4723 130 | msvc | initialize std string with nullptr | ❌ | ❌ | n/a 131 | msvc | large double to int | ❌ | ❌ | n/a 132 | msvc | malloc cast pod struct | ❌ | ❌ | n/a 133 | msvc | mutate const value | ❌ | ❌ | n/a 134 | msvc | non trivial destructor and global | ❌ | ❌ | n/a 135 | msvc | odr violation function | ❌ | ❌ | n/a 136 | msvc | odr violation function lib | ❌ | ❌ | n/a 137 | msvc | odr violation struct ret | ❌ | ❌ | n/a 138 | msvc | odr violation struct ret lib | ❌ | ❌ | n/a 139 | msvc | operator star on empty optional | ❌ | ❌ | n/a 140 | msvc | out of bounds pointer | ❌ | ❌ | n/a 141 | msvc | preincrement plus postincrement | ❌ | ❌ | n/a 142 | msvc | preincrement plus value | ❌ | ❌ | n/a 143 | msvc | read from old type | ❌ | ❌ | n/a 144 | msvc | reading uninitialized value add | ✔️ | ✔️ | 4700 145 | msvc | reading uninitialized value cout | ✔️ | ✔️ | 4700 146 | msvc | reading uninitialized value func arg | ❌ | ❌ | n/a 147 | msvc | reading uninitialized value if | ✔️ | ✔️ | 4700 148 | msvc | reading uninitialized value lib call cref | ❌ | ❌ | n/a 149 | msvc | reading uninitialized value partial | ❌ | ❌ | n/a 150 | msvc | reading uninitialized value printf | ✔️ | ✔️ | 4700 151 | msvc | reference out of scope | ✔️ | ✔️ | 4172 152 | msvc | reinterpret cast bad size | ❌ | ❌ | n/a 153 | msvc | reinterpret cast float to int32 | ❌ | ❌ | n/a 154 | msvc | reinterpret cast int32 to float | ❌ | ❌ | n/a 155 | msvc | reinterpret cast int32 to uint32 | ❌ | ❌ | n/a 156 | msvc | reinterpret cast uint32 to int32 | ❌ | ❌ | n/a 157 | msvc | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | n/a 158 | msvc | shifting more than width | ✔️ | ✔️ | 4293 159 | msvc | signed integer overflow | ❌ | ❌ | n/a 160 | msvc | sort comp reflexive | ❌ | ❌ | n/a 161 | msvc | stack overflow | ✔️ | ✔️ | 4717 162 | msvc | std vector reserve set read | ❌ | ❌ | n/a 163 | msvc | virtual call in constructor | ❌ | ❌ | n/a 164 | msvc | virtual call in constructor helper | ❌ | ❌ | n/a 165 | msvc | virtual call in constructor lib | ❌ | ❌ | n/a 166 | msvc | virtual call in constructor link | ❌ | ❌ | n/a 167 | msvc | virtual call in destructor | ❌ | ❌ | n/a 168 | msvc | virtual call in destructor helper | ❌ | ❌ | n/a 169 | msvc | virtual call in destructor lib | ❌ | ❌ | n/a 170 | msvc | virtual call in destructor link | ❌ | ❌ | n/a 171 | 172 | ### 1.2.Static Analyzers 173 | Tool | Undefined Behavior Type | Warning | Name 174 | --- | --- | --- | --- 175 | clang-tidy | access after realloc | ✔️ | clang-analyzer-unix.Malloc 176 | clang-tidy | array out of bounds | ✔️ | cppcoreguidelines-pro-bounds-constant-array-index 177 | clang-tidy | automatic variable over stack | ❌ | n/a 178 | clang-tidy | bad alignment | ❌ | n/a 179 | clang-tidy | bad identifier name | ✔️ | bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp 180 | clang-tidy | delete incomplete type | ✔️ | clang-diagnostic-delete-incomplete 181 | clang-tidy | dereferencing nullptr | ✔️ | clang-analyzer-core.NullDereference 182 | clang-tidy | divide by zero | ✔️ | clang-analyzer-core.DivideZero,clang-diagnostic-division-by-zero 183 | clang-tidy | initialize std string with nullptr | ❌ | n/a 184 | clang-tidy | large double to int | ❌ | n/a 185 | clang-tidy | malloc cast pod struct | ❌ | n/a 186 | clang-tidy | mutate const value | ✔️ | cppcoreguidelines-pro-type-const-cast 187 | clang-tidy | non trivial destructor and global | ❌ | n/a 188 | clang-tidy | odr violation function | ✔️ | misc-include-cleaner 189 | clang-tidy | odr violation function lib | ❌ | n/a 190 | clang-tidy | odr violation struct ret | ✔️ | misc-include-cleaner 191 | clang-tidy | odr violation struct ret lib | ❌ | n/a 192 | clang-tidy | operator star on empty optional | ✔️ | bugprone-unchecked-optional-access 193 | clang-tidy | out of bounds pointer | ❌ | n/a 194 | clang-tidy | preincrement plus postincrement | ✔️ | clang-diagnostic-unsequenced 195 | clang-tidy | preincrement plus value | ✔️ | clang-diagnostic-unsequenced 196 | clang-tidy | read from old type | ❌ | n/a 197 | clang-tidy | reading uninitialized value add | ✔️ | cppcoreguidelines-init-variables,clang-diagnostic-uninitialized,clang-analyzer-core.UndefinedBinaryOperatorResult 198 | clang-tidy | reading uninitialized value cout | ✔️ | cppcoreguidelines-init-variables,clang-analyzer-core.CallAndMessage,clang-diagnostic-uninitialized 199 | clang-tidy | reading uninitialized value func arg | ✔️ | cppcoreguidelines-init-variables,clang-analyzer-core.CallAndMessage 200 | clang-tidy | reading uninitialized value if | ✔️ | cppcoreguidelines-init-variables,clang-analyzer-core.uninitialized.Branch,clang-diagnostic-uninitialized 201 | clang-tidy | reading uninitialized value lib call cref | ✔️ | cppcoreguidelines-init-variables,clang-diagnostic-uninitialized-const-reference 202 | clang-tidy | reading uninitialized value partial | ✔️ | cppcoreguidelines-init-variables,clang-analyzer-core.CallAndMessage 203 | clang-tidy | reading uninitialized value printf | ✔️ | cppcoreguidelines-init-variables,clang-analyzer-core.CallAndMessage,clang-diagnostic-uninitialized 204 | clang-tidy | reading uninitialized value return | ✔️ | clang-diagnostic-return-type 205 | clang-tidy | reference out of scope | ✔️ | clang-analyzer-core.StackAddressEscape,clang-diagnostic-return-stack-address 206 | clang-tidy | reinterpret cast bad size | ❌ | n/a 207 | clang-tidy | reinterpret cast float to int32 | ❌ | n/a 208 | clang-tidy | reinterpret cast int32 to float | ❌ | n/a 209 | clang-tidy | reinterpret cast int32 to uint32 | ❌ | n/a 210 | clang-tidy | reinterpret cast uint32 to int32 | ❌ | n/a 211 | clang-tidy | reinterpret cast unaligned bytes to uint32 | ❌ | n/a 212 | clang-tidy | shifting more than width | ✔️ | clang-analyzer-core.BitwiseShift,clang-diagnostic-shift-count-overflow,hicpp-signed-bitwise 213 | clang-tidy | signed integer overflow | ❌ | n/a 214 | clang-tidy | sort comp reflexive | ❌ | n/a 215 | clang-tidy | stack overflow | ✔️ | misc-no-recursion,clang-diagnostic-infinite-recursion 216 | clang-tidy | std vector reserve set read | ❌ | n/a 217 | clang-tidy | strptime mktime unitialized | ✔️ | cppcoreguidelines-pro-type-member-init,hicpp-member-init 218 | clang-tidy | virtual call in constructor | ✔️ | clang-analyzer-cplusplus.PureVirtualCall,clang-diagnostic-call-to-pure-virtual-from-ctor-dtor,misc-const-correctness 219 | clang-tidy | virtual call in constructor helper | ✔️ | clang-analyzer-cplusplus.PureVirtualCall,misc-const-correctness 220 | clang-tidy | virtual call in constructor lib | ✔️ | clang-analyzer-cplusplus.PureVirtualCall 221 | clang-tidy | virtual call in constructor link | ❌ | n/a 222 | clang-tidy | virtual call in destructor | ✔️ | clang-analyzer-cplusplus.PureVirtualCall,clang-diagnostic-call-to-pure-virtual-from-ctor-dtor 223 | clang-tidy | virtual call in destructor helper | ✔️ | clang-analyzer-cplusplus.PureVirtualCall 224 | clang-tidy | virtual call in destructor lib | ✔️ | clang-analyzer-cplusplus.PureVirtualCall 225 | clang-tidy | virtual call in destructor link | ❌ | n/a 226 | cppcheck | access after realloc | ❌ | n/a 227 | cppcheck | array out of bounds | ✔️ | containerOutOfBounds,containerOutOfBoundsIndexExpression 228 | cppcheck | automatic variable over stack | ❌ | n/a 229 | cppcheck | bad alignment | ❌ | n/a 230 | cppcheck | bad identifier name | ❌ | n/a 231 | cppcheck | delete incomplete type | ❌ | n/a 232 | cppcheck | dereferencing nullptr | ✔️ | nullPointer 233 | cppcheck | divide by zero | ✔️ | zerodiv 234 | cppcheck | initialize std string with nullptr | ✔️ | nullPointer 235 | cppcheck | large double to int | ❌ | n/a 236 | cppcheck | malloc cast pod struct | ❌ | n/a 237 | cppcheck | mutate const value | ❌ | n/a 238 | cppcheck | non trivial destructor and global | ❌ | n/a 239 | cppcheck | odr violation function | ❌ | n/a 240 | cppcheck | odr violation function lib | ❌ | n/a 241 | cppcheck | odr violation struct ret | ✔️ | ctuOneDefinitionRuleViolation 242 | cppcheck | odr violation struct ret lib | ❌ | n/a 243 | cppcheck | operator star on empty optional | ❌ | n/a 244 | cppcheck | out of bounds pointer | ❌ | n/a 245 | cppcheck | preincrement plus postincrement | ❌ | n/a 246 | cppcheck | preincrement plus value | ❌ | n/a 247 | cppcheck | read from old type | ❌ | n/a 248 | cppcheck | reading uninitialized value add | ✔️ | uninitvar 249 | cppcheck | reading uninitialized value cout | ✔️ | uninitvar 250 | cppcheck | reading uninitialized value func arg | ❌ | n/a 251 | cppcheck | reading uninitialized value if | ✔️ | uninitvar 252 | cppcheck | reading uninitialized value lib call cref | ✔️ | uninitvar 253 | cppcheck | reading uninitialized value partial | ✔️ | uninitvar 254 | cppcheck | reading uninitialized value printf | ✔️ | uninitvar 255 | cppcheck | reading uninitialized value return | ✔️ | missingReturn 256 | cppcheck | reference out of scope | ✔️ | returnReference 257 | cppcheck | reinterpret cast bad size | ❌ | n/a 258 | cppcheck | reinterpret cast float to int32 | ❌ | n/a 259 | cppcheck | reinterpret cast int32 to float | ❌ | n/a 260 | cppcheck | reinterpret cast int32 to uint32 | ❌ | n/a 261 | cppcheck | reinterpret cast uint32 to int32 | ❌ | n/a 262 | cppcheck | reinterpret cast unaligned bytes to uint32 | ❌ | n/a 263 | cppcheck | shifting more than width | ✔️ | shiftTooManyBits 264 | cppcheck | signed integer overflow | ❌ | n/a 265 | cppcheck | sort comp reflexive | ❌ | n/a 266 | cppcheck | stack overflow | ❌ | n/a 267 | cppcheck | std vector reserve set read | ✔️ | containerOutOfBounds 268 | cppcheck | strptime mktime unitialized | ❌ | n/a 269 | cppcheck | virtual call in constructor | ✔️ | ctuOneDefinitionRuleViolation 270 | cppcheck | virtual call in constructor helper | ❌ | n/a 271 | cppcheck | virtual call in constructor lib | ❌ | n/a 272 | cppcheck | virtual call in constructor link | ❌ | n/a 273 | cppcheck | virtual call in destructor | ❌ | n/a 274 | cppcheck | virtual call in destructor helper | ❌ | n/a 275 | cppcheck | virtual call in destructor lib | ❌ | n/a 276 | cppcheck | virtual call in destructor link | ❌ | n/a 277 | 278 | ### 1.3.Static Analysis Summary 279 | Debug (unoptimized) / RelWithDebInfo (optimized) 280 | 281 | Undefined Behavior Type | clang | clang-tidy | cppcheck | gcc | msvc 282 | --- | --- | --- | --- | --- | --- 283 | access after realloc | ❌ | ✔️ | ❌ | ✔️ | ❌ 284 | array out of bounds | ❌ | ✔️ | ✔️ | ❌/✔️ | ❌ 285 | automatic variable over stack | ❌ | ❌ | ❌ | ❌ | ❌ 286 | bad alignment | ❌ | ❌ | ❌ | ❌ | ❌ 287 | bad identifier name | ❌ | ✔️ | ❌ | ❌ | ❌ 288 | delete incomplete type | ✔️ | ✔️ | ❌ | ✔️ | ✔️ 289 | dereferencing nullptr | ❌ | ✔️ | ✔️ | ❌ | ❌ 290 | divide by zero | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 291 | initialize std string with nullptr | ❌ | ❌ | ✔️ | ❌ | ❌ 292 | large double to int | ❌ | ❌ | ❌ | ❌ | ❌ 293 | malloc cast pod struct | ❌ | ❌ | ❌ | ❌ | ❌ 294 | mutate const value | ❌ | ✔️ | ❌ | ❌ | ❌ 295 | non trivial destructor and global | ❌ | ❌ | ❌ | ❌ | ❌ 296 | odr violation function | ❌ | ✔️ | ❌ | ❌ | ❌ 297 | odr violation function lib | ❌ | ❌ | ❌ | ❌ | ❌ 298 | odr violation struct ret | ❌ | ✔️ | ✔️ | ❌ | ❌ 299 | odr violation struct ret lib | ❌ | ❌ | ❌ | ❌ | ❌ 300 | operator star on empty optional | ❌ | ✔️ | ❌ | ❌ | ❌ 301 | out of bounds pointer | ❌ | ❌ | ❌ | ❌/✔️ | ❌ 302 | preincrement plus postincrement | ✔️ | ✔️ | ❌ | ✔️ | ❌ 303 | preincrement plus value | ✔️ | ✔️ | ❌ | ✔️ | ❌ 304 | read from old type | ❌ | ❌ | ❌ | ❌ | ❌ 305 | reading uninitialized value add | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 306 | reading uninitialized value cout | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 307 | reading uninitialized value func arg | ❌ | ✔️ | ❌ | ❌/✔️ | ❌ 308 | reading uninitialized value if | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 309 | reading uninitialized value lib call cref | ✔️ | ✔️ | ✔️ | ✔️ | ❌ 310 | reading uninitialized value partial | ❌ | ✔️ | ✔️ | ❌ | ❌ 311 | reading uninitialized value printf | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 312 | reading uninitialized value return | ✔️ | ✔️ | ✔️ | ✔️ | n/a 313 | reference out of scope | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 314 | reinterpret cast bad size | ❌ | ❌ | ❌ | ✔️ | ❌ 315 | reinterpret cast float to int32 | ❌ | ❌ | ❌ | ❌/✔️ | ❌ 316 | reinterpret cast int32 to float | ❌ | ❌ | ❌ | ❌/✔️ | ❌ 317 | reinterpret cast int32 to uint32 | ❌ | ❌ | ❌ | ❌ | ❌ 318 | reinterpret cast uint32 to int32 | ❌ | ❌ | ❌ | ❌ | ❌ 319 | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | ❌ | ❌ | ❌ 320 | shifting more than width | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 321 | signed integer overflow | ❌ | ❌ | ❌ | ❌ | ❌ 322 | sort comp reflexive | ❌ | ❌ | ❌ | ❌ | ❌ 323 | stack overflow | ✔️ | ✔️ | ❌ | ✔️ | ✔️ 324 | std vector reserve set read | ❌ | ❌ | ✔️ | ❌ | ❌ 325 | strptime mktime unitialized | ❌ | ✔️ | ❌ | ❌ | n/a 326 | virtual call in constructor | ✔️ | ✔️ | ✔️ | ❌ | ❌ 327 | virtual call in constructor helper | ❌ | ✔️ | ❌ | ❌ | ❌ 328 | virtual call in constructor lib | ❌ | ✔️ | ❌ | ❌ | ❌ 329 | virtual call in constructor link | ❌ | ❌ | ❌ | ❌ | ❌ 330 | virtual call in destructor | ✔️ | ✔️ | ❌ | ❌ | ❌ 331 | virtual call in destructor helper | ❌ | ✔️ | ❌ | ❌ | ❌ 332 | virtual call in destructor lib | ❌ | ✔️ | ❌ | ❌ | ❌ 333 | virtual call in destructor link | ❌ | ❌ | ❌ | ❌ | ❌ 334 | 335 | 336 | ## 2.Runtime Crashes 337 | ### 2.1.Runtime Crashes Return Codes 338 | Compiler | Undefined Behavior Type | Debug | RelWithDebInfo 339 | --- | --- | --- | --- 340 | clang | access after realloc | 0 | 0 341 | clang | array out of bounds | 0 | 0 342 | clang | automatic variable over stack | 139 | 0 343 | clang | bad alignment | 0 | 0 344 | clang | bad identifier name | 0 | 0 345 | clang | delete incomplete type | 0 | 0 346 | clang | dereferencing nullptr | 139 | 0 347 | clang | divide by zero | 0 | 0 348 | clang | initialize std string with nullptr | 134 | 134 349 | clang | large double to int | 0 | 0 350 | clang | malloc cast pod struct | 0 | 0 351 | clang | mutate const value | 0 | 0 352 | clang | odr violation function | 0 | 0 353 | clang | odr violation struct ret | 0 | 0 354 | clang | operator star on empty optional | 0 | 0 355 | clang | out of bounds pointer | 0 | 0 356 | clang | preincrement plus postincrement | 0 | 0 357 | clang | preincrement plus value | 0 | 0 358 | clang | read from old type | 0 | 0 359 | clang | reading uninitialized value add | 0 | 0 360 | clang | reading uninitialized value cout | 0 | 0 361 | clang | reading uninitialized value func arg | 0 | 139 362 | clang | reading uninitialized value if | 0 | 48 363 | clang | reading uninitialized value lib call cref | 0 | 0 364 | clang | reading uninitialized value partial | 0 | 0 365 | clang | reading uninitialized value printf | 0 | 0 366 | clang | reading uninitialized value return | 132 | 48 367 | clang | reference out of scope | 0 | 0 368 | clang | reinterpret cast bad size | 0 | 0 369 | clang | reinterpret cast float to int32 | 0 | 0 370 | clang | reinterpret cast int32 to float | 0 | 0 371 | clang | reinterpret cast int32 to uint32 | 0 | 0 372 | clang | reinterpret cast uint32 to int32 | 0 | 0 373 | clang | reinterpret cast unaligned bytes to uint32 | 0 | 0 374 | clang | shifting more than width | 0 | 0 375 | clang | signed integer overflow | 0 | 0 376 | clang | sort comp reflexive | 0 | 0 377 | clang | stack overflow | 139 | 48 378 | clang | std vector reserve set read | 0 | 0 379 | clang | strptime mktime unitialized | 0 | 0 380 | clang | virtual call in constructor | 134 | 134 381 | clang | virtual call in constructor helper | 134 | 134 382 | clang | virtual call in constructor link | 134 | 134 383 | clang | virtual call in destructor | 134 | 134 384 | clang | virtual call in destructor helper | 134 | 134 385 | clang | virtual call in destructor link | 134 | 134 386 | gcc | access after realloc | 0 | 0 387 | gcc | array out of bounds | 0 | 0 388 | gcc | automatic variable over stack | 139 | 0 389 | gcc | bad alignment | 0 | 0 390 | gcc | bad identifier name | 0 | 0 391 | gcc | delete incomplete type | 0 | 0 392 | gcc | dereferencing nullptr | 139 | 139 393 | gcc | divide by zero | 136 | 132 394 | gcc | initialize std string with nullptr | 134 | 134 395 | gcc | large double to int | 0 | 0 396 | gcc | malloc cast pod struct | 0 | 0 397 | gcc | mutate const value | 0 | 0 398 | gcc | odr violation function | 0 | 0 399 | gcc | odr violation struct ret | 0 | 0 400 | gcc | operator star on empty optional | 0 | 0 401 | gcc | out of bounds pointer | 0 | 0 402 | gcc | preincrement plus postincrement | 0 | 0 403 | gcc | preincrement plus value | 0 | 0 404 | gcc | read from old type | 0 | 0 405 | gcc | reading uninitialized value add | 0 | 0 406 | gcc | reading uninitialized value cout | 0 | 0 407 | gcc | reading uninitialized value func arg | 0 | 139 408 | gcc | reading uninitialized value if | 0 | 0 409 | gcc | reading uninitialized value lib call cref | 0 | 0 410 | gcc | reading uninitialized value partial | 0 | 0 411 | gcc | reading uninitialized value printf | 0 | 0 412 | gcc | reading uninitialized value return | 132 | 139 413 | gcc | reference out of scope | 139 | 139 414 | gcc | reinterpret cast bad size | 0 | 0 415 | gcc | reinterpret cast float to int32 | 0 | 0 416 | gcc | reinterpret cast int32 to float | 0 | 0 417 | gcc | reinterpret cast int32 to uint32 | 0 | 0 418 | gcc | reinterpret cast uint32 to int32 | 0 | 0 419 | gcc | reinterpret cast unaligned bytes to uint32 | 0 | 0 420 | gcc | shifting more than width | 0 | 0 421 | gcc | signed integer overflow | 0 | 0 422 | gcc | sort comp reflexive | 0 | 0 423 | gcc | stack overflow | 139 | 124 424 | gcc | std vector reserve set read | 0 | 0 425 | gcc | strptime mktime unitialized | 0 | 0 426 | gcc | virtual call in constructor helper | 134 | 134 427 | gcc | virtual call in constructor link | 134 | 134 428 | gcc | virtual call in destructor helper | 134 | 134 429 | gcc | virtual call in destructor link | 134 | 134 430 | msvc | access after realloc | 0 | 0 431 | msvc | array out of bounds | -1 | 0 432 | msvc | automatic variable over stack | -1073741571 | 0 433 | msvc | bad alignment | 0 | 0 434 | msvc | bad identifier name | 0 | 0 435 | msvc | delete incomplete type | 0 | 0 436 | msvc | dereferencing nullptr | -1073741819 | -1073741819 437 | msvc | divide by zero | -1073741676 | -1073741676 438 | msvc | initialize std string with nullptr | -1073741819 | -1073741819 439 | msvc | large double to int | 0 | 0 440 | msvc | malloc cast pod struct | 0 | 0 441 | msvc | mutate const value | 0 | 0 442 | msvc | odr violation function | 0 | 0 443 | msvc | odr violation struct ret | 0 | 0 444 | msvc | operator star on empty optional | -1 | 0 445 | msvc | out of bounds pointer | 0 | 0 446 | msvc | preincrement plus postincrement | 0 | 0 447 | msvc | preincrement plus value | 0 | 0 448 | msvc | read from old type | 0 | 0 449 | msvc | reading uninitialized value add | -1 | 0 450 | msvc | reading uninitialized value cout | -1 | 0 451 | msvc | reading uninitialized value func arg | -1073741819 | -1073740791 452 | msvc | reading uninitialized value if | -1 | 0 453 | msvc | reading uninitialized value lib call cref | 0 | 0 454 | msvc | reading uninitialized value partial | -1 | -1073740791 455 | msvc | reading uninitialized value printf | -1 | 0 456 | msvc | reference out of scope | 0 | 0 457 | msvc | reinterpret cast bad size | 0 | 0 458 | msvc | reinterpret cast float to int32 | 0 | 0 459 | msvc | reinterpret cast int32 to float | 0 | 0 460 | msvc | reinterpret cast int32 to uint32 | 0 | 0 461 | msvc | reinterpret cast uint32 to int32 | 0 | 0 462 | msvc | reinterpret cast unaligned bytes to uint32 | 0 | 0 463 | msvc | shifting more than width | 0 | 0 464 | msvc | signed integer overflow | 0 | 0 465 | msvc | sort comp reflexive | 0 | 0 466 | msvc | stack overflow | -1073741571 | -1073741571 467 | msvc | std vector reserve set read | -1 | 0 468 | msvc | virtual call in constructor helper | -1 | -1073740791 469 | msvc | virtual call in constructor link | -1 | -1073740791 470 | msvc | virtual call in destructor helper | -1 | -1073740791 471 | msvc | virtual call in destructor link | -1 | -1073740791 472 | 473 | ### 2.2.Runtime Crashes Summary 474 | Debug (unoptimized) / RelWithDebInfo (optimized) 475 | 476 | Undefined Behavior | clang | gcc | msvc 477 | --- | --- | --- | --- 478 | access after realloc | ❌ | ❌ | ❌ 479 | array out of bounds | ❌ | ❌ | ✔️/❌ 480 | automatic variable over stack | ✔️/❌ | ✔️/❌ | ✔️/❌ 481 | bad alignment | ❌ | ❌ | ❌ 482 | bad identifier name | ❌ | ❌ | ❌ 483 | delete incomplete type | ❌ | ❌ | ❌ 484 | dereferencing nullptr | ✔️/❌ | ✔️ | ✔️ 485 | divide by zero | ❌ | ✔️ | ✔️ 486 | initialize std string with nullptr | ✔️ | ✔️ | ✔️ 487 | large double to int | ❌ | ❌ | ❌ 488 | malloc cast pod struct | ❌ | ❌ | ❌ 489 | mutate const value | ❌ | ❌ | ❌ 490 | odr violation function | ❌ | ❌ | ❌ 491 | odr violation struct ret | ❌ | ❌ | ❌ 492 | operator star on empty optional | ❌ | ❌ | ✔️/❌ 493 | out of bounds pointer | ❌ | ❌ | ❌ 494 | preincrement plus postincrement | ❌ | ❌ | ❌ 495 | preincrement plus value | ❌ | ❌ | ❌ 496 | read from old type | ❌ | ❌ | ❌ 497 | reading uninitialized value add | ❌ | ❌ | ✔️/❌ 498 | reading uninitialized value cout | ❌ | ❌ | ✔️/❌ 499 | reading uninitialized value func arg | ❌/✔️ | ❌/✔️ | ✔️ 500 | reading uninitialized value if | ❌/✔️ | ❌ | ✔️/❌ 501 | reading uninitialized value lib call cref | ❌ | ❌ | ❌ 502 | reading uninitialized value partial | ❌ | ❌ | ✔️ 503 | reading uninitialized value printf | ❌ | ❌ | ✔️/❌ 504 | reading uninitialized value return | ✔️ | ✔️ | n/a 505 | reference out of scope | ❌ | ✔️ | ❌ 506 | reinterpret cast bad size | ❌ | ❌ | ❌ 507 | reinterpret cast float to int32 | ❌ | ❌ | ❌ 508 | reinterpret cast int32 to float | ❌ | ❌ | ❌ 509 | reinterpret cast int32 to uint32 | ❌ | ❌ | ❌ 510 | reinterpret cast uint32 to int32 | ❌ | ❌ | ❌ 511 | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | ❌ 512 | shifting more than width | ❌ | ❌ | ❌ 513 | signed integer overflow | ❌ | ❌ | ❌ 514 | sort comp reflexive | ❌ | ❌ | ❌ 515 | stack overflow | ✔️ | ✔️ | ✔️ 516 | std vector reserve set read | ❌ | ❌ | ✔️/❌ 517 | strptime mktime unitialized | ❌ | ❌ | n/a 518 | virtual call in constructor | ✔️ | n/a | n/a 519 | virtual call in constructor helper | ✔️ | ✔️ | ✔️ 520 | virtual call in constructor link | ✔️ | ✔️ | ✔️ 521 | virtual call in destructor | ✔️ | n/a | n/a 522 | virtual call in destructor helper | ✔️ | ✔️ | ✔️ 523 | virtual call in destructor link | ✔️ | ✔️ | ✔️ 524 | 525 | 526 | ## 3.Extra Dynamic Analysis 527 | ### 3.1.Extra Dynamic Analysis Return Codes 528 | Compiler | Tool | Undefined Behavior Type | Debug | RelWithDebInfo 529 | --- | --- | --- | --- | --- 530 | clang | address | access after realloc | 1 | 1 531 | clang | address | array out of bounds | 1 | 0 532 | clang | address | automatic variable over stack | 1 | 0 533 | clang | address | bad alignment | 0 | 0 534 | clang | address | bad identifier name | 0 | 0 535 | clang | address | delete incomplete type | 0 | 0 536 | clang | address | dereferencing nullptr | 1 | 0 537 | clang | address | divide by zero | 0 | 0 538 | clang | address | initialize std string with nullptr | 134 | 134 539 | clang | address | large double to int | 0 | 0 540 | clang | address | malloc cast pod struct | 0 | 0 541 | clang | address | mutate const value | 0 | 0 542 | clang | address | odr violation function | 0 | 0 543 | clang | address | odr violation struct ret | 0 | 0 544 | clang | address | operator star on empty optional | 0 | 0 545 | clang | address | out of bounds pointer | 0 | 0 546 | clang | address | preincrement plus postincrement | 0 | 0 547 | clang | address | preincrement plus value | 0 | 0 548 | clang | address | read from old type | 0 | 0 549 | clang | address | reading uninitialized value add | 0 | 0 550 | clang | address | reading uninitialized value cout | 0 | 0 551 | clang | address | reading uninitialized value func arg | 1 | 1 552 | clang | address | reading uninitialized value if | 0 | 48 553 | clang | address | reading uninitialized value lib call cref | 0 | 0 554 | clang | address | reading uninitialized value partial | 0 | 0 555 | clang | address | reading uninitialized value printf | 0 | 0 556 | clang | address | reading uninitialized value return | 132 | 48 557 | clang | address | reference out of scope | 1 | 0 558 | clang | address | reinterpret cast bad size | 1 | 0 559 | clang | address | reinterpret cast float to int32 | 0 | 0 560 | clang | address | reinterpret cast int32 to float | 0 | 0 561 | clang | address | reinterpret cast int32 to uint32 | 0 | 0 562 | clang | address | reinterpret cast uint32 to int32 | 0 | 0 563 | clang | address | reinterpret cast unaligned bytes to uint32 | 0 | 0 564 | clang | address | shifting more than width | 0 | 0 565 | clang | address | signed integer overflow | 0 | 0 566 | clang | address | sort comp reflexive | 0 | 0 567 | clang | address | stack overflow | 1 | 48 568 | clang | address | std vector reserve set read | 0 | 0 569 | clang | address | strptime mktime unitialized | 0 | 0 570 | clang | address | virtual call in constructor | 134 | 134 571 | clang | address | virtual call in constructor helper | 134 | 134 572 | clang | address | virtual call in constructor link | 134 | 134 573 | clang | address | virtual call in destructor | 134 | 134 574 | clang | address | virtual call in destructor helper | 134 | 134 575 | clang | address | virtual call in destructor link | 134 | 134 576 | clang | address,undefined | access after realloc | 1 | 1 577 | clang | address,undefined | array out of bounds | 1 | 1 578 | clang | address,undefined | automatic variable over stack | 1 | 1 579 | clang | address,undefined | bad alignment | 1 | 1 580 | clang | address,undefined | bad identifier name | 0 | 0 581 | clang | address,undefined | delete incomplete type | 0 | 0 582 | clang | address,undefined | dereferencing nullptr | 1 | 1 583 | clang | address,undefined | divide by zero | 1 | 1 584 | clang | address,undefined | initialize std string with nullptr | 134 | 134 585 | clang | address,undefined | large double to int | 1 | 1 586 | clang | address,undefined | malloc cast pod struct | 0 | 0 587 | clang | address,undefined | mutate const value | 0 | 0 588 | clang | address,undefined | odr violation function | 0 | 0 589 | clang | address,undefined | odr violation struct ret | 0 | 0 590 | clang | address,undefined | operator star on empty optional | 0 | 0 591 | clang | address,undefined | out of bounds pointer | 0 | 0 592 | clang | address,undefined | preincrement plus postincrement | 0 | 0 593 | clang | address,undefined | preincrement plus value | 0 | 0 594 | clang | address,undefined | read from old type | 1 | 1 595 | clang | address,undefined | reading uninitialized value add | 0 | 0 596 | clang | address,undefined | reading uninitialized value cout | 0 | 0 597 | clang | address,undefined | reading uninitialized value func arg | 1 | 1 598 | clang | address,undefined | reading uninitialized value if | 1 | 56 599 | clang | address,undefined | reading uninitialized value lib call cref | 0 | 0 600 | clang | address,undefined | reading uninitialized value partial | 0 | 0 601 | clang | address,undefined | reading uninitialized value printf | 0 | 0 602 | clang | address,undefined | reading uninitialized value return | 1 | 1 603 | clang | address,undefined | reference out of scope | 1 | 0 604 | clang | address,undefined | reinterpret cast bad size | 1 | 1 605 | clang | address,undefined | reinterpret cast float to int32 | 0 | 0 606 | clang | address,undefined | reinterpret cast int32 to float | 0 | 0 607 | clang | address,undefined | reinterpret cast int32 to uint32 | 0 | 0 608 | clang | address,undefined | reinterpret cast uint32 to int32 | 0 | 0 609 | clang | address,undefined | reinterpret cast unaligned bytes to uint32 | 0 | 0 610 | clang | address,undefined | shifting more than width | 1 | 1 611 | clang | address,undefined | signed integer overflow | 1 | 1 612 | clang | address,undefined | sort comp reflexive | 0 | 0 613 | clang | address,undefined | stack overflow | 1 | 1 614 | clang | address,undefined | std vector reserve set read | 0 | 0 615 | clang | address,undefined | strptime mktime unitialized | 0 | 0 616 | clang | address,undefined | virtual call in constructor | 134 | 134 617 | clang | address,undefined | virtual call in constructor helper | 134 | 134 618 | clang | address,undefined | virtual call in constructor link | 134 | 134 619 | clang | address,undefined | virtual call in destructor | 134 | 134 620 | clang | address,undefined | virtual call in destructor helper | 134 | 134 621 | clang | address,undefined | virtual call in destructor link | 134 | 134 622 | clang | undefined | access after realloc | 0 | 0 623 | clang | undefined | array out of bounds | 0 | 1 624 | clang | undefined | automatic variable over stack | 1 | 1 625 | clang | undefined | bad alignment | 0 | 1 626 | clang | undefined | bad identifier name | 0 | 0 627 | clang | undefined | delete incomplete type | 0 | 0 628 | clang | undefined | dereferencing nullptr | 1 | 1 629 | clang | undefined | divide by zero | 1 | 1 630 | clang | undefined | initialize std string with nullptr | 134 | 134 631 | clang | undefined | large double to int | 1 | 1 632 | clang | undefined | malloc cast pod struct | 0 | 0 633 | clang | undefined | mutate const value | 0 | 0 634 | clang | undefined | odr violation function | 0 | 0 635 | clang | undefined | odr violation struct ret | 0 | 0 636 | clang | undefined | operator star on empty optional | 0 | 0 637 | clang | undefined | out of bounds pointer | 0 | 0 638 | clang | undefined | preincrement plus postincrement | 0 | 0 639 | clang | undefined | preincrement plus value | 0 | 0 640 | clang | undefined | read from old type | 1 | 1 641 | clang | undefined | reading uninitialized value add | 0 | 0 642 | clang | undefined | reading uninitialized value cout | 0 | 0 643 | clang | undefined | reading uninitialized value func arg | 0 | 1 644 | clang | undefined | reading uninitialized value if | 1 | 1 645 | clang | undefined | reading uninitialized value lib call cref | 0 | 0 646 | clang | undefined | reading uninitialized value partial | 0 | 0 647 | clang | undefined | reading uninitialized value printf | 0 | 0 648 | clang | undefined | reading uninitialized value return | 1 | 1 649 | clang | undefined | reference out of scope | 0 | 0 650 | clang | undefined | reinterpret cast bad size | 0 | 1 651 | clang | undefined | reinterpret cast float to int32 | 0 | 0 652 | clang | undefined | reinterpret cast int32 to float | 0 | 0 653 | clang | undefined | reinterpret cast int32 to uint32 | 0 | 0 654 | clang | undefined | reinterpret cast uint32 to int32 | 0 | 0 655 | clang | undefined | reinterpret cast unaligned bytes to uint32 | 0 | 0 656 | clang | undefined | shifting more than width | 1 | 1 657 | clang | undefined | signed integer overflow | 1 | 1 658 | clang | undefined | sort comp reflexive | 0 | 0 659 | clang | undefined | stack overflow | 1 | 1 660 | clang | undefined | std vector reserve set read | 0 | 0 661 | clang | undefined | strptime mktime unitialized | 0 | 0 662 | clang | undefined | virtual call in constructor | 134 | 134 663 | clang | undefined | virtual call in constructor helper | 134 | 134 664 | clang | undefined | virtual call in constructor link | 134 | 134 665 | clang | undefined | virtual call in destructor | 134 | 134 666 | clang | undefined | virtual call in destructor helper | 134 | 134 667 | clang | undefined | virtual call in destructor link | 134 | 134 668 | gcc | address | access after realloc | 1 | 1 669 | gcc | address | array out of bounds | 1 | 1 670 | gcc | address | automatic variable over stack | 1 | 1 671 | gcc | address | bad alignment | 0 | 0 672 | gcc | address | bad identifier name | 0 | 0 673 | gcc | address | delete incomplete type | 0 | 0 674 | gcc | address | dereferencing nullptr | 1 | 1 675 | gcc | address | divide by zero | 1 | 132 676 | gcc | address | initialize std string with nullptr | 134 | 134 677 | gcc | address | large double to int | 0 | 0 678 | gcc | address | malloc cast pod struct | 0 | 0 679 | gcc | address | mutate const value | 0 | 0 680 | gcc | address | odr violation function | 0 | 0 681 | gcc | address | odr violation struct ret | 0 | 0 682 | gcc | address | operator star on empty optional | 0 | 0 683 | gcc | address | out of bounds pointer | 0 | 0 684 | gcc | address | preincrement plus postincrement | 0 | 0 685 | gcc | address | preincrement plus value | 0 | 0 686 | gcc | address | read from old type | 0 | 0 687 | gcc | address | reading uninitialized value add | 0 | 0 688 | gcc | address | reading uninitialized value cout | 0 | 0 689 | gcc | address | reading uninitialized value func arg | 1 | 1 690 | gcc | address | reading uninitialized value if | 0 | 0 691 | gcc | address | reading uninitialized value lib call cref | 0 | 0 692 | gcc | address | reading uninitialized value partial | 0 | 0 693 | gcc | address | reading uninitialized value printf | 0 | 0 694 | gcc | address | reading uninitialized value return | 132 | 132 695 | gcc | address | reference out of scope | 1 | 1 696 | gcc | address | reinterpret cast bad size | 1 | 1 697 | gcc | address | reinterpret cast float to int32 | 0 | 0 698 | gcc | address | reinterpret cast int32 to float | 0 | 0 699 | gcc | address | reinterpret cast int32 to uint32 | 0 | 0 700 | gcc | address | reinterpret cast uint32 to int32 | 0 | 0 701 | gcc | address | reinterpret cast unaligned bytes to uint32 | 0 | 0 702 | gcc | address | shifting more than width | 0 | 0 703 | gcc | address | signed integer overflow | 0 | 0 704 | gcc | address | sort comp reflexive | 0 | 0 705 | gcc | address | stack overflow | 1 | 124 706 | gcc | address | std vector reserve set read | 0 | 0 707 | gcc | address | strptime mktime unitialized | 0 | 0 708 | gcc | address | virtual call in constructor helper | 134 | 134 709 | gcc | address | virtual call in constructor link | 134 | 134 710 | gcc | address | virtual call in destructor helper | 134 | 134 711 | gcc | address | virtual call in destructor link | 134 | 134 712 | gcc | address,leak,undefined | access after realloc | 1 | 1 713 | gcc | address,leak,undefined | array out of bounds | 1 | 1 714 | gcc | address,leak,undefined | automatic variable over stack | 1 | 1 715 | gcc | address,leak,undefined | bad alignment | 1 | 1 716 | gcc | address,leak,undefined | bad identifier name | 0 | 0 717 | gcc | address,leak,undefined | delete incomplete type | 0 | 0 718 | gcc | address,leak,undefined | dereferencing nullptr | 1 | 1 719 | gcc | address,leak,undefined | divide by zero | 1 | 1 720 | gcc | address,leak,undefined | initialize std string with nullptr | 134 | 134 721 | gcc | address,leak,undefined | large double to int | 0 | 0 722 | gcc | address,leak,undefined | malloc cast pod struct | 0 | 0 723 | gcc | address,leak,undefined | mutate const value | 0 | 0 724 | gcc | address,leak,undefined | odr violation function | 0 | 0 725 | gcc | address,leak,undefined | odr violation struct ret | 0 | 0 726 | gcc | address,leak,undefined | operator star on empty optional | 0 | 0 727 | gcc | address,leak,undefined | out of bounds pointer | 0 | 0 728 | gcc | address,leak,undefined | preincrement plus postincrement | 0 | 0 729 | gcc | address,leak,undefined | preincrement plus value | 0 | 0 730 | gcc | address,leak,undefined | read from old type | 1 | 1 731 | gcc | address,leak,undefined | reading uninitialized value add | 0 | 0 732 | gcc | address,leak,undefined | reading uninitialized value cout | 0 | 0 733 | gcc | address,leak,undefined | reading uninitialized value func arg | 1 | 1 734 | gcc | address,leak,undefined | reading uninitialized value if | 0 | 0 735 | gcc | address,leak,undefined | reading uninitialized value lib call cref | 0 | 0 736 | gcc | address,leak,undefined | reading uninitialized value partial | 0 | 0 737 | gcc | address,leak,undefined | reading uninitialized value printf | 0 | 0 738 | gcc | address,leak,undefined | reading uninitialized value return | 1 | 1 739 | gcc | address,leak,undefined | reference out of scope | 1 | 1 740 | gcc | address,leak,undefined | reinterpret cast bad size | 1 | 1 741 | gcc | address,leak,undefined | reinterpret cast float to int32 | 0 | 0 742 | gcc | address,leak,undefined | reinterpret cast int32 to float | 0 | 0 743 | gcc | address,leak,undefined | reinterpret cast int32 to uint32 | 0 | 0 744 | gcc | address,leak,undefined | reinterpret cast uint32 to int32 | 0 | 0 745 | gcc | address,leak,undefined | reinterpret cast unaligned bytes to uint32 | 0 | 0 746 | gcc | address,leak,undefined | shifting more than width | 1 | 1 747 | gcc | address,leak,undefined | signed integer overflow | 1 | 1 748 | gcc | address,leak,undefined | sort comp reflexive | 0 | 0 749 | gcc | address,leak,undefined | stack overflow | 1 | 124 750 | gcc | address,leak,undefined | std vector reserve set read | 0 | 0 751 | gcc | address,leak,undefined | strptime mktime unitialized | 0 | 0 752 | gcc | address,leak,undefined | virtual call in constructor helper | 134 | 134 753 | gcc | address,leak,undefined | virtual call in constructor link | 134 | 134 754 | gcc | address,leak,undefined | virtual call in destructor helper | 134 | 134 755 | gcc | address,leak,undefined | virtual call in destructor link | 134 | 134 756 | gcc | leak | access after realloc | 0 | 0 757 | gcc | leak | array out of bounds | 0 | 0 758 | gcc | leak | automatic variable over stack | 23 | 0 759 | gcc | leak | bad alignment | 0 | 0 760 | gcc | leak | bad identifier name | 0 | 0 761 | gcc | leak | delete incomplete type | 0 | 0 762 | gcc | leak | dereferencing nullptr | 23 | 23 763 | gcc | leak | divide by zero | 23 | 132 764 | gcc | leak | initialize std string with nullptr | 134 | 134 765 | gcc | leak | large double to int | 0 | 0 766 | gcc | leak | malloc cast pod struct | 0 | 0 767 | gcc | leak | mutate const value | 0 | 0 768 | gcc | leak | odr violation function | 0 | 0 769 | gcc | leak | odr violation struct ret | 0 | 0 770 | gcc | leak | operator star on empty optional | 0 | 0 771 | gcc | leak | out of bounds pointer | 0 | 0 772 | gcc | leak | preincrement plus postincrement | 0 | 0 773 | gcc | leak | preincrement plus value | 0 | 0 774 | gcc | leak | read from old type | 0 | 0 775 | gcc | leak | reading uninitialized value add | 0 | 0 776 | gcc | leak | reading uninitialized value cout | 0 | 0 777 | gcc | leak | reading uninitialized value func arg | 0 | 23 778 | gcc | leak | reading uninitialized value if | 0 | 0 779 | gcc | leak | reading uninitialized value lib call cref | 0 | 0 780 | gcc | leak | reading uninitialized value partial | 0 | 0 781 | gcc | leak | reading uninitialized value printf | 0 | 0 782 | gcc | leak | reading uninitialized value return | 132 | 23 783 | gcc | leak | reference out of scope | 23 | 23 784 | gcc | leak | reinterpret cast bad size | 0 | 0 785 | gcc | leak | reinterpret cast float to int32 | 0 | 0 786 | gcc | leak | reinterpret cast int32 to float | 0 | 0 787 | gcc | leak | reinterpret cast int32 to uint32 | 0 | 0 788 | gcc | leak | reinterpret cast uint32 to int32 | 0 | 0 789 | gcc | leak | reinterpret cast unaligned bytes to uint32 | 0 | 0 790 | gcc | leak | shifting more than width | 0 | 0 791 | gcc | leak | signed integer overflow | 0 | 0 792 | gcc | leak | sort comp reflexive | 0 | 0 793 | gcc | leak | stack overflow | 23 | 124 794 | gcc | leak | std vector reserve set read | 0 | 0 795 | gcc | leak | strptime mktime unitialized | 0 | 0 796 | gcc | leak | virtual call in constructor helper | 134 | 134 797 | gcc | leak | virtual call in constructor link | 134 | 134 798 | gcc | leak | virtual call in destructor helper | 134 | 134 799 | gcc | leak | virtual call in destructor link | 134 | 134 800 | gcc | undefined | access after realloc | 0 | 0 801 | gcc | undefined | array out of bounds | 0 | 1 802 | gcc | undefined | automatic variable over stack | 139 | 139 803 | gcc | undefined | bad alignment | 0 | 0 804 | gcc | undefined | bad identifier name | 0 | 0 805 | gcc | undefined | delete incomplete type | 0 | 0 806 | gcc | undefined | dereferencing nullptr | 1 | 1 807 | gcc | undefined | divide by zero | 1 | 1 808 | gcc | undefined | initialize std string with nullptr | 134 | 134 809 | gcc | undefined | large double to int | 0 | 0 810 | gcc | undefined | malloc cast pod struct | 0 | 0 811 | gcc | undefined | mutate const value | 0 | 0 812 | gcc | undefined | odr violation function | 0 | 0 813 | gcc | undefined | odr violation struct ret | 0 | 0 814 | gcc | undefined | operator star on empty optional | 0 | 0 815 | gcc | undefined | out of bounds pointer | 0 | 0 816 | gcc | undefined | preincrement plus postincrement | 0 | 0 817 | gcc | undefined | preincrement plus value | 0 | 0 818 | gcc | undefined | read from old type | 1 | 1 819 | gcc | undefined | reading uninitialized value add | 0 | 0 820 | gcc | undefined | reading uninitialized value cout | 0 | 0 821 | gcc | undefined | reading uninitialized value func arg | 0 | 1 822 | gcc | undefined | reading uninitialized value if | 0 | 0 823 | gcc | undefined | reading uninitialized value lib call cref | 0 | 0 824 | gcc | undefined | reading uninitialized value partial | 0 | 0 825 | gcc | undefined | reading uninitialized value printf | 0 | 0 826 | gcc | undefined | reading uninitialized value return | 1 | 1 827 | gcc | undefined | reference out of scope | 1 | 1 828 | gcc | undefined | reinterpret cast bad size | 1 | 1 829 | gcc | undefined | reinterpret cast float to int32 | 0 | 0 830 | gcc | undefined | reinterpret cast int32 to float | 0 | 0 831 | gcc | undefined | reinterpret cast int32 to uint32 | 0 | 0 832 | gcc | undefined | reinterpret cast uint32 to int32 | 0 | 0 833 | gcc | undefined | reinterpret cast unaligned bytes to uint32 | 0 | 0 834 | gcc | undefined | shifting more than width | 1 | 1 835 | gcc | undefined | signed integer overflow | 1 | 1 836 | gcc | undefined | sort comp reflexive | 0 | 0 837 | gcc | undefined | stack overflow | 139 | 124 838 | gcc | undefined | std vector reserve set read | 0 | 0 839 | gcc | undefined | strptime mktime unitialized | 0 | 0 840 | gcc | undefined | virtual call in constructor helper | 134 | 134 841 | gcc | undefined | virtual call in constructor link | 134 | 134 842 | gcc | undefined | virtual call in destructor helper | 134 | 134 843 | gcc | undefined | virtual call in destructor link | 134 | 134 844 | gcc | valgrind | access after realloc | 1 | 1 845 | gcc | valgrind | array out of bounds | 0 | 0 846 | gcc | valgrind | automatic variable over stack | 139 | 0 847 | gcc | valgrind | bad alignment | 0 | 0 848 | gcc | valgrind | bad identifier name | 0 | 0 849 | gcc | valgrind | delete incomplete type | 0 | 0 850 | gcc | valgrind | dereferencing nullptr | 139 | 139 851 | gcc | valgrind | divide by zero | 136 | 132 852 | gcc | valgrind | initialize std string with nullptr | 134 | 134 853 | gcc | valgrind | large double to int | 0 | 0 854 | gcc | valgrind | malloc cast pod struct | 0 | 0 855 | gcc | valgrind | mutate const value | 0 | 0 856 | gcc | valgrind | odr violation function | 0 | 0 857 | gcc | valgrind | odr violation struct ret | 0 | 0 858 | gcc | valgrind | operator star on empty optional | 0 | 0 859 | gcc | valgrind | out of bounds pointer | 0 | 0 860 | gcc | valgrind | preincrement plus postincrement | 0 | 0 861 | gcc | valgrind | preincrement plus value | 0 | 0 862 | gcc | valgrind | read from old type | 0 | 0 863 | gcc | valgrind | reading uninitialized value add | 1 | 0 864 | gcc | valgrind | reading uninitialized value cout | 1 | 0 865 | gcc | valgrind | reading uninitialized value func arg | 1 | 139 866 | gcc | valgrind | reading uninitialized value if | 1 | 0 867 | gcc | valgrind | reading uninitialized value lib call cref | 1 | 1 868 | gcc | valgrind | reading uninitialized value partial | 1 | 0 869 | gcc | valgrind | reading uninitialized value printf | 1 | 0 870 | gcc | valgrind | reading uninitialized value return | 132 | 139 871 | gcc | valgrind | reference out of scope | 139 | 139 872 | gcc | valgrind | reinterpret cast bad size | 0 | 1 873 | gcc | valgrind | reinterpret cast float to int32 | 0 | 0 874 | gcc | valgrind | reinterpret cast int32 to float | 0 | 0 875 | gcc | valgrind | reinterpret cast int32 to uint32 | 0 | 0 876 | gcc | valgrind | reinterpret cast uint32 to int32 | 0 | 0 877 | gcc | valgrind | reinterpret cast unaligned bytes to uint32 | 0 | 0 878 | gcc | valgrind | shifting more than width | 0 | 0 879 | gcc | valgrind | signed integer overflow | 0 | 0 880 | gcc | valgrind | sort comp reflexive | 0 | 0 881 | gcc | valgrind | stack overflow | 139 | 124 882 | gcc | valgrind | std vector reserve set read | 0 | 0 883 | gcc | valgrind | strptime mktime unitialized | 1 | 1 884 | gcc | valgrind | virtual call in constructor helper | 134 | 134 885 | gcc | valgrind | virtual call in constructor link | 134 | 134 886 | gcc | valgrind | virtual call in destructor helper | 134 | 134 887 | gcc | valgrind | virtual call in destructor link | 134 | 134 888 | 889 | ### 3.2.1.Extra Dynamic Analysis Summary Clang 890 | Debug (unoptimized) / RelWithDebInfo (optimized) 891 | 892 | Undefined Behavior Type | address | address,undefined | undefined 893 | --- |--- |--- | --- 894 | access after realloc | ✔️ | ✔️ | ❌ 895 | array out of bounds | ✔️/❌ | ✔️ | ❌/✔️ 896 | automatic variable over stack | ✔️/❌ | ✔️ | ✔️ 897 | bad alignment | ❌ | ✔️ | ❌/✔️ 898 | bad identifier name | ❌ | ❌ | ❌ 899 | delete incomplete type | ❌ | ❌ | ❌ 900 | dereferencing nullptr | ✔️/❌ | ✔️ | ✔️ 901 | divide by zero | ❌ | ✔️ | ✔️ 902 | initialize std string with nullptr | ✔️ | ✔️ | ✔️ 903 | large double to int | ❌ | ✔️ | ✔️ 904 | malloc cast pod struct | ❌ | ❌ | ❌ 905 | mutate const value | ❌ | ❌ | ❌ 906 | odr violation function | ❌ | ❌ | ❌ 907 | odr violation struct ret | ❌ | ❌ | ❌ 908 | operator star on empty optional | ❌ | ❌ | ❌ 909 | out of bounds pointer | ❌ | ❌ | ❌ 910 | preincrement plus postincrement | ❌ | ❌ | ❌ 911 | preincrement plus value | ❌ | ❌ | ❌ 912 | read from old type | ❌ | ✔️ | ✔️ 913 | reading uninitialized value add | ❌ | ❌ | ❌ 914 | reading uninitialized value cout | ❌ | ❌ | ❌ 915 | reading uninitialized value func arg | ✔️ | ✔️ | ❌/✔️ 916 | reading uninitialized value if | ❌/✔️ | ✔️ | ✔️ 917 | reading uninitialized value lib call cref | ❌ | ❌ | ❌ 918 | reading uninitialized value partial | ❌ | ❌ | ❌ 919 | reading uninitialized value printf | ❌ | ❌ | ❌ 920 | reading uninitialized value return | ✔️ | ✔️ | ✔️ 921 | reference out of scope | ✔️/❌ | ✔️/❌ | ❌ 922 | reinterpret cast bad size | ✔️/❌ | ✔️ | ❌/✔️ 923 | reinterpret cast float to int32 | ❌ | ❌ | ❌ 924 | reinterpret cast int32 to float | ❌ | ❌ | ❌ 925 | reinterpret cast int32 to uint32 | ❌ | ❌ | ❌ 926 | reinterpret cast uint32 to int32 | ❌ | ❌ | ❌ 927 | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | ❌ 928 | shifting more than width | ❌ | ✔️ | ✔️ 929 | signed integer overflow | ❌ | ✔️ | ✔️ 930 | sort comp reflexive | ❌ | ❌ | ❌ 931 | stack overflow | ✔️ | ✔️ | ✔️ 932 | std vector reserve set read | ❌ | ❌ | ❌ 933 | strptime mktime unitialized | ❌ | ❌ | ❌ 934 | virtual call in constructor | ✔️ | ✔️ | ✔️ 935 | virtual call in constructor helper | ✔️ | ✔️ | ✔️ 936 | virtual call in constructor link | ✔️ | ✔️ | ✔️ 937 | virtual call in destructor | ✔️ | ✔️ | ✔️ 938 | virtual call in destructor helper | ✔️ | ✔️ | ✔️ 939 | virtual call in destructor link | ✔️ | ✔️ | ✔️ 940 | 941 | ### 3.2.2.Extra Dynamic Analysis Summary Gcc 942 | Debug (unoptimized) / RelWithDebInfo (optimized) 943 | 944 | Undefined Behavior Type | address | address,leak,undefined | leak | undefined | valgrind 945 | --- |--- |--- |--- |--- | --- 946 | access after realloc | ✔️ | ✔️ | ❌ | ❌ | ✔️ 947 | array out of bounds | ✔️ | ✔️ | ❌ | ❌/✔️ | ❌ 948 | automatic variable over stack | ✔️ | ✔️ | ✔️/❌ | ✔️ | ✔️/❌ 949 | bad alignment | ❌ | ✔️ | ❌ | ❌ | ❌ 950 | bad identifier name | ❌ | ❌ | ❌ | ❌ | ❌ 951 | delete incomplete type | ❌ | ❌ | ❌ | ❌ | ❌ 952 | dereferencing nullptr | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 953 | divide by zero | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 954 | initialize std string with nullptr | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 955 | large double to int | ❌ | ❌ | ❌ | ❌ | ❌ 956 | malloc cast pod struct | ❌ | ❌ | ❌ | ❌ | ❌ 957 | mutate const value | ❌ | ❌ | ❌ | ❌ | ❌ 958 | odr violation function | ❌ | ❌ | ❌ | ❌ | ❌ 959 | odr violation struct ret | ❌ | ❌ | ❌ | ❌ | ❌ 960 | operator star on empty optional | ❌ | ❌ | ❌ | ❌ | ❌ 961 | out of bounds pointer | ❌ | ❌ | ❌ | ❌ | ❌ 962 | preincrement plus postincrement | ❌ | ❌ | ❌ | ❌ | ❌ 963 | preincrement plus value | ❌ | ❌ | ❌ | ❌ | ❌ 964 | read from old type | ❌ | ✔️ | ❌ | ✔️ | ❌ 965 | reading uninitialized value add | ❌ | ❌ | ❌ | ❌ | ✔️/❌ 966 | reading uninitialized value cout | ❌ | ❌ | ❌ | ❌ | ✔️/❌ 967 | reading uninitialized value func arg | ✔️ | ✔️ | ❌/✔️ | ❌/✔️ | ✔️ 968 | reading uninitialized value if | ❌ | ❌ | ❌ | ❌ | ✔️/❌ 969 | reading uninitialized value lib call cref | ❌ | ❌ | ❌ | ❌ | ✔️ 970 | reading uninitialized value partial | ❌ | ❌ | ❌ | ❌ | ✔️/❌ 971 | reading uninitialized value printf | ❌ | ❌ | ❌ | ❌ | ✔️/❌ 972 | reading uninitialized value return | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 973 | reference out of scope | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 974 | reinterpret cast bad size | ✔️ | ✔️ | ❌ | ✔️ | ❌/✔️ 975 | reinterpret cast float to int32 | ❌ | ❌ | ❌ | ❌ | ❌ 976 | reinterpret cast int32 to float | ❌ | ❌ | ❌ | ❌ | ❌ 977 | reinterpret cast int32 to uint32 | ❌ | ❌ | ❌ | ❌ | ❌ 978 | reinterpret cast uint32 to int32 | ❌ | ❌ | ❌ | ❌ | ❌ 979 | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | ❌ | ❌ | ❌ 980 | shifting more than width | ❌ | ✔️ | ❌ | ✔️ | ❌ 981 | signed integer overflow | ❌ | ✔️ | ❌ | ✔️ | ❌ 982 | sort comp reflexive | ❌ | ❌ | ❌ | ❌ | ❌ 983 | stack overflow | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 984 | std vector reserve set read | ❌ | ❌ | ❌ | ❌ | ❌ 985 | strptime mktime unitialized | ❌ | ❌ | ❌ | ❌ | ✔️ 986 | virtual call in constructor | n/a | n/a | n/a | n/a | n/a 987 | virtual call in constructor helper | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 988 | virtual call in constructor link | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 989 | virtual call in destructor | n/a | n/a | n/a | n/a | n/a 990 | virtual call in destructor helper | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 991 | virtual call in destructor link | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ 992 | 993 | 994 | ### 4.Overall Summary 995 | Undefined Behavior Type | Compiler Warning | Standalone Static Analysis | Runtime Crash | Extra Dynamic Analsyis 996 | --- | --- | --- | --- | --- 997 | access after realloc | ✔️ | ✔️ | ❌ | ✔️ 998 | array out of bounds | ✔️ | ✔️ | ✔️ | ✔️ 999 | automatic variable over stack | ❌ | ❌ | ✔️ | ✔️ 1000 | bad alignment | ❌ | ❌ | ❌ | ✔️ 1001 | bad identifier name | ❌ | ✔️ | ❌ | ❌ 1002 | delete incomplete type | ✔️ | ✔️ | ❌ | ❌ 1003 | dereferencing nullptr | ❌ | ✔️ | ✔️ | ✔️ 1004 | divide by zero | ✔️ | ✔️ | ✔️ | ✔️ 1005 | initialize std string with nullptr | ❌ | ✔️ | ✔️ | ✔️ 1006 | large double to int | ❌ | ❌ | ❌ | ✔️ 1007 | malloc cast pod struct | ❌ | ❌ | ❌ | ❌ 1008 | mutate const value | ❌ | ✔️ | ❌ | ❌ 1009 | non trivial destructor and global | ❌ | ❌ | n/a | n/a 1010 | odr violation function | ❌ | ✔️ | ❌ | ❌ 1011 | odr violation function lib | ❌ | ❌ | n/a | n/a 1012 | odr violation struct ret | ❌ | ✔️ | ❌ | ❌ 1013 | odr violation struct ret lib | ❌ | ❌ | n/a | n/a 1014 | operator star on empty optional | ❌ | ✔️ | ✔️ | ❌ 1015 | out of bounds pointer | ✔️ | ❌ | ❌ | ❌ 1016 | preincrement plus postincrement | ✔️ | ✔️ | ❌ | ❌ 1017 | preincrement plus value | ✔️ | ✔️ | ❌ | ❌ 1018 | read from old type | ❌ | ❌ | ❌ | ✔️ 1019 | reading uninitialized value add | ✔️ | ✔️ | ✔️ | ✔️ 1020 | reading uninitialized value cout | ✔️ | ✔️ | ✔️ | ✔️ 1021 | reading uninitialized value func arg | ✔️ | ✔️ | ✔️ | ✔️ 1022 | reading uninitialized value if | ✔️ | ✔️ | ✔️ | ✔️ 1023 | reading uninitialized value lib call cref | ✔️ | ✔️ | ❌ | ✔️ 1024 | reading uninitialized value partial | ❌ | ✔️ | ✔️ | ✔️ 1025 | reading uninitialized value printf | ✔️ | ✔️ | ✔️ | ✔️ 1026 | reading uninitialized value return | ✔️ | ✔️ | ✔️ | ✔️ 1027 | reference out of scope | ✔️ | ✔️ | ✔️ | ✔️ 1028 | reinterpret cast bad size | ✔️ | ❌ | ❌ | ✔️ 1029 | reinterpret cast float to int32 | ✔️ | ❌ | ❌ | ❌ 1030 | reinterpret cast int32 to float | ✔️ | ❌ | ❌ | ❌ 1031 | reinterpret cast int32 to uint32 | ❌ | ❌ | ❌ | ❌ 1032 | reinterpret cast uint32 to int32 | ❌ | ❌ | ❌ | ❌ 1033 | reinterpret cast unaligned bytes to uint32 | ❌ | ❌ | ❌ | ❌ 1034 | shifting more than width | ✔️ | ✔️ | ❌ | ✔️ 1035 | signed integer overflow | ❌ | ❌ | ❌ | ✔️ 1036 | sort comp reflexive | ❌ | ❌ | ❌ | ❌ 1037 | stack overflow | ✔️ | ✔️ | ✔️ | ✔️ 1038 | std vector reserve set read | ❌ | ✔️ | ✔️ | ❌ 1039 | strptime mktime unitialized | ❌ | ✔️ | ❌ | ✔️ 1040 | virtual call in constructor | ✔️ | ✔️ | ✔️ | ✔️ 1041 | virtual call in constructor helper | ❌ | ✔️ | ✔️ | ✔️ 1042 | virtual call in constructor lib | ❌ | ✔️ | n/a | n/a 1043 | virtual call in constructor link | ❌ | ❌ | ✔️ | ✔️ 1044 | virtual call in destructor | ✔️ | ✔️ | ✔️ | ✔️ 1045 | virtual call in destructor helper | ❌ | ✔️ | ✔️ | ✔️ 1046 | virtual call in destructor lib | ❌ | ✔️ | n/a | n/a 1047 | virtual call in destructor link | ❌ | ❌ | ✔️ | ✔️ 1048 | 1049 | ## Versions 1050 | - Linux 1b21937069a7 6.5.0-41-generic #41~22.04.2-Ubuntu SMP PREEMPT_DYNAMIC Mon Jun 3 11:32:55 UTC 2 x86_64 x86_64 x86_64 GNU/Linux 1051 | - Ubuntu clang version 18.1.3 (1ubuntu1) 1052 | - clang-tidy: 18.1.3 1053 | - Cppcheck 2.13.0 1054 | - gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0 1055 | - GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu) 1056 | - GNU parallel 20231122 1057 | - MSVC: 2022 MSVC 19.40.33811.0 1058 | - Python 3.12.3 1059 | - valgrind-3.22.0 1060 | - Windows SDK version 10.0.22621.0 to target Windows 10.0.17763. 1061 | 1062 | ## Reference Warning Classes 1063 | Compiler | Name | Code | Class 1064 | --- | --- | --- | --- 1065 | clang | divide by zero | division-by-zero | default 1066 | clang | infinite recursion | infinite-recursion | Most 1067 | clang | most | Most | all 1068 | clang | shift count overflow | shift-count-overflow | default 1069 | clang | uninitialized | uninitialized | Most 1070 | clang | return type| return-type | Most 1071 | gcc | delete incomplete | delete-incomplete | default 1072 | gcc | divide by zero | div-by-zero | default 1073 | gcc | shift count overflow | shift-count-overflow | extra 1074 | gcc | strict aliasing | strict-aliasing | all 1075 | gcc | return type | return-type | all 1076 | gcc | uninitialized | uninitialized | all 1077 | MSVC | divide by zero | 4723 | W3 1078 | MSVC | uninitialized | 4700 | W1 1079 | MSVC | stack overflow | 4717 | W1 1080 | MSVC | shift count overflow | 4293 | W1 1081 | MSVC | truncation of constant value | 4309 | W2 1082 | 1083 | ## Notes 1084 | Valgrind was run on GCC compiled binaries. msan, asan, and ubsan are all different flags into clang's "fsanatize" parameter. 1085 | 1086 | Passing means the process halted with a non zero error code. Tests were on intel x86\_64. MSVC was tested on Windows 10 and the rest was tested on Ubuntu 20.04. Debug mode and RelWithDebInfo is in reference to CMake's build types. 1087 | 1088 | There is only one case of each type. It's expected that slightly different implementations of the same types of undefined behavior may yield different results. Multiple runs were not performed consistently for statistical purposes. 1089 | 1090 | There were a few other static analyzers, but they didn't seem appropriate for these problems. I tried OCLint version 0.13.1, but it didn't provide any additional insights besides compiler warnings in regards to undefined behavior. It did warn about short variable names. I also tried cppclean 0.12. It wasn't able to identify undefined behavior issues. It was able to find static data, which is in the stack overflow code by design. 1091 | 1092 | It's recommended for clang-tidy to have a compile database. If it doesn't it will not detect certain errors. For example, it wouldn't detect the stack overflow error. 1093 | 1094 | ## Analysis 1095 | When in debug mode, MSVC halted on the most undefined behavior. Clang and GCC both benefited with the additional "-Wall" flag to catch undefined behavior as warnings. No extra flags made MSVC catch more undefined behavior. 1096 | 1097 | Valgrind caught a few more cases of undefined behavior over running the programs directly. The additional cases were reading uninitialized values and dereferencing an array out of its bounds. It did provide more actionable messages than just "seg fault." Clang with "-fsanitize=undefined" performed much better in RelWithDebInfo mode over just Debug mode. It caught all types but reading from an uninitialized value and out of bounds pointer. 1098 | 1099 | asan was able to identify the array out of bounds error over the undefined option, but didn't detect other use cases. Once the optimizer works, the address sanitizer is not effective at detecting undefined behavior. Pairing it with ubsan combined the best of both tools. 1100 | 1101 | msan was similar to asan, except it didn't identify any new cases. It also benefited from pairing up with ubsan, but ubsan by itself was good enough. 1102 | 1103 | Reading from an uninitialized value is a very common mistake for beginners and experts. Compilers sometimes catch it as warnings. Valgrind can detect it, but clang with fsantize can often miss it. 1104 | 1105 | ## Updates 1106 | ### 2022/07/25 1107 | clang 10->14 1108 | undefined behavior | new check 1109 | ------------------ | --------- 1110 | reading uninitialized value lib call cref | -Wuninitialized-const-reference 1111 | 1112 | gcc 9.3->11.2 1113 | undefined behavior | new check 1114 | ------------------ | --------- 1115 | array out of bounds | -Warray-bounds 1116 | out of bound pointer | -Warray-bounds 1117 | reading uninitialized value lib call cref | -Wmaybe-uninitialized 1118 | type pun cast same line | -Wuninitialized 1119 | type pun cast two lines | -Wuninitialized 1120 | 1121 | clang-tidy 10->14 1122 | undefined behavior | new check 1123 | ------------------ | --------- 1124 | bad identifier name | bugprone-reserved-identifier 1125 | reading uninitialized value lib call cref | clang-diagnostic-uninitialized-const-reference 1126 | 1127 | cppcheck 1.9->2.7 1128 | undefined behavior | new check 1129 | ------------------ | --------- 1130 | odr violation struct ret | ctuOneDefinitionRuleViolation 1131 | reading uninitialized value return | missingReturn 1132 | std vector reserve set read | containerOutOfBounds 1133 | 1134 | 1135 | ### 2024/07/06 1136 | gcc 11.2.0->13.2.0 1137 | undefined behavior | new check 1138 | ------------------ | --------- 1139 | access after realloc | -Wuse-after-free 1140 | stack overflow | -Winfinite-recursion 1141 | 1142 | clang-tidy 14.0 -> 18.1.3 1143 | undefined behavior | new check 1144 | ------------------ | --------- 1145 | odr violation function | misc-include-cleaner* 1146 | odr violation struct ret | misc-include-cleaner* 1147 | operator star on empty optional | bugprone-unchecked-optional-access 1148 | 1149 | *misc-include-cleaner doesn't really call out the ODR violation, but it is a strong indicator. 1150 | 1151 | Clang's memory sanitizer removed. Its results were similar to address. Also, the results were questionable, since it didn't work with a memory compiled standard library. 1152 | 1153 | The type pun examples were changed to reinterpret cast ones. There are more examples to stress that the standard has strict requirements on reinterpret cast. Still most of them aren't checked. 1154 | 1155 | ## Variability 1156 | Valgrind seems to have different results over time. This may be due to version upgrades from 3.11 to 1.13 or the very nature of undefined behavior itself. It was observed that array out of bounds was undetected by valgrind during the upgrade. Not detecting uninitialized memory in release with debug info went undetected at some point later. 1157 | --------------------------------------------------------------------------------