├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.TXT ├── README.md ├── WishList.md ├── include ├── CMakeLists.txt ├── _builtin_common.h ├── _builtin_stdio_checked.h ├── _builtin_string_checked.h ├── arpa │ ├── inet.h │ └── inet_checked.h ├── assert.h ├── assert_checked.h ├── checkedc_extensions.h ├── crypt.h ├── crypt_checked.h ├── dirent.h ├── dirent_checked.h ├── errno.h ├── errno_checked.h ├── fcntl.h ├── fcntl_checked.h ├── fenv.h ├── fenv_checked.h ├── grp.h ├── grp_checked.h ├── inttypes_checked.h ├── inttypes_checked_internal.h ├── math.h ├── math_checked.h ├── netdb.h ├── netdb_checked.h ├── poll.h ├── poll_checked.h ├── pwd.h ├── pwd_checked.h ├── shadow.h ├── shadow_checked.h ├── signal.h ├── signal_checked.h ├── stdchecked.h ├── stdio.h ├── stdio_checked.h ├── stdlib.h ├── stdlib_checked.h ├── string.h ├── string_checked.h ├── sys │ ├── mman.h │ ├── mman_checked.h │ ├── resource.h │ ├── resource_checked.h │ ├── select.h │ ├── select_checked.h │ ├── socket.h │ ├── socket_checked.h │ ├── stat.h │ ├── stat_checked.h │ ├── time.h │ ├── time_checked.h │ ├── wait.h │ └── wait_checked.h ├── syslog.h ├── syslog_checked.h ├── threads.h ├── threads_checked.h ├── time.h ├── time_checked.h ├── unistd.h ├── unistd_checked.h ├── utime.h └── utime_checked.h ├── papers └── dynamic_checks │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── abstract.tex │ ├── c_syntax.tex │ ├── checked_c.sty │ ├── checkedc.bib │ ├── checks.tex │ ├── conclusion.tex │ ├── evaluation.tex │ ├── example.tex │ ├── grammars │ └── lvalue-expressions.tex │ ├── hyperendnotes.sty │ ├── introduction.tex │ ├── listing-label.sty │ ├── overview.tex │ ├── propagation.tex │ ├── propagation_rules.tex │ ├── related_work.tex │ ├── scripts │ ├── Makefile │ ├── bm_res.csv │ ├── bm_res.r │ ├── bm_res_install.r │ ├── bm_results_macros.tex │ ├── bm_results_tab.tex │ ├── modifications.pdf │ └── overheads.pdf │ ├── tables │ ├── bmdesc.tex │ ├── bmresults.tex │ └── canonical.tex │ └── tr02.tex ├── presentations ├── Checked-C-UW-PLSE-Workshop'-Final.pdf ├── Checked-C-UW-PLSE-Workshop-Final.pptx ├── checkedc-presentation.pptx ├── llvmdevmeet2019-checkedc_for_memory_safety.pdf └── llvmdevmeet2020-checkedc_adding_memory_safety_to_llvm.pdf ├── samples ├── README.md ├── avoid-warning.c ├── echo-args-buggy.c ├── echo-args.c ├── exit-on-failure.c ├── find-pattern.c ├── hello-world.c ├── spec │ ├── 2_3_1_add.c │ ├── 2_7_checked.c │ ├── 2_8_append.c │ ├── 3_11_compare.c │ ├── 3_11_sum.c │ ├── 3_2_1_add.c │ ├── 3_2_1_find.c │ ├── 3_2_1_sum.c │ ├── 3_2_1_sum_extern.c │ ├── 3_2_2_find.c │ ├── 3_4_array_ptr.c │ └── 3_4_ptr.c └── string-helpers.c ├── spec ├── .gitignore └── bounds_safety │ ├── README.md │ ├── abstract.tex │ ├── bounds-declarations.tex │ ├── changelog.tex │ ├── checkedc.tex │ ├── checking-variable-bounds.tex │ ├── core-extensions.tex │ ├── design-alternatives.tex │ ├── fragments.tex │ ├── interoperation.tex │ ├── introduction.tex │ ├── lessons.tex │ ├── makefile │ ├── pictures │ ├── build-pics.tex │ └── rel-align-picture1.tex │ ├── related-work.tex │ ├── roadmap.tex │ ├── simple-invariants.tex │ ├── sources.bib │ ├── span-compilation.tex │ └── void-ptr-replacements.tex └── tests ├── checked_headers ├── redeclare_libs_explicit.c ├── redeclare_libs_explicit_linux.c ├── redeclare_libs_implicit.c ├── redeclare_libs_implicit_linux.c ├── redeclare_libs_mixed.c └── redeclare_libs_mixed_linux.c ├── dynamic_checking ├── README.md ├── bounds │ ├── array-bounds-decls.c │ ├── bounds-safe-interfaces.c │ ├── deref.c │ ├── deref_arith.c │ ├── deref_arith_call_expr.c │ ├── deref_arith_call_expr_opt.c │ ├── deref_arith_opt.c │ ├── deref_arrow_member_expr.c │ ├── deref_arrow_member_expr_opt.c │ ├── deref_dot_member_expr.c │ ├── deref_dot_member_expr_opt.c │ ├── deref_opt.c │ ├── nullterm_pointers.c │ ├── predefined_literals.c │ ├── subscript.c │ ├── subscript_arrow_member_expr.c │ ├── subscript_arrow_member_expr_opt.c │ ├── subscript_call_expr.c │ ├── subscript_call_expr_bsi.c │ ├── subscript_call_expr_opt.c │ ├── subscript_dot_member_expr.c │ ├── subscript_dot_member_expr_opt.c │ └── subscript_opt.c ├── checked_headers │ └── ext.c ├── dynamic-bounds-cast-check.c ├── dynamic_check │ ├── arith-fail.c │ ├── arith-pass.c │ ├── simple-fail.c │ └── simple-pass.c └── null_ptr_checks │ └── ptr-arith.c ├── exist_types_runtest ├── callbacks.c └── counters.c ├── parsing ├── checked_array_types.c ├── declaration_bounds.c ├── interop_and_bounds.c ├── interop_types.c ├── member_bounds.c ├── parameter_bounds.c ├── pointer-larger-int │ ├── lit.local.cfg │ └── member_bounds.c ├── pointer_bounds_cast.c ├── pointer_types.c ├── rel_align.c ├── return_bounds.c └── typevariable │ ├── forany_parsing.c │ ├── forany_parsing_error.c │ ├── generic_func_parsing.c │ └── generic_func_parsing_error.c ├── runtime_operations ├── README.md └── assignments.c ├── static_checking ├── address_of.c ├── bounds_decl_checking.c ├── bundled_statements.c ├── initializers.c ├── lexical_equality.c ├── nme_bounds.c ├── returns │ ├── falloff1.c │ ├── falloff2.c │ ├── falloff3.c │ ├── falloff4.c │ ├── falloff5.c │ ├── falloff6.c │ ├── falloff7.c │ ├── falloff8.c │ └── funcbody.c └── static_check_bounds_cast.c └── typechecking ├── bounds.c ├── checked_arrays.c ├── checked_scope_basic.c ├── checked_scope_bounds_only.c ├── checked_scope_interfaces.c ├── checked_scope_pragma.c ├── checked_scope_pragma_bounds_only.c ├── errno-use.c ├── existential_structs.c ├── function_casts.c ├── generic_functions.c ├── generic_structs.c ├── generic_type_arguments.c ├── interop.c ├── interop_type_annotations.c ├── itype_generic_functions.c ├── itype_generic_structs.c ├── malloc_free.c ├── no_prototype_functions.c ├── pointer-larger-int ├── bounds.c └── lit.local.cfg ├── pointer-larger-long ├── bounds.c └── lit.local.cfg ├── pointer-sized-long-long ├── function_casts.c ├── lit.local.cfg └── pointer_casts.c ├── pointer-sized-long ├── function_casts.c ├── lit.local.cfg └── pointer_casts.c ├── pointer_types.c ├── redeclarations.c ├── static_variables_free_type_variables.c └── type_check_bounds_cast.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | *.exe 3 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | Checked C Test and Sample Code 2 | Copyright (c) Microsoft Corporation 3 | All rights reserved. 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /WishList.md: -------------------------------------------------------------------------------- 1 | # A Wish List of Checked C Projects. 2 | 3 | There is plenty of work to do on Checked C. Here is a list of projects 4 | that could be begun now or in the next few months. The projects cover compiler 5 | implementation, tools, language design, and experimental evaluation. The 6 | projects range in nature from implementation to design to open research 7 | problems. If you decide to work on a project, it would be helpful to let us 8 | know so that we can try to coordinate work among interested parties. 9 | 10 | # Compiler implementation 11 | 12 | Here are projects for the LLVM/clang implementation of Checked C. Some 13 | projects could be begun now. Others will need to wait until bounds declarations 14 | are added to the clang AST. 15 | 16 | - Nightly build automation and build testing. 17 | - Pointer arithmetic for checked pointers types that has overflow checking. 18 | - Non-null checks for checked pointer types. 19 | - Span pointer types: parsing, representation in IR, typechecking, and 20 | implementation of operations. 21 | - Insert runtime bounds checks during the lowering to LLVM IR. 22 | - Enforce the rule in Section 3.2 that all uses of externally-scoped variables 23 | within a compilation unit have the same view of the bounds for the variable. 24 | - Bounds-safe interfaces for functions and static variables: 25 | -- Parsing of interoperation annotations for unchecked pointer types. 26 | -- Insertion of implicit type coercions between checked and unchecked pointer 27 | types. 28 | -- Compatibility between declarations with and without bounds information. 29 | -- Checks that there are no intervening definitions. 30 | - Checked/unchecked blocks. 31 | - Bounds declarations for structure types and structure member operations. 32 | 33 | Another interesting direction is to begin implementing Checked C in other 34 | compilers such as GCC. 35 | 36 | # Tools 37 | 38 | - Create tools that modify existing C code to use features in Checked C. One possible project 39 | is to build a tool that identifies pointers that are never used with pointer arithmetic 40 | and convert them to _ptr_. We have implemented typechecking for the _ptr_ type in LLVM/clang, 41 | so the typechecking rules for _ptr_ would be enforced. 42 | 43 | # Experimental evaluation 44 | 45 | - Try applying Checked C to additional code bases. We are experimenting with OpenSSL. 46 | It would be useful to gather experiences with other code bases, which will have 47 | different coding styles and address other problem domains. 48 | 49 | # Language design 50 | 51 | - Extend the Checked C design to describe null-terminated array types. 52 | - Extend the C language definition notion of compatibility to declarations 53 | with and without bounds information. This would allow bounds-safe 54 | interfaces to be declared for C standard library functions, without 55 | modifying the source code for existing headers. 56 | - Add a way to describe that aliasing (or anti-aliasing) properties of data 57 | structures. This would allow bounds invariants to be suspended for certain 58 | data during function calls. 59 | - Ways to check the correct use of the following memory management strategies 60 | used in C programs: 61 | -- Stack allocation. 62 | -- Reference counting 63 | -- Regions. 64 | - A design for checking the correctness of explicit memory management 65 | strategies. 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeList.txt used by the Checked C version of clang/LLVM. 2 | # This copies the Checked C header files to the system header 3 | # directory for clang so that they can easily be found/used. 4 | # 5 | # Checked C does not require runtime system changes, and it would 6 | # be unnecesarily heavyweight to require people to pick up a new 7 | # library just to get the Checked C include wrpaper files. 8 | # So we place the header files with the compiler. 9 | 10 | set(files 11 | assert_checked.h 12 | assert.h 13 | crypt_checked.h 14 | crypt.h 15 | dirent_checked.h 16 | dirent.h 17 | errno_checked.h 18 | errno.h 19 | fcntl.h 20 | fcntl_checked.h 21 | fenv_checked.h 22 | fenv.h 23 | grp_checked.h 24 | grp.h 25 | inttypes_checked.h 26 | inttypes_checked_internal.h 27 | math_checked.h 28 | math.h 29 | netdb_checked.h 30 | netdb.h 31 | poll_checked.h 32 | poll.h 33 | pwd_checked.h 34 | pwd.h 35 | shadow_checked.h 36 | shadow.h 37 | signal_checked.h 38 | signal.h 39 | stdchecked.h 40 | stdio_checked.h 41 | stdio.h 42 | stdlib_checked.h 43 | stdlib.h 44 | string_checked.h 45 | string.h 46 | syslog_checked.h 47 | syslog.h 48 | threads_checked.h 49 | threads.h 50 | utime_checked.h 51 | utime.h 52 | time_checked.h 53 | time.h 54 | unistd_checked.h 55 | unistd.h 56 | _builtin_stdio_checked.h 57 | _builtin_string_checked.h 58 | _builtin_common.h 59 | checkedc_extensions.h 60 | ) 61 | 62 | set(posix_arpa_files 63 | arpa/inet_checked.h 64 | arpa/inet.h 65 | ) 66 | 67 | set(posix_sys_files 68 | sys/mman_checked.h 69 | sys/mman.h 70 | sys/resource_checked.h 71 | sys/resource.h 72 | sys/select_checked.h 73 | sys/select.h 74 | sys/socket_checked.h 75 | sys/socket.h 76 | sys/stat_checked.h 77 | sys/stat.h 78 | sys/time_checked.h 79 | sys/time.h 80 | sys/wait_checked.h 81 | sys/wait.h 82 | ) 83 | 84 | # Hack - compute the CLANG version from the LLVM version. The 85 | # CLANG_VERSION variable is not available at this point during the build. 86 | 87 | string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CHECKEDC_CLANG_VERSION 88 | ${PACKAGE_VERSION}) 89 | 90 | set(output_dir ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CHECKEDC_CLANG_VERSION}/include) 91 | 92 | set(out_files) 93 | foreach( f ${files} ${posix_arpa_files} ${posix_sys_files} ) 94 | set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} ) 95 | set( dst ${output_dir}/${f} ) 96 | add_custom_command(OUTPUT ${dst} 97 | DEPENDS ${src} 98 | COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} 99 | COMMENT "Copying Checked C's ${f}...") 100 | list(APPEND out_files ${dst}) 101 | endforeach( f ) 102 | 103 | add_custom_target(checkedc-headers ALL DEPENDS ${out_files}) 104 | set_target_properties(checkedc-headers PROPERTIES FOLDER "Misc") 105 | 106 | install( 107 | FILES ${files} 108 | COMPONENT checkedc-headers 109 | PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ 110 | DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CHECKEDC_CLANG_VERSION}/include 111 | ) 112 | 113 | install( 114 | FILES ${posix_arpa_files} 115 | COMPONENT checkedc-headers 116 | PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ 117 | DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CHECKEDC_CLANG_VERSION}/include/arpa 118 | ) 119 | 120 | install( 121 | FILES ${posix_sys_files} 122 | COMPONENT checkedc-headers 123 | PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ 124 | DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CHECKEDC_CLANG_VERSION}/include/sys 125 | ) 126 | 127 | if (NOT CMAKE_CONFIGURATION_TYPES) # don't add this for IDE's. 128 | add_custom_target(install-checkedc-headers 129 | DEPENDS checkedc-headers 130 | COMMAND "${CMAKE_COMMAND}" 131 | -DCMAKE_INSTALL_COMPONENT=checkedc-headers 132 | -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") 133 | endif() 134 | -------------------------------------------------------------------------------- /include/_builtin_common.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for compiler-defined builtin functions // 3 | // corresponding to secure/_common.h functions // 4 | // // 5 | // These are given in the order they appear in clang's Builtins.def. // 6 | // Functions that do not appear can not have checked interfaces // 7 | // defined. // 8 | // // 9 | // These are based on the types as declared within clang // 10 | // and https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html // 11 | ///////////////////////////////////////////////////////////////////////// 12 | 13 | #ifndef __has_builtin 14 | #define _undef__has_builtin 15 | #define __has_builtin(x) 0 16 | #endif 17 | 18 | #if __has_builtin(__builtin_object_size) 19 | size_t __builtin_object_size(const void* obj : itype(_Array_ptr), 20 | int i); 21 | #endif 22 | 23 | #ifdef _undef__has_builtin 24 | #undef _undef__has_builtin 25 | #undef __has_builtin 26 | #endif 27 | -------------------------------------------------------------------------------- /include/_builtin_string_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for compiler-defined builtin functions // 3 | // corresponding to string.h functions // 4 | // // 5 | // These are given in the order they appear in clang's Builtins.def. // 6 | // Functions that do not appear can not have checked interfaces // 7 | // defined. // 8 | // // 9 | // These are based on the types as declared within clang // 10 | // and https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html // 11 | ///////////////////////////////////////////////////////////////////////// 12 | 13 | #include "_builtin_common.h" 14 | 15 | #if _USE_FORTIFY_LEVEL > 0 16 | 17 | #ifndef __has_builtin 18 | #define _undef__has_builtin 19 | #define __has_builtin(x) 0 20 | #endif 21 | 22 | #if __has_builtin(__builtin___memcpy_chk) || defined(__GNUC__) 23 | void *__builtin___memcpy_chk(void * restrict dest : byte_count(n), 24 | const void * restrict src : byte_count(n), 25 | size_t n, 26 | size_t obj_size) : bounds(dest, (_Array_ptr) dest + n); 27 | #endif 28 | 29 | #if __has_builtin(__builtin___memmove_chk) || defined(__GNUC__) 30 | void *__builtin___memmove_chk(void * restrict dest : byte_count(n), 31 | const void * restrict src : byte_count(n), 32 | size_t n, 33 | size_t obj_size) : bounds(dest, (_Array_ptr)dest + n); 34 | #endif 35 | 36 | #if __has_builtin(__builtin___memset_chk) || defined(__GNUC__) 37 | void *__builtin___memset_chk(void * s : byte_count(n), 38 | int c, 39 | size_t n, 40 | size_t obj_size) : bounds(s, (_Array_ptr) s + n); 41 | #endif 42 | 43 | #if __has_builtin(__builtin___strcat_chk) || defined(__GNUC__) 44 | // Left Unchecked Intentionally. See comment in string_checked.h 45 | _Unchecked 46 | char *__builtin___strcat_chk(char * restrict dest, 47 | const char * restrict src : 48 | itype(restrict _Nt_array_ptr), 49 | size_t obj_size); 50 | #endif 51 | 52 | #if __has_builtin(__builtin___strcpy_chk) || defined(__GNUC__) 53 | // Left Unchecked Intentionally. See comment in string_checked.h 54 | _Unchecked 55 | char *__builtin___strcpy_chk(char * restrict dest, 56 | const char * restrict src : 57 | itype(restrict _Nt_array_ptr), 58 | size_t obj_size); 59 | #endif 60 | 61 | #if __has_builtin(__builtin___strncat_chk) || defined(__GNUC__) 62 | // TODO: we have no way to express the bounds requirement on dest, 63 | // which needs to be count(strlen(dest) + n). 64 | _Unchecked 65 | char *__builtin___strncat_chk(char * restrict dest, 66 | const char * restrict src : count(n), 67 | size_t n, 68 | size_t obj_size); 69 | #endif 70 | 71 | #if __has_builtin(__builtin___strncpy_chk) || defined(__GNUC__) 72 | char *__builtin___strncpy_chk(char * restrict dest : count(n), 73 | const char * restrict src : count(n), 74 | size_t n, 75 | size_t obj_size) : bounds(dest, (_Array_ptr)dest + n); 76 | #endif 77 | 78 | #ifdef _undef__has_builtin 79 | #undef _undef__has_builtin 80 | #undef __has_builtin 81 | #endif 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /include/arpa/inet.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have arpa/inet.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have arpa/inet.h 29 | #error "cannot include 'arpa/inet.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/arpa/inet_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for some functions in arpa/inet.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are POSIX-only // 6 | ///////////////////////////////////////////////////////////////////////// 7 | 8 | // The Windows environment may not have arpa/inet.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #ifdef __checkedc 12 | #pragma CHECKED_SCOPE push 13 | #pragma CHECKED_SCOPE off 14 | #endif 15 | 16 | #include_next 17 | 18 | #ifdef __checkedc 19 | #pragma CHECKED_SCOPE pop 20 | #endif 21 | 22 | #ifdef __checkedc 23 | #ifndef __INET_CHECKED_H 24 | #define __INET_CHECKED_H 25 | 26 | #pragma CHECKED_SCOPE push 27 | #pragma CHECKED_SCOPE on 28 | 29 | extern in_addr_t inet_addr (const char *__cp : itype(_Nt_array_ptr)) __THROW; 30 | extern int inet_aton(const char *cp : itype(_Nt_array_ptr), 31 | struct in_addr *inp : itype(_Ptr)); 32 | 33 | extern char *inet_ntoa(struct in_addr) : itype(_Nt_array_ptr); 34 | extern const char *inet_ntop(int af, 35 | const void *restrict src : byte_count(af == AF_INET ? 4 : 16), 36 | char *restrict dst : itype(restrict _Nt_array_ptr) count(size-1), 37 | socklen_t size _Where size > 0) 38 | : itype(_Nt_array_ptr); 39 | extern int inet_pton(int af, 40 | const char *restrict src : itype(restrict _Nt_array_ptr), 41 | void *restrict dst : byte_count(af == AF_INET ? 4 : 16)); 42 | 43 | #pragma CHECKED_SCOPE pop 44 | 45 | #endif // guard 46 | #endif // Checked C 47 | 48 | #else // doesn't have arpa/inet.h 49 | #error "cannot include 'arpa/inet_checked.h' because this system does not have the original 'arpa/inet.h'" 50 | #endif 51 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/assert_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for some functions in assert.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | #include // define wchar_t for wcstoimax and wcstoumax 14 | 15 | #ifdef __checkedc 16 | #pragma CHECKED_SCOPE pop 17 | #endif 18 | 19 | #ifdef __checkedc 20 | #ifndef __ASSERT_CHECKED_H 21 | #define __ASSERT_CHECKED_H 22 | 23 | #pragma CHECKED_SCOPE push 24 | #pragma CHECKED_SCOPE on 25 | 26 | #if defined(_WIN32) || defined(_WIN64) 27 | _ACRTIMP void __cdecl _wassert(_In_z_ wchar_t const *_Message : itype(_Nt_array_ptr), 28 | _In_z_ wchar_t const *_File : itype(_Nt_array_ptr), 29 | _In_ unsigned _Line); 30 | #else 31 | 32 | #ifdef __APPLE__ 33 | #define __THROW 34 | extern void __assert_rtn(const char *msg : itype(_Nt_array_ptr), 35 | const char *file : itype(_Nt_array_ptr), 36 | int line, 37 | const char *fn : itype(const char _Nt_checked[])); 38 | #else 39 | extern void __assert(const char *msg : itype(_Nt_array_ptr), 40 | const char *file : itype(_Nt_array_ptr), 41 | int line); 42 | #endif 43 | 44 | #undef __assert_fail 45 | extern void __assert_fail (const char *__assertion : itype(_Nt_array_ptr), const char *__file : itype(_Nt_array_ptr), 46 | unsigned int __line, const char *__function : itype(const char _Nt_checked[])) 47 | __THROW __attribute__ ((__noreturn__)); 48 | 49 | #endif 50 | 51 | #pragma CHECKED_SCOPE pop 52 | 53 | #endif // guard 54 | #endif // Checked C 55 | -------------------------------------------------------------------------------- /include/checkedc_extensions.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | // Additional bounds-safe interface options for functions that have // 3 | // different interfaces for array_ptr and nt_array_ptr args. Programmer can // 4 | // choose to use these over the default bounds-safe interfaces. // 5 | ////////////////////////////////////////////////////////////////////////////// 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef __checkedc 12 | 13 | #ifndef __CHECKED_C_EXTENSIONS_H 14 | #define __CHECKED_C_EXTENSIONS_H 15 | 16 | #pragma CHECKED_SCOPE push 17 | #pragma CHECKED_SCOPE on 18 | 19 | // default strncmp has a bounds-safe interface nt_array_ptr; 20 | // this option is for array_ptr 21 | inline int __attribute__((__always_inline__)) 22 | strncmp_array_ptr(const char *src : count(n), const char *s2 : count(n), size_t n) { 23 | _Unchecked { return strncmp(src, s2, n); } 24 | } 25 | 26 | // default snprintf assumes nt_array_ptr for bounds-safe interface 27 | // this option is for array_ptr 28 | // clang does not inline functions that use va_list/va_start/va_end to 29 | // access variable number of arguments. 30 | _Unchecked static int 31 | snprintf_array_ptr(char * restrict s : itype(restrict _Array_ptr) count(n), 32 | size_t n, 33 | const char * restrict format : itype(restrict _Nt_array_ptr), 34 | ...) { 35 | va_list argptr; 36 | va_start(argptr, format); 37 | // The call to snprintf needs to be in an unchecked block as the compiler, 38 | // in checked scope, will not allow passing an argument of type 39 | // _Array_ptr count(n) whose corresponding parameter has the type 40 | // _Nt_array_ptr count(n-1). 41 | snprintf(s, n, format, argptr); 42 | va_end(argptr); 43 | } 44 | 45 | #pragma CHECKED_SCOPE pop 46 | 47 | #endif // guard 48 | #endif // Checked C 49 | -------------------------------------------------------------------------------- /include/crypt.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // Uses clang-specific __has_include macro to detect unistd.h 9 | // which is required by Posix Standard. 10 | // The Windows environment also may not have unistd.h 11 | #if defined __has_include_next && __has_include_next() 12 | 13 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 14 | 15 | #ifdef __checkedc 16 | #pragma CHECKED_SCOPE push 17 | #pragma CHECKED_SCOPE off 18 | #endif 19 | 20 | #include_next 21 | 22 | #ifdef __checkedc 23 | #pragma CHECKED_SCOPE pop 24 | #endif 25 | 26 | #else // checkedc && implicit include enabled 27 | #include 28 | #endif 29 | 30 | #else // doesn't have unistd.h 31 | #error "cannot include 'crypt.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 32 | #endif 33 | -------------------------------------------------------------------------------- /include/crypt_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in crypt.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __CRYPT_CHECKED_H 20 | #define __CRYPT_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | char * crypt(const char *phrase : itype(_Nt_array_ptr), const char *setting : itype(_Nt_array_ptr)) : itype(_Nt_array_ptr); 26 | 27 | #pragma CHECKED_SCOPE pop 28 | 29 | #endif // guard 30 | #endif // Checked C 31 | -------------------------------------------------------------------------------- /include/dirent.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/dirent_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for some functions in dirent.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __DIRENT_CHECKED_H 20 | #define __DIRENT_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | DIR *opendir(const char *name : itype(_Nt_array_ptr)) : itype(_Ptr); 26 | DIR *fdopendir(int fd) : itype(_Ptr); 27 | int closedir(DIR *dirp : itype(_Ptr)); 28 | struct dirent *readdir(DIR *dirp : itype(_Ptr)) : itype(_Ptr); 29 | int dirfd(DIR *dirp : itype(_Ptr)); 30 | 31 | #pragma CHECKED_SCOPE pop 32 | 33 | #endif // guard 34 | #endif // Checked C 35 | -------------------------------------------------------------------------------- /include/errno.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/errno_checked.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in errno.h // 3 | // // 4 | //////////////////////////////////////////////////////////////////////// 5 | 6 | #ifdef __checkedc 7 | #pragma CHECKED_SCOPE push 8 | #pragma CHECKED_SCOPE off 9 | #endif 10 | 11 | #include_next 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE pop 15 | #endif 16 | 17 | #ifdef __checkedc 18 | #ifndef __ERRNO_CHECKED_H 19 | #define __ERRNO_CHECKED_H 20 | 21 | #pragma CHECKED_SCOPE push 22 | #pragma CHECKED_SCOPE on 23 | 24 | #if defined(_WIN32) || defined(_WIN64) 25 | __declspec(dllimport) int* __cdecl _errno(void) : itype(_Ptr); 26 | #elif defined(__APPLE__) 27 | #if defined(__aarch64__) 28 | extern int * __error(void) : itype(_Ptr); 29 | #else 30 | extern int* __errno_location(void) : itype(_Ptr); 31 | #endif 32 | #else 33 | extern int* __errno_location(void) : itype(_Ptr) __THROW __attribute_const__; 34 | #endif 35 | 36 | #pragma CHECKED_SCOPE pop 37 | 38 | #endif // guards 39 | #endif // Checked C 40 | -------------------------------------------------------------------------------- /include/fcntl.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/fcntl_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for some functions in fcntl.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __FCNTL_CHECKED_H 20 | #define __FCNTL_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | _Unchecked 26 | int open(const char *pathname : itype(_Nt_array_ptr), int flags, ...); 27 | 28 | #pragma CHECKED_SCOPE pop 29 | 30 | #endif // guard 31 | #endif // Checked C 32 | -------------------------------------------------------------------------------- /include/fenv.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/fenv_checked.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in fenv.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are listed in the same order that they occur in the C11 // 6 | // specification. // 7 | //////////////////////////////////////////////////////////////////////// 8 | 9 | #ifdef __checkedc 10 | #pragma CHECKED_SCOPE push 11 | #pragma CHECKED_SCOPE off 12 | #endif 13 | 14 | #include_next 15 | 16 | #ifdef __checkedc 17 | #pragma CHECKED_SCOPE pop 18 | #endif 19 | 20 | #ifdef __checkedc 21 | #ifndef __FENV_CHECKED_H 22 | #define __FENV_CHECKED_H 23 | 24 | #pragma CHECKED_SCOPE push 25 | #pragma CHECKED_SCOPE on 26 | 27 | int fesetexceptflag(const fexcept_t *flagp : itype(_Ptr), 28 | int excepts); 29 | int fegetenv(fenv_t *envp : itype(_Ptr)); 30 | int feholdexcept(fenv_t *envp : itype(_Ptr)); 31 | int fesetenv(const fenv_t *envp : itype(_Ptr)); 32 | int feupdateenv(const fenv_t *envp : itype(_Ptr)); 33 | 34 | #pragma CHECKED_SCOPE pop 35 | 36 | #endif // guard 37 | #endif // Checked C 38 | -------------------------------------------------------------------------------- /include/grp.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have grp.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have grp.h 29 | #error "cannot include 'grp.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/grp_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in grp.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have grp.h 8 | #if defined __has_include_next && __has_include_next() 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #ifdef __checkedc 22 | #ifndef __GRP_CHECKED_H 23 | #define __GRP_CHECKED_H 24 | 25 | #pragma CHECKED_SCOPE push 26 | #pragma CHECKED_SCOPE on 27 | 28 | int initgroups(const char *user : itype(_Nt_array_ptr), gid_t group); 29 | 30 | #pragma CHECKED_SCOPE pop 31 | 32 | #endif // guard 33 | #endif // Checked C 34 | 35 | #else // doesn't have grp.h 36 | #error "cannot include 'grp_checked.h' because this system does not have the original 'grp.h'" 37 | #endif 38 | -------------------------------------------------------------------------------- /include/inttypes_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that includes Checked-C-specific declarations // 3 | // explicitly. // 4 | ///////////////////////////////////////////////////////////////////////// 5 | 6 | 7 | // Ensure that clang-specific declarations are included. 8 | #include 9 | // Ensure that Checked-C-specific declarations are included even if 10 | // implicit inclusion is disabled. 11 | #include 12 | -------------------------------------------------------------------------------- /include/inttypes_checked_internal.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in inttypes.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are listed in the same order that they occur in the C11 // 6 | // specification. // 7 | ///////////////////////////////////////////////////////////////////////// 8 | 9 | #ifdef __checkedc 10 | #pragma CHECKED_SCOPE push 11 | #pragma CHECKED_SCOPE off 12 | #endif 13 | 14 | #include // define wchar_t for wcstoimax and wcstoumax 15 | 16 | #ifdef __checkedc 17 | #pragma CHECKED_SCOPE pop 18 | #endif 19 | 20 | #ifdef __checkedc 21 | #ifndef __INTTYPES_CHECKED_H 22 | #define __INTTYPES_CHECKED_H 23 | 24 | #pragma CHECKED_SCOPE push 25 | #pragma CHECKED_SCOPE on 26 | 27 | _Unchecked 28 | intmax_t strtoimax(const char * restrict nptr : 29 | itype(restrict _Nt_array_ptr), 30 | char ** restrict endptr : 31 | itype(restrict _Ptr<_Nt_array_ptr>), 32 | int base); 33 | _Unchecked 34 | uintmax_t strtoumax(const char * restrict nptr : 35 | itype(restrict _Nt_array_ptr), 36 | char ** restrict endptr : 37 | itype(restrict _Ptr<_Nt_array_ptr>), 38 | int base); 39 | 40 | _Unchecked 41 | intmax_t wcstoimax(const wchar_t * restrict nptr : 42 | itype(restrict _Nt_array_ptr), 43 | wchar_t ** restrict endptr : 44 | itype(restrict _Ptr<_Nt_array_ptr>), 45 | int base); 46 | 47 | _Unchecked 48 | uintmax_t wcstoumax(const wchar_t * restrict nptr : 49 | itype(restrict _Nt_array_ptr), 50 | wchar_t ** restrict endptr : 51 | itype(restrict _Ptr<_Nt_array_ptr>), 52 | int base); 53 | 54 | #pragma CHECKED_SCOPE pop 55 | 56 | #endif // guard 57 | #endif // Checked C 58 | -------------------------------------------------------------------------------- /include/math.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/math_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in math.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are listed in the same order that they occur in the C11 // 6 | // specification. // 7 | ///////////////////////////////////////////////////////////////////////// 8 | 9 | #ifdef __checkedc 10 | #pragma CHECKED_SCOPE push 11 | #pragma CHECKED_SCOPE off 12 | #endif 13 | 14 | #include_next 15 | 16 | #ifdef __checkedc 17 | #pragma CHECKED_SCOPE pop 18 | #endif 19 | 20 | #ifdef __checkedc 21 | #ifndef __MATH_CHECKED_H 22 | #define __MATH_CHECKED_H 23 | 24 | #pragma CHECKED_SCOPE push 25 | #pragma CHECKED_SCOPE on 26 | 27 | double frexp(double value, int *exp : itype(_Ptr)); 28 | float frexpf(float value, int *exp : itype(_Ptr)); 29 | long double frexpl(long double value, int *exp : itype(_Ptr)); 30 | 31 | double modf(double value, double *iptr : itype(_Ptr)); 32 | float modff(float value, float *iptr : itype(_Ptr)); 33 | long double modfl(long double value, 34 | long double *iptr : itype(_Ptr)); 35 | 36 | double remquo(double x, double y, int *quo : itype(_Ptr)); 37 | float remquof(float x, float y, int *quo : itype(_Ptr)); 38 | long double remquol(long double x, long double y, int *quo : itype(_Ptr)); 39 | 40 | double nan(const char *t : itype(_Nt_array_ptr)); 41 | float nanf(const char *t : itype(_Nt_array_ptr)); 42 | long double nanl(const char *t : itype(_Nt_array_ptr)); 43 | 44 | #pragma CHECKED_SCOPE pop 45 | 46 | #endif // guard 47 | #endif // Checked C 48 | -------------------------------------------------------------------------------- /include/netdb.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have netdb.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have netdb.h 29 | #error "cannot include 'netdb.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/netdb_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in netdb.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have netdb.h 8 | #if defined __has_include_next && __has_include_next() 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #ifdef __checkedc 22 | #ifndef __NETDB_CHECKED_H 23 | #define __NETDB_CHECKED_H 24 | 25 | #pragma CHECKED_SCOPE push 26 | #pragma CHECKED_SCOPE on 27 | 28 | extern struct hostent *gethostbyname(const char *name : itype(_Nt_array_ptr)) : itype(_Ptr); 29 | extern struct hostent *gethostbyaddr(const void *addr : byte_count(len), socklen_t len, int type) : itype(_Ptr); 30 | 31 | int getaddrinfo(const char *restrict node : itype(_Nt_array_ptr restrict), 32 | const char *restrict service : itype(_Nt_array_ptr restrict), 33 | const struct addrinfo *restrict hints : itype(_Ptr restrict), 34 | struct addrinfo **restrict res : itype(_Ptr<_Ptr> restrict)); 35 | void freeaddrinfo(struct addrinfo *res : itype(_Ptr)); 36 | const char *gai_strerror(int errcode) : itype(_Nt_array_ptr); 37 | 38 | #pragma CHECKED_SCOPE pop 39 | 40 | #endif // guard 41 | #endif // Checked C 42 | 43 | #else // doesn't have netdb.h 44 | #error "cannot include 'netdb_checked.h' because this system does not have the original 'netdb.h'" 45 | #endif 46 | -------------------------------------------------------------------------------- /include/poll.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have poll.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have poll.h 29 | #error "cannot include 'poll.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/poll_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in poll.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have poll.h 8 | #if defined __has_include_next && __has_include_next() 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #ifdef __checkedc 22 | #ifndef __POLL_CHECKED_H 23 | #define __POLL_CHECKED_H 24 | 25 | #pragma CHECKED_SCOPE push 26 | #pragma CHECKED_SCOPE on 27 | 28 | extern int poll(struct pollfd fds[] : count(nfds), nfds_t nfds, int timeout); 29 | 30 | #pragma CHECKED_SCOPE pop 31 | 32 | #endif // guard 33 | #endif // Checked C 34 | 35 | #else // doesn't have poll.h 36 | #error "cannot include 'poll_checked.h' because this system does not have the original 'poll.h'" 37 | #endif 38 | -------------------------------------------------------------------------------- /include/pwd.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have pwd.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have pwd.h 29 | #error "cannot include 'pwd.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/pwd_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in pwd.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have pwd.h 8 | #if defined __has_include_next && __has_include_next() 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #ifdef __checkedc 22 | #ifndef __PWD_CHECKED_H 23 | #define __PWD_CHECKED_H 24 | 25 | #pragma CHECKED_SCOPE push 26 | #pragma CHECKED_SCOPE on 27 | 28 | struct passwd *getpwnam(const char *user : itype(_Nt_array_ptr)) : itype(_Ptr); 29 | int getpwnam_r(const char *user : itype(_Nt_array_ptr), 30 | struct passwd *pwd : itype(_Ptr), 31 | char *buf : byte_count(bufsize), 32 | size_t bufsize, struct passwd **result : itype(_Ptr<_Ptr>)); 33 | 34 | struct passwd *getpwuid(uid_t uid) : itype(_Ptr); 35 | int getpwuid_r(uid_t uid, 36 | struct passwd *pwd : itype(_Ptr), 37 | char *buf : byte_count(bufsize), 38 | size_t bufsize, struct passwd **result : itype(_Ptr<_Ptr>)); 39 | 40 | #pragma CHECKED_SCOPE pop 41 | 42 | #endif // guard 43 | #endif // Checked C 44 | 45 | #else // doesn't have pwd.h 46 | #error "cannot include 'pwd_checked.h' because this system does not have the original 'pwd.h'" 47 | #endif 48 | -------------------------------------------------------------------------------- /include/shadow.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // Uses clang-specific __has_include macro to detect unistd.h 9 | // which is required by Posix Standard. 10 | // The Windows environment also may not have unistd.h 11 | #if defined __has_include_next && __has_include_next() 12 | 13 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 14 | 15 | #ifdef __checkedc 16 | #pragma CHECKED_SCOPE push 17 | #pragma CHECKED_SCOPE off 18 | #endif 19 | 20 | #include_next 21 | 22 | #ifdef __checkedc 23 | #pragma CHECKED_SCOPE pop 24 | #endif 25 | 26 | #else // checkedc && implicit include enabled 27 | #include 28 | #endif 29 | 30 | #else // doesn't have unistd.h 31 | #error "cannot include 'shadow.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 32 | #endif 33 | -------------------------------------------------------------------------------- /include/shadow_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in shadow.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __SHADOW_CHECKED_H 20 | #define __SHADOW_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | struct spwd *getspnam(const char *name : itype(_Nt_array_ptr)) : itype(_Ptr); 26 | 27 | #pragma CHECKED_SCOPE pop 28 | 29 | #endif // guard 30 | #endif // Checked C 31 | -------------------------------------------------------------------------------- /include/signal.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/signal_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for a functions in signal.h that // 3 | // take pointer arguments. // 4 | ///////////////////////////////////////////////////////////////////////// 5 | 6 | #ifdef __checkedc 7 | #pragma CHECKED_SCOPE push 8 | #pragma CHECKED_SCOPE off 9 | #endif 10 | 11 | #include_next 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE pop 15 | #endif 16 | 17 | #ifdef __checkedc 18 | #ifndef __SIGNAL_CHECKED_H 19 | #define __SIGNAL_CHECKED_H 20 | 21 | #pragma CHECKED_SCOPE push 22 | #pragma CHECKED_SCOPE on 23 | 24 | _Unchecked 25 | void (*signal(int sig, 26 | void ((*func)(int)) : 27 | itype(_Ptr) // bound-safe interface for func 28 | ) : itype(_Ptr) // bounds-safe interface for signal return 29 | )(int); 30 | 31 | _Unchecked 32 | void (*sigset(int sig, 33 | void ((*func)(int)) : 34 | itype(_Ptr) // bound-safe interface for func 35 | ) : itype(_Ptr) // bounds-safe interface for signal return 36 | )(int); 37 | 38 | #ifdef _POSIX_C_SOURCE 39 | int sigemptyset(sigset_t *set : itype(_Ptr)); 40 | int sigfillset(sigset_t *set : itype(_Ptr)); 41 | int sigaddset(sigset_t *set : itype(_Ptr), int signum); 42 | int sigdelset(sigset_t *set : itype(_Ptr), int signum); 43 | int sigismember(const sigset_t *set : itype(_Ptr), int signum); 44 | 45 | int sigaction(int signum, const struct sigaction *act : itype(_Ptr), 46 | struct sigaction *oldact : itype(_Ptr)); 47 | 48 | 49 | int sigprocmask(int how, const sigset_t *set : itype(_Ptr), sigset_t *oldset : itype(_Ptr)); 50 | #endif // _POSIX_C_SOURCE 51 | 52 | #pragma CHECKED_SCOPE pop 53 | 54 | #endif // guard 55 | #endif // Checked C 56 | -------------------------------------------------------------------------------- /include/stdchecked.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDCHECKED_H 2 | #define __STDCHECKED_H 3 | 4 | #define ptr _Ptr 5 | #define array_ptr _Array_ptr 6 | #define nt_array_ptr _Nt_array_ptr 7 | #define checked _Checked 8 | #define nt_checked _Nt_checked 9 | #define unchecked _Unchecked 10 | #define bounds_only _Bounds_only 11 | #define where _Where 12 | #define dynamic_check _Dynamic_check 13 | #define dynamic_bounds_cast _Dynamic_bounds_cast 14 | #define assume_bounds_cast _Assume_bounds_cast 15 | #define return_value _Return_value 16 | #define _Dynamic_bounds_cast_M(T, e1, ... ) _Dynamic_bounds_cast(e1, __VA_ARGS__) 17 | #define _Dynamic_bounds_cast_M_N(T, e1 ) _Dynamic_bounds_cast(e1) 18 | #define _Assume_bounds_cast_M(T, e1, ... ) _Assume_bounds_cast(e1, __VA_ARGS__) 19 | #define _Assume_bounds_cast_M_N(T, e1 ) _Assume_bounds_cast(e1) 20 | #endif /* __STDCHECKED_H */ 21 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/stdlib.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sys/mman.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sys/mman_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in sys/mman.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __MMAN_CHECKED_H 20 | #define __MMAN_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | _Itype_for_any(T) void * mmap(void *addr : itype(_Array_ptr) byte_count(0), size_t length, int prot, int flags, int fd, off_t offset) : itype(_Array_ptr) byte_count(length); 26 | _Itype_for_any(T) int munmap(void *addr : itype(_Array_ptr) byte_count(length), size_t length); 27 | _Itype_for_any(T) int mprotect(void *addr : itype(_Array_ptr) byte_count(len) , size_t len, int prot); 28 | 29 | #pragma CHECKED_SCOPE pop 30 | 31 | #endif // guard 32 | #endif // Checked C 33 | -------------------------------------------------------------------------------- /include/sys/resource.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sys/resource_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in sys/resource.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __RESOURCE_CHECKED_H 20 | #define __RESOURCE_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | int getrlimit(int resource, struct rlimit *rlim : itype(_Ptr)); 26 | int setrlimit(int resource, const struct rlimit *rlim : itype(_Ptr)); 27 | 28 | #pragma CHECKED_SCOPE pop 29 | 30 | #endif // guard 31 | #endif // Checked C 32 | -------------------------------------------------------------------------------- /include/sys/select.h: -------------------------------------------------------------------------------- 1 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 2 | 3 | #ifdef __checkedc 4 | #pragma CHECKED_SCOPE push 5 | #pragma CHECKED_SCOPE off 6 | #endif 7 | 8 | #include_next 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE pop 12 | #endif 13 | 14 | #else // checkedc && implicit include enabled 15 | #include 16 | #endif 17 | -------------------------------------------------------------------------------- /include/sys/select_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in sys/select.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __SELECT_CHECKED_H 20 | #define __SELECT_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | int select(int nfds, fd_set *readfds : itype(_Ptr), fd_set *writefds : itype(_Ptr), fd_set *exceptfds : itype(_Ptr), struct timeval *timeout : itype(_Ptr)); 26 | 27 | #pragma CHECKED_SCOPE pop 28 | 29 | #endif // guard 30 | #endif // Checked C 31 | -------------------------------------------------------------------------------- /include/sys/socket.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have sys/socket.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have sys/socket.h 29 | #error "cannot include 'sys/socket.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/sys/stat.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have sys/stat.h 8 | #if defined __has_include_next && __has_include_next() 9 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 10 | 11 | #ifdef __checkedc 12 | #pragma CHECKED_SCOPE push 13 | #pragma CHECKED_SCOPE off 14 | #endif 15 | 16 | #include_next 17 | 18 | #ifdef __checkedc 19 | #pragma CHECKED_SCOPE pop 20 | #endif 21 | 22 | #else // checkedc && implicit include enabled 23 | #include 24 | #endif 25 | 26 | #else // doesn't have sys/stat.h 27 | #error "cannot include 'sys/stat.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 28 | #endif 29 | -------------------------------------------------------------------------------- /include/sys/stat_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in sys/stat.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __STAT_CHECKED_H 20 | #define __STAT_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | extern int mkdir(const char *pathname : itype(_Nt_array_ptr), mode_t mode); 26 | extern int chmod(const char *pathname : itype(_Nt_array_ptr), mode_t mode); 27 | extern int fstat(int fd, struct stat *buf : itype(_Ptr)); 28 | extern int lstat(const char *restrict file : itype(restrict _Nt_array_ptr), 29 | struct stat *restrict buf : itype(restrict _Ptr)); 30 | extern int stat(const char *restrict file : itype(restrict _Nt_array_ptr), 31 | struct stat *restrict buf : itype(restrict _Ptr)); 32 | 33 | #pragma CHECKED_SCOPE pop 34 | 35 | #endif // guard 36 | #endif // Checked C 37 | -------------------------------------------------------------------------------- /include/sys/time.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sys/time_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in sys/time.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __SYS_TIME_CHECKED_H 20 | #define __SYS_TIME_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | #ifdef __USE_MISC 26 | 27 | // The original system header has defined `struct timezone`, so we 28 | // should accommodate callers that pass a non-null `struct timezone *` 29 | // to gettimeofday. The man page shows the second parameter as `struct 30 | // timezone *tz`, but glibc has it as `void *`, and our redeclaration 31 | // must be consistent with that. 32 | // 33 | // ~ Matt 2022-01-05 34 | int gettimeofday(struct timeval * tv : itype(_Ptr), void *tz : itype(_Array_ptr) byte_count(sizeof(struct timezone))); 35 | 36 | int settimeofday(const struct timeval *tv : itype(_Ptr), const struct timezone *tz : itype(_Ptr)); 37 | 38 | #else 39 | 40 | // `struct timezone` has not been defined, so we mustn't reference it 41 | // from the Checked C annotations. Currently, it looks like if we 42 | // leave the parameter type as an unchecked pointer (which requires us 43 | // to declare the function as _Unchecked here), gettimeofday can still 44 | // be called from a checked scope with a literal null pointer as the 45 | // argument, though there's a risk of the compiler behavior changing 46 | // and breaking this in the future. 47 | // 48 | // Another reasonable approach would be to declare the parameter 49 | // `bounds(any)` as described in the specification, but the Checked C 50 | // compiler doesn't seem to be able to parse that. (TODO: File an 51 | // issue?) The other obvious approaches (`_Array_ptr : 52 | // bounds(unknown)`, `_Ptr`) would allow pointers with 53 | // insufficient bounds to be passed. 54 | 55 | _Unchecked 56 | int gettimeofday(struct timeval * tv : itype(_Ptr), void *tz); 57 | 58 | // glibc doesn't declare settimeofday in this case. 59 | 60 | #endif 61 | 62 | #pragma CHECKED_SCOPE pop 63 | 64 | #endif // guard 65 | #endif // Checked C 66 | -------------------------------------------------------------------------------- /include/sys/wait.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sys/wait_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in sys/wait.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | #ifdef __checkedc 8 | #pragma CHECKED_SCOPE push 9 | #pragma CHECKED_SCOPE off 10 | #endif 11 | 12 | #include_next 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE pop 16 | #endif 17 | 18 | #ifdef __checkedc 19 | #ifndef __WAIT_CHECKED_H 20 | #define __WAIT_CHECKED_H 21 | 22 | #pragma CHECKED_SCOPE push 23 | #pragma CHECKED_SCOPE on 24 | 25 | pid_t wait(int *wstatus : itype(_Ptr)); 26 | 27 | #pragma CHECKED_SCOPE pop 28 | 29 | #endif // guard 30 | #endif // Checked C 31 | -------------------------------------------------------------------------------- /include/syslog.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have syslog.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have syslog.h 29 | #error "cannot include 'syslog.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/syslog_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in syslog.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have syslog.h 8 | #if defined __has_include_next && __has_include_next() 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #ifdef __checkedc 22 | #ifndef __SYSLOG_CHECKED_H 23 | #define __SYSLOG_CHECKED_H 24 | 25 | #pragma CHECKED_SCOPE push 26 | #pragma CHECKED_SCOPE on 27 | 28 | void closelog(void); 29 | void openlog (const char *ident : itype(_Nt_array_ptr), int option, int facility); 30 | 31 | // TODO: Is this conditional right? There are two considerations: 32 | // 33 | // 1. Precedent in the Checked C system headers. I don't see any cases of 34 | // __foo_chk without __builtin___foo_chk, but this is my best guess of what 35 | // would be considered consistent. 36 | // 2. What's actually needed on the OSes we try to support (Linux, Windows, Mac 37 | // OS), though we might go with a solution that is more complex than 38 | // necessary if it's consistent with precedent. 39 | #if _FORTIFY_SOURCE == 0 || !defined(syslog) 40 | #undef syslog 41 | _Unchecked 42 | void syslog(int priority, const char * format : itype(_Nt_array_ptr), ...); 43 | #else 44 | _Unchecked 45 | void __syslog_chk(int priority, int flag, const char * format : itype(_Nt_array_ptr), ...); 46 | #endif 47 | 48 | // TODO: Can we assume that va_list has been included via the `#include_next 49 | // `, analogous to the situation in stdio_checked.h? 50 | // 51 | // TODO: The same questions about the conditional as for `syslog`. 52 | #if _FORTIFY_SOURCE == 0 || !defined(vsyslog) 53 | #undef vsyslog 54 | _Unchecked 55 | void vsyslog(int priority, const char * format : itype(_Nt_array_ptr), va_list ap); 56 | #else 57 | _Unchecked 58 | void __vsyslog_chk(int priority, int flag, const char * format : itype(_Nt_array_ptr), va_list ap); 59 | #endif 60 | 61 | #pragma CHECKED_SCOPE pop 62 | 63 | #endif // guard 64 | #endif // Checked C 65 | 66 | #else // doesn't have syslog.h 67 | #error "cannot include 'syslog_checked.h' because this system does not have the original 'syslog.h'" 68 | #endif 69 | -------------------------------------------------------------------------------- /include/threads.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // C implementations may not support the C11 threads package or even the 9 | // macro that says C11 threads are not supported. 10 | #if defined __has_include_next && __has_include_next() 11 | 12 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE push 16 | #pragma CHECKED_SCOPE off 17 | #endif 18 | 19 | #include_next 20 | 21 | #ifdef __checkedc 22 | #pragma CHECKED_SCOPE pop 23 | #endif 24 | 25 | #else // checkedc && implicit include enabled 26 | #include 27 | #endif 28 | 29 | #else // doesn't have threads.h 30 | #error "cannot include 'threads.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 31 | #endif 32 | -------------------------------------------------------------------------------- /include/threads_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in threads.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are listed in the same order that they occur in the C11 // 6 | // specification. // 7 | ///////////////////////////////////////////////////////////////////////// 8 | 9 | 10 | 11 | #ifdef _CHECKEDC_MOCKUP_THREADS 12 | // C implementations may not support the C11 threads package or even the 13 | // macro that says C11 threads are not supported. This mocks up 14 | // the types needed by threads so that we can test that the declarations 15 | // below compile. 16 | typedef struct __once_flag_struct once_flag; 17 | typedef struct __cnd_struct cnd_t; 18 | typedef struct __mtx_struct mtx_t; 19 | typedef struct __thread_struct thrd_t; 20 | typedef int (*thrd_start_t)(void *); 21 | typedef struct __thread_specific_storage_struct tss_t; 22 | typedef void (tss_dtor_t)(void *); 23 | struct timespec; 24 | #else 25 | 26 | #if defined __has_include_next && __has_include_next() 27 | 28 | #ifdef __checkedc 29 | #pragma CHECKED_SCOPE push 30 | #pragma CHECKED_SCOPE off 31 | #endif 32 | 33 | #include_next 34 | 35 | #ifdef __checkedc 36 | #pragma CHECKED_SCOPE pop 37 | #endif 38 | 39 | #else // doesn't have threads.h 40 | #error "cannot include 'threads_checked.h' because this system does not have the original 'threads.h'" 41 | #endif // threads.h 42 | #endif // _CHECKEDC_MOCKUP_THREADS 43 | 44 | 45 | #if defined _CHECKEDC_MOCKUP_THREADS || \ 46 | (defined __has_include_next && __has_include_next()) 47 | 48 | #ifdef __checkedc 49 | #ifndef __THREADS_CHECKED_H 50 | #define __THREADS_CHECKED_H 51 | 52 | #pragma CHECKED_SCOPE push 53 | #pragma CHECKED_SCOPE on 54 | 55 | void call_once(once_flag *flag : itype(_Ptr), 56 | void ((*fn)(void)) : itype(_Ptr)); 57 | 58 | int cnd_broadcast(cnd_t *condition : itype(_Ptr)); 59 | void cnd_destroy(cnd_t *condition : itype(_Ptr)); 60 | int cnd_init(cnd_t *condition : itype(_Ptr)); 61 | int cnd_signal(cnd_t *condition : itype(_Ptr)); 62 | int cnd_timedwait(cnd_t *restrict cond : itype(restrict _Ptr), 63 | mtx_t *restrict mutex: itype(restrict _Ptr), 64 | const struct timespec *restrict spec : 65 | itype(restrict _Ptr)); 66 | int cnd_wait(cnd_t *condition : itype(_Ptr), 67 | mtx_t *mutex : itype(_Ptr)); 68 | void mtx_destroy(mtx_t *mutex : itype(_Ptr)); 69 | int mtx_init(mtx_t *mutex : itype(_Ptr), int type); 70 | int mtx_lock(mtx_t *mutex : itype(_Ptr)); 71 | int mtx_timedlock(mtx_t *restrict mutex : itype(restrict _Ptr), 72 | const struct timespec *restrict ts : 73 | itype(restrict _Ptr)); 74 | int mtx_trylock(mtx_t *mtex : itype(_Ptr)); 75 | int mtx_unlock(mtx_t *mtex : itype(_Ptr)); 76 | 77 | int thrd_create(thrd_t *thr : itype(_Ptr), 78 | thrd_start_t func : 79 | itype(_Ptr))>), 80 | void *arg : itype(_Ptr)); 81 | int thrd_join(thrd_t thr, int *res : itype(_Ptr)); 82 | int thrd_sleep(const struct timespec *duration : 83 | itype(_Ptr), 84 | struct timespec *remaining : itype(_Ptr)); 85 | int tss_create(tss_t *key : itype(_Ptr), 86 | tss_dtor_t dtor : 87 | itype(_Ptr))>)); 88 | // Casting the Ptr returned by tss_get to a specific type will be an 89 | // unchecked operation. 90 | void *tss_get(tss_t key) : itype(_Ptr); 91 | int tss_set(tss_t key, void *value : itype(_Ptr)); 92 | 93 | #pragma CHECKED_SCOPE pop 94 | 95 | #endif // guard 96 | #endif // Checked C 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /include/time.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #else // checkedc && implicit include enabled 22 | #include 23 | #endif 24 | -------------------------------------------------------------------------------- /include/time_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in time.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are listed in the same order that they occur in the C11 // 6 | // specification. // 7 | ///////////////////////////////////////////////////////////////////////// 8 | 9 | #ifdef __checkedc 10 | #pragma CHECKED_SCOPE push 11 | #pragma CHECKED_SCOPE off 12 | #endif 13 | 14 | #include_next 15 | 16 | #ifdef __checkedc 17 | #pragma CHECKED_SCOPE pop 18 | #endif 19 | 20 | #ifdef __checkedc 21 | #ifndef __TIME_CHECKED_H 22 | #define __TIME_CHECKED_H 23 | 24 | #pragma CHECKED_SCOPE push 25 | #pragma CHECKED_SCOPE on 26 | 27 | time_t mktime(struct tm *timeptr : itype(_Ptr)); 28 | 29 | int timespec_get(struct timespec *ts : itype(_Ptr), 30 | int base); 31 | 32 | char *asctime(const struct tm *timeptr : itype(_Ptr)) : 33 | itype(_Nt_array_ptr); 34 | 35 | char *ctime(const time_t *timer : itype(_Ptr)) : 36 | itype(_Nt_array_ptr); 37 | 38 | struct tm *gmtime(const time_t *timer : itype(_Ptr)) : 39 | itype(_Ptr); 40 | 41 | struct tm *localtime(const time_t *timer : itype(_Ptr)) : 42 | itype(_Ptr); 43 | 44 | size_t strftime(char * restrict output : itype(restrict _Nt_array_ptr) count(maxsize-1), 45 | size_t maxsize _Where maxsize > 0, 46 | const char * restrict format : itype(restrict _Nt_array_ptr), 47 | const struct tm * restrict timeptr : 48 | itype(restrict _Ptr)); 49 | 50 | int nanosleep(const struct timespec *req : itype(_Ptr), struct timespec *rem : itype(_Ptr)); 51 | 52 | #pragma CHECKED_SCOPE pop 53 | 54 | #endif // guard 55 | #endif // Checked C 56 | -------------------------------------------------------------------------------- /include/unistd.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // Uses clang-specific __has_include macro to detect unistd.h 9 | // which is required by Posix Standard. 10 | // The Windows environment also may not have unistd.h 11 | #if defined __has_include_next && __has_include_next() 12 | 13 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 14 | 15 | #ifdef __checkedc 16 | #pragma CHECKED_SCOPE push 17 | #pragma CHECKED_SCOPE off 18 | #endif 19 | 20 | #include_next 21 | 22 | #ifdef __checkedc 23 | #pragma CHECKED_SCOPE pop 24 | #endif 25 | 26 | #else // checkedc && implicit include enabled 27 | #include 28 | #endif 29 | 30 | #else // doesn't have unistd.h 31 | #error "cannot include 'unistd.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 32 | #endif 33 | -------------------------------------------------------------------------------- /include/unistd_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in unistd.h that // 3 | // take pointer arguments. // 4 | // // 5 | // These are POSIX-only // 6 | ///////////////////////////////////////////////////////////////////////// 7 | 8 | 9 | // Uses clang-specific __has_include macro to detect unistd.h 10 | // which is required by Posix Standard. 11 | // The Windows environment also may not have unistd.h 12 | #if defined __has_include_next && __has_include_next() 13 | 14 | #ifdef __checkedc 15 | #pragma CHECKED_SCOPE push 16 | #pragma CHECKED_SCOPE off 17 | #endif 18 | 19 | #include_next 20 | 21 | #ifdef __checkedc 22 | #pragma CHECKED_SCOPE pop 23 | #endif 24 | 25 | #ifdef __checkedc 26 | #ifndef __UNISTD_CHECKED_H 27 | #define __UNISTD_CHECKED_H 28 | 29 | #pragma CHECKED_SCOPE push 30 | #pragma CHECKED_SCOPE on 31 | 32 | #if _POSIX_VERSION >= 200112L 33 | 34 | char *getpass(const char *prompt : itype(_Nt_array_ptr)) : itype(_Nt_array_ptr); 35 | char *crypt(const char *phrase : itype(_Nt_array_ptr), const char *setting : itype(_Nt_array_ptr)) : itype(_Nt_array_ptr); 36 | 37 | extern char ** environ : itype(_Nt_array_ptr<_Nt_array_ptr>); 38 | 39 | extern char *getcwd(char *buf : itype(_Nt_array_ptr) count(size-1), 40 | size_t size _Where size > 0) : itype(_Nt_array_ptr); 41 | extern int rmdir(const char *pathname : itype(_Nt_array_ptr)); 42 | extern int chdir(const char *p_dirname : itype(_Nt_array_ptr)); 43 | // Caution: Does not null-terminate `buf`. 44 | extern ssize_t readlink (const char *restrict path : itype(restrict _Nt_array_ptr), 45 | char *restrict buf : count(len), size_t len); 46 | extern int chroot(const char *dirname : itype(_Nt_array_ptr)); 47 | int unlink(const char *pathname : itype(_Nt_array_ptr)); 48 | int mkstemp(char *template : itype(_Nt_array_ptr)); 49 | 50 | #ifdef __APPLE__ 51 | 52 | extern int access (const char *__name : itype(_Nt_array_ptr), int __type); 53 | extern ssize_t read (int __fd, void *__buf : byte_count(__nbytes), size_t __nbytes); 54 | extern ssize_t write (int __fd, const void *__buf : byte_count(__n), size_t __n); 55 | 56 | #else 57 | 58 | extern int access (const char *__name : itype(_Nt_array_ptr), int __type) __THROW __nonnull ((1)); 59 | extern ssize_t read (int __fd, void *__buf : byte_count(__nbytes), size_t __nbytes) __wur; 60 | extern ssize_t write (int __fd, const void *__buf : byte_count(__n), size_t __n) __wur; 61 | 62 | #endif 63 | 64 | extern int execve(const char *pathname : itype(_Nt_array_ptr), 65 | char * const *argv : itype(_Nt_array_ptr>), 66 | char * const *envp : itype(_Nt_array_ptr>)); 67 | 68 | // Caution: Does not null-terminate `name` on overflow. 69 | int gethostname(char *name : count(len), size_t len); 70 | 71 | extern char *getusershell(void) : itype(_Nt_array_ptr); 72 | 73 | #endif 74 | 75 | #pragma CHECKED_SCOPE pop 76 | 77 | #endif // guard 78 | #endif // Checked C 79 | 80 | #else // doesn't have unistd.h 81 | #error "cannot include 'unistd_checked.h' because this system does not have the original 'unistd.h'" 82 | #endif 83 | -------------------------------------------------------------------------------- /include/utime.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Wrapper header file that excludes Checked-C-specific declarations // 3 | // if the compilation is not for Checked C, or if is for Checked C // 4 | // but the implicit inclusion of checked header files is disabled. // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | 8 | // The Windows environment may not have utime.h 9 | #if defined __has_include_next && __has_include_next() 10 | 11 | #if !defined __checkedc || defined NO_IMPLICIT_INCLUDE_CHECKED_HDRS 12 | 13 | #ifdef __checkedc 14 | #pragma CHECKED_SCOPE push 15 | #pragma CHECKED_SCOPE off 16 | #endif 17 | 18 | #include_next 19 | 20 | #ifdef __checkedc 21 | #pragma CHECKED_SCOPE pop 22 | #endif 23 | 24 | #else // checkedc && implicit include enabled 25 | #include 26 | #endif 27 | 28 | #else // doesn't have utime.h 29 | #error "cannot include 'utime.h' because this system does not have the original header, even though Checked C provides a wrapper for it" 30 | #endif 31 | -------------------------------------------------------------------------------- /include/utime_checked.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------// 2 | // Bounds-safe interfaces for functions in utime.h that // 3 | // take pointer arguments. // 4 | // // 5 | ///////////////////////////////////////////////////////////////////////// 6 | 7 | // The Windows environment may not have utime.h 8 | #if defined __has_include_next && __has_include_next() 9 | 10 | #ifdef __checkedc 11 | #pragma CHECKED_SCOPE push 12 | #pragma CHECKED_SCOPE off 13 | #endif 14 | 15 | #include_next 16 | 17 | #ifdef __checkedc 18 | #pragma CHECKED_SCOPE pop 19 | #endif 20 | 21 | #ifdef __checkedc 22 | #ifndef __UTIME_CHECKED_H 23 | #define __UTIME_CHECKED_H 24 | 25 | #pragma CHECKED_SCOPE push 26 | #pragma CHECKED_SCOPE on 27 | 28 | extern int utime (const char *file : itype(_Nt_array_ptr), 29 | const struct utimbuf *file_times : itype(_Ptr)); 30 | 31 | #pragma CHECKED_SCOPE pop 32 | 33 | #endif // guard 34 | #endif // Checked C 35 | 36 | #else // doesn't have utime.h 37 | #error "cannot include 'utime_checked.h' because this system does not have the original 'utime.h'" 38 | #endif 39 | -------------------------------------------------------------------------------- /papers/dynamic_checks/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore LaTeX (and Latexmk) files 2 | *.aux 3 | *.lof 4 | *.log 5 | *.lot 6 | *.fls 7 | *.out 8 | *.toc 9 | *.fmt 10 | *.fot 11 | *.cb 12 | *.cb2 13 | *.dvi 14 | *.bbl 15 | *.bcf 16 | *.blg 17 | *-blx.aux 18 | *-blx.bib 19 | *.run.xml 20 | *.fdb_latexmk 21 | *.synctex 22 | *.synctex(busy) 23 | *.synctex.gz 24 | *.synctex.gz(busy) 25 | *.pdfsync 26 | **/auto/* 27 | .R* 28 | *.ent 29 | tr02.pdf 30 | -------------------------------------------------------------------------------- /papers/dynamic_checks/Makefile: -------------------------------------------------------------------------------- 1 | # This Makefile uses latexmk as far as possible 2 | # because it understands LaTeX files better than 3 | # a hand-coded makefile. latexmk should be in any 4 | # modern Tex Live distribution. 5 | # Info: http://mg.readthedocs.io/latexmk.html 6 | 7 | .PHONY: tr02.pdf all clean cleanall pres 8 | 9 | all : tr02.pdf 10 | 11 | pres : $(addprefix scripts/,modifications_pres.pdf overheads_pres.pdf) 12 | 13 | clean : 14 | latexmk -c 15 | 16 | cleanall : 17 | latexmk -C 18 | $(MAKE) -C scripts clean 19 | 20 | GEN_TEX_SCRIPTS=$(addprefix scripts/,bm_results_tab.tex bm_results_macros.tex) 21 | GEN_GRAPHS=$(addprefix scripts/,modifications.pdf overheads.pdf) 22 | GEN_RESULTS=$(GEN_TEX_SCRIPTS) $(GEN_GRAPHS) 23 | 24 | tr02.pdf : $(GEN_RESULTS) 25 | latexmk -pdf -use-make tr02.tex 26 | 27 | scripts/%.pdf : scripts 28 | $(MAKE) -C scripts $(@F) 29 | scripts/%.tex : scripts 30 | $(MAKE) -C scripts $(@F) 31 | 32 | 33 | -------------------------------------------------------------------------------- /papers/dynamic_checks/README.md: -------------------------------------------------------------------------------- 1 | # Putting the Checks into Checked C 2 | ## Checked C Technical Report Number 2 3 | 4 | This document is current as of October 2017, and omits a description of null-terminated pointers. 5 | 6 | ### Building 7 | 8 | To build this document fully, you'll need to install [R](https://www.r-project.org) and put `Rscript` on your path, as well as LaTeX. 9 | 10 | -------------------------------------------------------------------------------- /papers/dynamic_checks/abstract.tex: -------------------------------------------------------------------------------- 1 | Checked C is an extension to C that aims to provide a route for 2 | programmers to upgrade their existing C programs to a safer language 3 | without losing the low-level control they enjoy. Checked C currently 4 | only addresses unsafe code with spatial memory violations such as 5 | buffer overruns and out-of-bounds memory accesses. \\[1em] 6 | 7 | Checked C addresses these memory safety problems by adding new pointer 8 | and array types to C, and a method for annotating pointers with 9 | expressions denoting the bounds of the objects they reference in 10 | memory. To ensure memory safety, the Checked C compiler uses a mixture 11 | of static and dynamic checks over these additions to the C language. \\[1em] 12 | 13 | This Technical Report concerns these Dynamic Checks, and the 14 | algorithms and infrastructure required to support them, including: the 15 | soundness property Checked C is aiming to preserve, propagation rules 16 | for bounds information, and the code generation algorithm for the 17 | checks themselves. This report includes an evaluation of these dynamic 18 | bounds checks, their overhead, and their interaction with a 19 | state-of-the-art optimizer. 20 | 21 | %%% Local Variables: 22 | %%% mode: latex 23 | %%% TeX-master: "tr02" 24 | %%% End: 25 | -------------------------------------------------------------------------------- /papers/dynamic_checks/c_syntax.tex: -------------------------------------------------------------------------------- 1 | \chapter{C Syntax} 2 | \label{app:c-syntax} 3 | 4 | This appendix contains a definition of the relevant parts of C Syntax 5 | for this report. This is based on the C11 Specification, but written 6 | with mathematical symbols rather than ASCII text. 7 | 8 | \begin{align*} 9 | \text{LValue Expressions} \\* 10 | e_l \gis {} & x \tag*{Variables} \\ 11 | \gor {} & \deref e_v \tag*{Dereference} \\ 12 | \gor {} & e_v[e_v] \tag*{Index} \\ 13 | \gor {} & e_l \member m \tag*{Struct Member Access} \\ 14 | \gor {} & e_v \arrow m \tag*{Pointer Member Access} \\[1em] 15 | % 16 | \text{Value Expressions} \\* 17 | e_v \gis {} & \addrof e_l \tag*{Address-of} \\ 18 | \gor {} & e_l \assign e_v \tag*{Assignment} \\ 19 | \gor {} & e_l \compassign e_v \tag*{Compound Assignment} \\ 20 | \gor {} & e_l \inc \mathrel{\mid} \inc e_l \tag*{Increment} \\ 21 | \gor {} & e_l \dec \mathrel{\mid} \dec e_l \tag*{Decrement} \\ 22 | \gor {} & e_v \member m \tag*{Struct Member Access} \\ 23 | \gor {} & e_v , e_v \tag*{Comma Expression} \\ 24 | \gor {} & e_v \binop e_v \tag*{Binary Operation} \\ 25 | \gor {} & e_v \mathrel{R} e_v \tag*{Binary Relational Operation} \\ 26 | \gor {} & \unop e_v \tag*{Unary Operation} \\ 27 | \gor {} & e_v(\overline{e_v}) \tag*{Function Call} \\ 28 | \gor {} & (t)e_v \tag*{Cast} \\ 29 | \gor {} & e_v \mathrel{?} e_v : e_v \tag*{Conditional Operator} \\ 30 | \gor {} & l \tag*{Literal Value} \\ 31 | \gor {} & e_l \tag*{Lvalue \& Array Conversion} \displaybreak\\[1em] 32 | % 33 | \text{Binary Operators} \\* 34 | \binop \gis {} & + \tag*{Addition} \\ 35 | \gor {} & - \tag*{Subtraction} \\ 36 | \gor {} & * \tag*{Multiplication} \\ 37 | \gor {} & / \tag*{Division} \\ 38 | \gor {} & \% \tag*{Modulus} \\ 39 | \gor {} & \& \tag*{Bitwise AND} \\ 40 | \gor {} & \mid \tag*{Bitwise OR} \\ 41 | \gor {} & \wedge \tag*{Bitwise XOR} \\ 42 | \gor {} & \gg \tag*{Bitwise Shift Right} \\ 43 | \gor {} & \ll \tag*{Bitwise Shift Left} \\[1em] 44 | % 45 | \text{Relational Operators} \\* 46 | R \gis {} & \&\& \tag*{Logical AND} \\ 47 | \gor {} & \mid\mid \tag*{Logical OR} \\ 48 | \gor {} & \mathord{==} \tag*{Equality} \\ 49 | \gor {} & \mathord{!=} \tag*{Negated Equality} \\ 50 | \gor {} & \mathord{>} \mathrel{\mid} 51 | \mathord{\ge} \mathrel{\mid} 52 | \mathord{<} \mathrel{\mid} 53 | \mathord{\le} \tag*{Comparison} \\[1em] 54 | % 55 | \text{Unary Operators} \\* 56 | \unop \gis {} & + \tag*{Unary Plus} \\ 57 | \gor {} & - \tag*{Numerical Negation} \\ 58 | \gor {} & \sim \tag*{Bitwise Negation} \\ 59 | \gor {} & ! \tag*{Logical Negation} \\[1em] 60 | % 61 | \text{Literals} \\* 62 | l \gis {} & \mathtt{NULL} \tag*{Null Pointer Literal} \\ 63 | \gor {} & \mathrm{integers} \tag*{Integer Literals} \\ 64 | \gor {} & \mathrm{floats} \tag*{Float Literals} \\ 65 | \gor {} & \{ l , \dots \} \tag*{Array \& Struct Literals} \\[1em] 66 | % 67 | \text{Types} \\* 68 | t \gis {} & \dots \\[1em] 69 | % 70 | \text{Struct Members} \\* 71 | m \gis {} & \dots \\ 72 | \end{align*} 73 | 74 | %%% Local Variables: 75 | %%% mode: latex 76 | %%% TeX-master: "tr02" 77 | %%% End: 78 | -------------------------------------------------------------------------------- /papers/dynamic_checks/conclusion.tex: -------------------------------------------------------------------------------- 1 | \chapter{Conclusion} 2 | \label{sec:conclusion} 3 | 4 | This report has described how I implemented the dynamic checks in the 5 | Checked C compiler. I have presented a flow-insensitive algorithm for 6 | propagating bounds information through expressions, such that these 7 | bounds can be checked when memory is accessed, and has shown one 8 | possible compilation of these bounds expressions into dynamic checks. 9 | 10 | I have also shown that, for a set of pointer-intensive benchmarks, 11 | though the programmer will have to modify on average 12 | \ResultLinesModifiedMean of each benchmark in order to have the 13 | soundness Checked C guarantees, this gives a run-time overhead of on 14 | average \ResultRunTimeMean and at most \ResultRunTimeMax. 15 | 16 | This work is an important step towards proving the viability and 17 | usefulness of Checked C. 18 | 19 | 20 | %\section{Future Work} 21 | 22 | %%% Local Variables: 23 | %%% mode: latex 24 | %%% TeX-master: "tr02" 25 | %%% End: 26 | -------------------------------------------------------------------------------- /papers/dynamic_checks/grammars/lvalue-expressions.tex: -------------------------------------------------------------------------------- 1 | \begin{align*} 2 | \text{LValue Expressions} \qquad 3 | e_l \Coloneqq {} & x \tag*{Variables} \\ 4 | \mid {} & \deref e_v \tag*{Dereference} \\ 5 | \mid {} & e_v[e_v] \tag*{Index} \\ 6 | \mid {} & e_l \member m \tag*{Struct Member Access} \\ 7 | \mid {} & e_v \arrow m \tag*{Pointer Member Access} \\[1em] 8 | \text{Value Expressions} \qquad 9 | e_v \Coloneqq {} & \addrof e_l \tag*{Address-of} \\ 10 | \mid {} & e_l \assign e_v \tag*{Assignment} \\ 11 | \mid {} & e_l \compassign e_v & \tag*{Compound Assignment} \\ 12 | \mid {} & e_l \inc \mathrel{\mid} \inc e_l \tag*{Increment} \\ 13 | \mid {} & e_l \dec \mathrel{\mid} \dec e_l \tag*{Decrement} \\ 14 | \mid {} & e_v \member m \tag*{Struct Member Access} \\ 15 | \mid {} & \hdots \tag*{Other Value Expressions} \\ 16 | \mid {} & e_l \tag*{Lvalue \& Array Conversion} 17 | \end{align*}% 18 | \caption[Lvalue expressions and their usage in C]{Lvalue expressions 19 | and their usage in C. A more complete description of C's expression 20 | syntax, including a definition of $\binop$ (binary operators), is 21 | contained in~\autoref{app:c-syntax}. Note that a Struct Member Access 22 | can be an lvalue or a value depending on whether the sub-expression is 23 | an lvalue or a value (respectively).} 24 | \label{fig:lvalue-expressions} 25 | 26 | %%% Local Variables: 27 | %%% mode: latex 28 | %%% TeX-master: "../tr02" 29 | %%% End: 30 | -------------------------------------------------------------------------------- /papers/dynamic_checks/hyperendnotes.sty: -------------------------------------------------------------------------------- 1 | % From Ulrich Dirr via https://tex.stackexchange.com/a/8474/45937 2 | %%% hyperendnotes.sty 3 | \makeatletter 4 | \newif\ifenotelinks 5 | \newcounter{Hendnote} 6 | % Redefining portions of endnotes-package: 7 | \let\savedhref\href 8 | \let\savedurl\url 9 | \def\endnotemark{% 10 | \@ifnextchar[\@xendnotemark{% 11 | \stepcounter{endnote}% 12 | \protected@xdef\@theenmark{\theendnote}% 13 | \protected@xdef\@theenvalue{\number\c@endnote}% 14 | \@endnotemark 15 | }% 16 | }% 17 | \def\@xendnotemark[#1]{% 18 | \begingroup\c@endnote#1\relax 19 | \unrestored@protected@xdef\@theenmark{\theendnote}% 20 | \unrestored@protected@xdef\@theenvalue{\number\c@endnote}% 21 | \endgroup 22 | \@endnotemark 23 | }% 24 | \def\endnotetext{% 25 | \@ifnextchar[\@xendnotenext{% 26 | \protected@xdef\@theenmark{\theendnote}% 27 | \protected@xdef\@theenvalue{\number\c@endnote}% 28 | \@endnotetext 29 | }% 30 | }% 31 | \def\@xendnotenext[#1]{% 32 | \begingroup 33 | \c@endnote=#1\relax 34 | \unrestored@protected@xdef\@theenmark{\theendnote}% 35 | \unrestored@protected@xdef\@theenvalue{\number\c@endnote}% 36 | \endgroup 37 | \@endnotetext 38 | }% 39 | \def\endnote{% 40 | \@ifnextchar[\@xendnote{% 41 | \stepcounter{endnote}% 42 | \protected@xdef\@theenmark{\theendnote}% 43 | \protected@xdef\@theenvalue{\number\c@endnote}% 44 | \@endnotemark\@endnotetext 45 | }% 46 | }% 47 | \def\@xendnote[#1]{% 48 | \begingroup 49 | \c@endnote=#1\relax 50 | \unrestored@protected@xdef\@theenmark{\theendnote}% 51 | \unrestored@protected@xdef\@theenvalue{\number\c@endnote}% 52 | \show\@theenvalue 53 | \endgroup 54 | \@endnotemark\@endnotetext 55 | }% 56 | \def\@endnotemark{% 57 | \leavevmode 58 | \ifhmode 59 | \edef\@x@sf{\the\spacefactor}\nobreak 60 | \fi 61 | \ifenotelinks 62 | \expandafter\@firstofone 63 | \else 64 | \expandafter\@gobble 65 | \fi 66 | {% 67 | \Hy@raisedlink{% 68 | \hyper@@anchor{Hendnotepage.\@theenvalue}{\empty}% 69 | }% 70 | }% 71 | \hyper@linkstart{link}{Hendnote.\@theenvalue}% 72 | \makeenmark 73 | \hyper@linkend 74 | \ifhmode 75 | \spacefactor\@x@sf 76 | \fi 77 | \relax 78 | }% 79 | \long\def\@endnotetext#1{% 80 | \if@enotesopen 81 | \else 82 | \@openenotes 83 | \fi 84 | \immediate\write\@enotes{% 85 | \@doanenote{\@theenmark}{\@theenvalue}% 86 | }% 87 | \begingroup 88 | \def\next{#1}% 89 | \newlinechar='40 90 | \immediate\write\@enotes{\meaning\next}% 91 | \endgroup 92 | \immediate\write\@enotes{% 93 | \@endanenote 94 | }% 95 | }% 96 | \def\theendnotes{% 97 | \immediate\closeout\@enotes 98 | \global\@enotesopenfalse 99 | \begingroup 100 | \makeatletter 101 | \edef\@tempa{`\string>}% 102 | \ifnum\catcode\@tempa=12 103 | \let\@ResetGT\relax 104 | \else 105 | \edef\@ResetGT{\noexpand\catcode\@tempa=\the\catcode\@tempa}% 106 | \@makeother\>% 107 | \fi 108 | \def\@doanenote##1##2##3>{% 109 | \def\@theenmark{##1}% 110 | \def\@theenvalue{##2}% 111 | \par 112 | \smallskip %<-small vertical gap between endnotes 113 | \begingroup 114 | \def\href{\expandafter\savedhref}% 115 | \def\url{\expandafter\savedurl}% 116 | \@ResetGT 117 | \edef\@currentlabel{\csname p@endnote\endcsname\@theenmark}% 118 | \enoteformat 119 | }% 120 | \def\@endanenote{% 121 | \par\endgroup 122 | }% 123 | % Redefine, how numbers are formatted in the endnotes-section: 124 | \renewcommand*\@makeenmark{% 125 | \hbox{\normalfont\@theenmark.~}% 126 | }% 127 | % header of endnotes-section 128 | \enoteheading 129 | % font-size of endnotes 130 | \enotesize 131 | \input{\jobname.ent}% 132 | \endgroup 133 | }% 134 | \def\enoteformat{% 135 | \rightskip\z@ 136 | \leftskip1.8em 137 | \parindent\z@ 138 | \leavevmode\llap{% 139 | \setcounter{Hendnote}{\@theenvalue}% 140 | \addtocounter{Hendnote}{-1}% 141 | \refstepcounter{Hendnote}% 142 | \ifenotelinks 143 | \expandafter\@secondoftwo 144 | \else 145 | \expandafter\@firstoftwo 146 | \fi 147 | {\@firstofone}% 148 | {\hyperlink{Hendnotepage.\@theenvalue}}% 149 | {\makeenmark}% 150 | }% 151 | }% 152 | % stop redefining portions of endnotes-package: 153 | \makeatother 154 | % Toggle switch in order to turn on/off back-links in the 155 | % endnote-section: 156 | \enotelinkstrue 157 | %\enotelinksfalse 158 | -------------------------------------------------------------------------------- /papers/dynamic_checks/listing-label.sty: -------------------------------------------------------------------------------- 1 | %% Source Code Notes 2 | \ProvidesPackage{listing-label} 3 | \RequirePackage{tikz} 4 | 5 | % Counter, numbered by section 6 | \newcounter{decoratedlabel}[section] 7 | % Use this in listing, to label something right there. You'll need a way to 8 | % escape into normal latex in listings, I use \lstset{escapechar=@} so 9 | % this command goes in @\lstlabel{...}@. You'll probably also want 10 | % \lstset{flexiblecolumns,keepspaces} because it looks nicer. 11 | \newcommand{\decorate}[1]{\refstepcounter{decoratedlabel}\label{#1}% 12 | \protect\decoratedlabelpicture{\thedecoratedlabel}} 13 | % Use this in listing (again once escaped to latex), to label 14 | % something in the left margin (must be at start of a line, takes up 0 15 | % horizontal space in the listing line) 16 | \newcommand{\decorateleft}[1]{\refstepcounter{decoratedlabel}\label{#1}% 17 | \makebox[0pt]{\decoratedlabelpicture{\thedecoratedlabel}\hspace{2em}}} 18 | % Use this in text to refer to \lstlabel. If you use `hyperref` they 19 | % get linked together! 20 | \newcommand{\decref}[1]{\decoratedlabelpicture{\ref{#1}}} 21 | % Use letters, because we might have a lot of them 22 | \renewcommand{\thedecoratedlabel}{\Alph{decoratedlabel}} 23 | % Put a circle around the letter, of course. 24 | \newcommand*\decoratedlabelpicture[1]{% 25 | \tikz[baseline=(char.base)]{ 26 | \node[shape=circle,draw,inner sep=1pt,minimum size=1.05em] (char) {\scriptsize\sffamily#1}; 27 | }} 28 | % 29 | % If you want the label numbers to be per-listing, then uncomment the 30 | % following code. They are currently per-section (see above) 31 | % 32 | % \AtBeginDocument{ 33 | % \makeatletter 34 | % \@addtoreset{decoratedlabel}{lstlisting} 35 | % \makeatother 36 | % } 37 | 38 | \newcommand{\lstlabel}[1]{\decorate{#1}} 39 | \newcommand{\lstleftlabel}[1]{\decorateleft{#1}} 40 | \newcommand{\lstref}[1]{\decref{#1}} 41 | -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/Makefile: -------------------------------------------------------------------------------- 1 | 2 | TEX_SCRIPTS=bm_results_tab.tex bm_results_macros.tex 3 | GRAPHS=modifications.pdf overheads.pdf 4 | RESULTS=$(TEX_SCRIPTS) $(GRAPHS) 5 | 6 | .PHONY : clean all install 7 | all : $(RESULTS) 8 | 9 | install : bm_res_install.r 10 | ./bm_res_install.r 11 | 12 | clean : 13 | rm $(RESULTS) 14 | 15 | 16 | $(RESULTS) : bm_res.r bm_res.csv 17 | ./bm_res.r 18 | 19 | -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/bm_res.csv: -------------------------------------------------------------------------------- 1 | Suite,Name,LM,EM,LU,RT,CT,ES 2 | # 3 | Olden,bh,9.98,76.7,5.15,0.24,23.76,6.21 4 | Olden,bisort,21.76,84.3,6.98,0.0,7.34,3.78 5 | Olden,em3d,35.29,66.4,16.89,0.80,18.01,-0.37 6 | Olden,health,23.96,97.8,9.28,2.11,18.47,6.73 7 | Olden,mst,30.15,75.0,19.33,0.0,6.28,-4.97 8 | Olden,perimeter,9.77,92.3,5.16,0.0,4.88,0.76 9 | Olden,power,15.04,69.2,3.90,0.0,21.58,8.54 10 | Olden,treadd,17.22,92.3,20.42,8.25,83.10,6.96 11 | Olden,tsp,9.90,94.5,10.33,0.0,47.62,4.63 12 | # Olden,voronoi,NA,NA,NA,NA,NA,NA 13 | # 14 | Ptrdist,anagram,26.59,67.5,10.72,23.53,16.82,5.13 15 | # Ptrdist,bc,NA,NA,NA,NA,NA,NA 16 | Ptrdist,ft,18.70,98.5,6.35,25.92,16.54,11.3 17 | Ptrdist,ks,14.21,93.4,8.12,12.77,32.34,26.71 18 | Ptrdist,yacr2,14.51,51.5,16.17,49.32,38.37,24.50 19 | -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/bm_res_install.r: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env Rscript 2 | 3 | # You'll need the following packages 4 | install.packages(c("tidyverse", "scales", "cowplot"), repos="https://ftp.osuosl.org/pub/cran/") 5 | 6 | -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/bm_results_macros.tex: -------------------------------------------------------------------------------- 1 | % Auto Generated by bm_res.r 2 | % Do Not Modify 3 | \newcommand{\ResultLinesModifiedMean}{17.5\%\xspace} 4 | \newcommand{\ResultLinesModifiedMax}{35.3\%\xspace} 5 | \newcommand{\ResultLinesModifiedMin}{9.8\%\xspace} 6 | 7 | \newcommand{\ResultEasyModificationsMean}{80.1\%\xspace} 8 | \newcommand{\ResultEasyModificationsMax}{98.5\%\xspace} 9 | \newcommand{\ResultEasyModificationsMin}{51.5\%\xspace} 10 | 11 | \newcommand{\ResultLinesUncheckedMean}{9.3\%\xspace} 12 | \newcommand{\ResultLinesUncheckedMax}{20.4\%\xspace} 13 | \newcommand{\ResultLinesUncheckedMin}{3.9\%\xspace} 14 | 15 | \newcommand{\ResultRunTimeMean}{8.6\%\xspace} 16 | \newcommand{\ResultRunTimeMax}{49.3\%\xspace} 17 | \newcommand{\ResultRunTimeMin}{0.0\%\xspace} 18 | 19 | \newcommand{\ResultCompileTimeMean}{24.3\%\xspace} 20 | \newcommand{\ResultCompileTimeMax}{83.1\%\xspace} 21 | \newcommand{\ResultCompileTimeMin}{4.9\%\xspace} 22 | 23 | \newcommand{\ResultExecutableSizeMean}{7.4\%\xspace} 24 | \newcommand{\ResultExecutableSizeMax}{26.7\%\xspace} 25 | \newcommand{\ResultExecutableSizeMin}{-5.0\%\xspace} 26 | -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/bm_results_tab.tex: -------------------------------------------------------------------------------- 1 | bh & 10.0 & 76.7 & 5.2 & + 0.2 & + 23.8 & + 6.2 \\ 2 | bisort & 21.8 & 84.3 & 7.0 & 0.0 & + 7.3 & + 3.8 \\ 3 | em3d & 35.3 & 66.4 & 16.9 & + 0.8 & + 18.0 & - 0.4 \\ 4 | health & 24.0 & 97.8 & 9.3 & + 2.1 & + 18.5 & + 6.7 \\ 5 | mst & 30.1 & 75.0 & 19.3 & 0.0 & + 6.3 & - 5.0 \\ 6 | perimeter & 9.8 & 92.3 & 5.2 & 0.0 & + 4.9 & + 0.8 \\ 7 | power & 15.0 & 69.2 & 3.9 & 0.0 & + 21.6 & + 8.5 \\ 8 | treadd & 17.2 & 92.3 & 20.4 & + 8.3 & + 83.1 & + 7.0 \\ 9 | tsp & 9.9 & 94.5 & 10.3 & 0.0 & + 47.6 & + 4.6 \\ 10 | \addlinespace 11 | anagram & 26.6 & 67.5 & 10.7 & + 23.5 & + 16.8 & + 5.1 \\ 12 | ft & 18.7 & 98.5 & 6.3 & + 25.9 & + 16.5 & + 11.3 \\ 13 | ks & 14.2 & 93.4 & 8.1 & + 12.8 & + 32.3 & + 26.7 \\ 14 | yacr2 & 14.5 & 51.5 & 16.2 & + 49.3 & + 38.4 & + 24.5 \\ 15 | \midrule 16 | \multicolumn{1}{r}{Geo. Mean:} & 17.5 & 80.1 & 9.3 & + 8.6 & + 24.3 & + 7.4 \\ 17 | -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/modifications.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/papers/dynamic_checks/scripts/modifications.pdf -------------------------------------------------------------------------------- /papers/dynamic_checks/scripts/overheads.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/papers/dynamic_checks/scripts/overheads.pdf -------------------------------------------------------------------------------- /papers/dynamic_checks/tables/bmdesc.tex: -------------------------------------------------------------------------------- 1 | % Table: A Description of our Benchmarks 2 | \centering 3 | \begin{tabular}{lrl} 4 | \toprule 5 | Name & \multicolumn{1}{c}{LoC} & Description \\ 6 | \midrule 7 | bh & 1,162 & Barnes \& Hut N-body force computation algorithm \\ 8 | bisort & 262 & Sorts using two disjoint bitonic sequences \\ 9 | em3d & 476 & Simulates electromagnetic waves in 3D \\ 10 | health & 338 & Simulates Colombian health-care system \\ 11 | mst & 325 & Computes minimum spanning tree using linked lists \\ 12 | perimeter & 399 & Computes perimeter of a set of quad-tree encoded images \\ 13 | power & 452 & The Power System Optimization problem \\ 14 | treadd & 180 & Computes the sum of values in a tree \\ 15 | tsp & 415 & Estimates solution for the Traveling-salesman problem \\ 16 | \emph{voronoi} & 814 & Computes voronoi diagram of a set of points \\ 17 | \addlinespace 18 | anagram & 346 & Generates anagrams from a list of words \\ 19 | \emph{bc} & 5,194 & An arbitrary precision calculator \\ 20 | ft & 893 & Computes minimum spanning tree using Fibonacci heaps \\ 21 | ks & 549 & Schweikert-Kernighan graph partitioning \\ 22 | yacr2 & 2,529 & VLSI channel router \\ 23 | \bottomrule 24 | \end{tabular} 25 | \caption{Compiler Benchmarks. Top group is the Olden suite, bottom 26 | group is the Ptrdist suite. LoC includes all comments and blank lines 27 | in benchmark source files. Descriptions are from 28 | \cite{Rogers1995Olden,Austin1994Ptrdist}. We were unable to convert 29 | \emph{voronoi} from the Olden suite and \emph{bc} from the Ptrdist suite using the current version of 30 | Checked C.} 31 | \label{tab:bmdesc} 32 | %%% Local Variables: 33 | %%% mode: latex 34 | %%% TeX-master: "../tr02" 35 | %%% End: 36 | -------------------------------------------------------------------------------- /papers/dynamic_checks/tables/bmresults.tex: -------------------------------------------------------------------------------- 1 | % Table of benchmark results 2 | \centering 3 | \begin{tabular}{lrrrrrr} 4 | \toprule 5 | & \multicolumn{3}{c}{Code Changes} 6 | & \multicolumn{3}{c}{Observed Overheads} \\ 7 | \addlinespace 8 | Benchmark 9 | & \multicolumn{1}{c}{\emph{LM} \%} 10 | & \multicolumn{1}{c}{\emph{EM} \%} 11 | & \multicolumn{1}{c}{\emph{LU} \%} 12 | & \multicolumn{1}{c}{\emph{RT} $\pm$\%} 13 | & \multicolumn{1}{c}{\emph{CT} $\pm$\%} 14 | & \multicolumn{1}{c}{\emph{ES} $\pm$\%} \\ 15 | \midrule 16 | \input{scripts/bm_results_tab} 17 | \bottomrule 18 | \end{tabular} 19 | \caption{Benchmark Results. Key: \emph{LM~\%}: 20 | Percentage of Source LoC Modified, including Additions; \emph{EM~\%}: 21 | Percentage of Code Modifications deemed to be Easy (see 22 | \ref{sec:eval-code-changes}); \emph{LU~\%}: Percentage of Lines 23 | remaining Unchecked; \emph{RT~$\pm$\%}: Percentage Change in Run Time; 24 | \emph{CT~$\pm$\%}: Percentage Change in Compile Time; 25 | \emph{ES~$\pm$\%}: Percentage Change in Executable Size 26 | (\texttt{.text} section only)} 27 | \label{tab:bmresults} 28 | 29 | 30 | %%% Local Variables: 31 | %%% mode: latex 32 | %%% TeX-master: "../tr02" 33 | %%% End: 34 | -------------------------------------------------------------------------------- /papers/dynamic_checks/tables/canonical.tex: -------------------------------------------------------------------------------- 1 | \centering 2 | \begin{tabular}{lll} 3 | \toprule 4 | Bounds Kind & Declaration & Canonical Bounds \\ 5 | \midrule 6 | Range & \boundsdecl{\ArrayptrT~p}{\bounds{\mv{l}}{\mv{u}}} & 7 | \bounds{\mv{l}}{\mv{u}} \\ 8 | Count & \boundsdecl{\ArrayptrT~p}{\boundscount{\mv{n}}} & 9 | \bounds{p}{p + \mv{n}} \\ 10 | Byte Count & \boundsdecl{\ArrayptrT~p}{\boundsbytecount{\mv{n}}} & 11 | \bounds{p}{((\Arrayptr{\kw{char}})p) + \mv{n}} \\ 12 | Singleton & \expr{\PtrT~p} & \bounds{p}{p + 1} \\ 13 | \addlinespace 14 | \emph{Array} & \expr{\mv{T}~a~\kwchecked[\mv{N}]} & 15 | \bounds{a}{a + \mv{N}} \\ 16 | \bottomrule 17 | \end{tabular} 18 | \caption{Canonical Bounds Expressions. In Canonical Bounds, the 19 | \expr{+} refers to C's pointer-integer addition operator, which adds 20 | integer multiples of the size of the pointer's referent type to the 21 | original pointer (hence the cast to \Arrayptr{\kw{char}} in the 22 | \kwbytecount{} case). The bounds on \emph{Array} are used when 23 | \expr{a} is converted from an array into a pointer, and \mv{N} must be 24 | constant.} 25 | \label{tab:canonical} 26 | %%% Local Variables: 27 | %%% mode: latex 28 | %%% TeX-master: "../tr02" 29 | %%% End: 30 | -------------------------------------------------------------------------------- /papers/dynamic_checks/tr02.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,openany,oneside]{book} 2 | \usepackage[left=1in,right=1in,top=1in,bottom=1in,headheight=14pt,headsep=14pt]{geometry} 3 | 4 | \usepackage[draft]{checked_c} 5 | 6 | \usepackage{bytefield} 7 | \usepackage{xspace} 8 | 9 | \title{Putting the Checks into Checked C \\% 10 | Checked C Technical Report Number 2} 11 | 12 | \author{Archibald Samuel Elliott} 13 | 14 | \date{31 October 2017} 15 | 16 | \hypersetup{% 17 | pdftitle={Putting the Checks into Checked C}, 18 | pdfauthor={Archibald Samuel Elliott}, 19 | pdfsubject={Checked C Technical Report Number 2} 20 | } 21 | 22 | \allowdisplaybreaks 23 | 24 | \input{scripts/bm_results_macros} 25 | 26 | \begin{document} 27 | 28 | \frontmatter 29 | \begin{titlepage} 30 | \begin{center} 31 | \vspace*{2in} 32 | {\huge Putting the Checks into Checked C \\} 33 | \vspace{0.5in} 34 | {Checked C Technical Report Number 2\medskip\\} 35 | {\makeatletter\@date\makeatother\\} 36 | \vspace{0.25in} 37 | {\large Archibald Samuel Elliott\medskip\\} 38 | {Paul G. Allen School,\\ 39 | University of Washington\\} 40 | \vspace{1in} 41 | {\it Summary \par} 42 | \begin{minipage}{5in} 43 | \input{abstract} 44 | \end{minipage} 45 | \end{center} 46 | \end{titlepage} 47 | 48 | \tableofcontents 49 | 50 | \mainmatter 51 | \input{introduction} 52 | \input{overview} 53 | \input{example} 54 | \input{propagation} 55 | \input{checks} 56 | \input{evaluation} 57 | \input{related_work} 58 | \input{conclusion} 59 | 60 | \appendix 61 | \addtocontents{toc}{% 62 | \protect\bigbreak 63 | {\large\bfseries \hfill Appendices\hfill } 64 | \protect\smallbreak 65 | } 66 | 67 | \bibliography{checkedc} 68 | \theendnotes 69 | \input{c_syntax} 70 | \input{propagation_rules} 71 | 72 | 73 | \end{document} 74 | -------------------------------------------------------------------------------- /presentations/Checked-C-UW-PLSE-Workshop'-Final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/presentations/Checked-C-UW-PLSE-Workshop'-Final.pdf -------------------------------------------------------------------------------- /presentations/Checked-C-UW-PLSE-Workshop-Final.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/presentations/Checked-C-UW-PLSE-Workshop-Final.pptx -------------------------------------------------------------------------------- /presentations/checkedc-presentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/presentations/checkedc-presentation.pptx -------------------------------------------------------------------------------- /presentations/llvmdevmeet2019-checkedc_for_memory_safety.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/presentations/llvmdevmeet2019-checkedc_for_memory_safety.pdf -------------------------------------------------------------------------------- /presentations/llvmdevmeet2020-checkedc_adding_memory_safety_to_llvm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/checkedc/checkedc-fork/d2ed3c9f36badc643a6ff98fea43af8a73bf7be9/presentations/llvmdevmeet2020-checkedc_adding_memory_safety_to_llvm.pdf -------------------------------------------------------------------------------- /samples/README.md: -------------------------------------------------------------------------------- 1 | # Sample Checked C code 2 | 3 | This directory contains some sample Checked C code: 4 | - [hello-world.c](hello-world.c): The canonical "hello, world" program, using Checked C. Show how to declare bounds for the array of arguments. 5 | - [echo-args.c](echo-args.c): Echo arguments to the output console. Use the array of arguments with bounds. 6 | - [echo-args-buggy.c](echo-args-buggy.c): A buggy version of [echo-args.c](echo-args.c) with an off-by-one error that tries to read past the end of the array of arguments. 7 | - [find-pattern.c](find-pattern.c): The "find pattern" program from Kernighan and Richie, rewritten to use Checked C. This program illustrates some subtle points about using strings in Checked C. 8 | - [string-helper.c](string-helpers.c): A short tutorial on using strings in Checked C, with Checked C versions of `atoi`, `squeeze`, `strcmp`, `strlen`, and `reverse`. 9 | + [avoid-warning.c](avoid-warning.c): This example shows how to use `dynamic_bounds_cast` to avoid a compile-time warning that the compiler cannot prove declared bounds are valid. 10 | - [spec](spec): Examples drawn from the Checked C specification. 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/avoid-warning.c: -------------------------------------------------------------------------------- 1 | // This example illustrates how to use dynamic_bounds_cast 2 | // to avoid a compile-time warning about being unable to 3 | // prove declared bounds. 4 | #include 5 | #include 6 | 7 | #pragma CHECKED_SCOPE ON 8 | 9 | extern void test(array_ptr p : count(len), int len); 10 | 11 | 12 | int main(int argc, nt_array_ptr argv checked[] : count(argc)) { 13 | int arr checked[5] = { 0, 1, 2, 3, 4 }; 14 | test(arr, 4); 15 | return 0; 16 | } 17 | 18 | void test(array_ptr p : count(len), int len) { 19 | // Code was originally: 20 | // array_ptr r : count(len - 1) = p + 1. 21 | array_ptr r : count(len - 1) = 22 | dynamic_bounds_cast>(p + 1, count(len - 1)); 23 | } 24 | -------------------------------------------------------------------------------- /samples/echo-args-buggy.c: -------------------------------------------------------------------------------- 1 | // This is a buggy version of a program that echos its arguments. 2 | // There's an off-by-one error when looping over the arguments. 3 | 4 | #include 5 | #include 6 | 7 | #pragma CHECKED_SCOPE ON 8 | 9 | int main(int argc, nt_array_ptr argv checked[] : count(argc)) { 10 | for (int i = 1; i <= argc; i++) { // introduce an off-by-one error. 11 | fputc(' ', stdout); 12 | fputs(argv[i], stdout); 13 | } 14 | fputc('\n', stdout); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /samples/echo-args.c: -------------------------------------------------------------------------------- 1 | // This program echos its arguments to its output. 2 | 3 | #include 4 | #include 5 | 6 | #pragma CHECKED_SCOPE ON 7 | 8 | int main(int argc, nt_array_ptr argv checked[] : count(argc)) { 9 | for (int i = 1; i < argc; i++) { 10 | if (i > 1) { 11 | fputc(' ', stdout); 12 | } 13 | fputs(argv[i], stdout); 14 | } 15 | fputc('\n', stdout); 16 | return 0; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /samples/exit-on-failure.c: -------------------------------------------------------------------------------- 1 | // This program shows how to use a signal handler to catch a runtime fault and 2 | // exit gracefully. The program reads an integer between 0 and 9 and prints 3 | // out the corresponding argument. If the integer is larger than the number of 4 | // arguments, the program will crash. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma CHECKED_SCOPE ON 12 | 13 | // The signal handling function. 14 | void handle_error(int err) { 15 | _Exit(1); 16 | } 17 | 18 | int main(int argc, nt_array_ptr argv checked[] : count(argc)) { 19 | // Set up the handler for a failing runtime check. A SIGILL is raised when a Checked C 20 | // runtime check fails. 21 | 22 | // BUG: Compiler crashes when this is done in a checked scope, so put it 23 | // in a unchecked scope. Checked C clang github issue #478. 24 | unchecked { signal(SIGILL, handle_error); } 25 | 26 | // Read the integer and print the corresponding argument. 27 | fputs("Enter a number between 0 and 9:", stdout); 28 | char c = fgetc(stdin); 29 | if (c < '0' || c > '9') { 30 | puts("\nInvalid number"); 31 | return 2; 32 | } 33 | fputs("Result = ", stdout); 34 | puts(argv[c - '0']); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /samples/hello-world.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #pragma CHECKED_SCOPE ON 5 | 6 | int main(int argc, nt_array_ptr argv checked[] : count(argc)) { 7 | puts("hello, world"); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /samples/spec/2_3_1_add.c: -------------------------------------------------------------------------------- 1 | // Simple Example of checked arrays, from Section 2.3.1 of the spec 2 | // 3 | 4 | #include 5 | 6 | void add(int a checked[2][2], int b checked[2][2]) { 7 | for (int i = 0; i < 2; i++) { 8 | for (int j = 0; j < 2; j++) { 9 | a[i][j] += b[i][j]; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/spec/2_7_checked.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, based on code in Section 2.7 of the spec 2 | 3 | #include 4 | 5 | void update(ptr a, int b checked[5][5]) { 6 | for (int i = 0; i < 5; i++) 7 | for (int j = 0; j < 5; j++) 8 | b[i][j] = *a; 9 | } 10 | -------------------------------------------------------------------------------- /samples/spec/2_8_append.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 2.8 of the spec 2 | 3 | #include 4 | #include 5 | 6 | void append(array_ptr dst : count(dst_count), 7 | array_ptr src : count(src_count), 8 | size_t dst_count, size_t src_count) { 9 | dynamic_check(src_count <= dst_count); 10 | for (size_t i = 0; i < src_count; i++) { 11 | if (src[i] == '\0') { 12 | break; 13 | } 14 | dst[i] = src[i]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/spec/3_11_compare.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 2.8 of the spec 2 | 3 | #include 4 | 5 | /* lexicographic comparison of two arrays of integers */ 6 | int compare(array_ptr x : bounds(x, x_end), 7 | array_ptr y : bounds(y, y_end), 8 | array_ptr x_end, array_ptr y_end) { 9 | while (x < x_end && y < y_end) { 10 | if (*x == *y) { 11 | x++; 12 | y++; 13 | } 14 | else if (*x < *y) { 15 | return -1; 16 | } 17 | else { 18 | return 1; 19 | } 20 | } 21 | if (x == x_end && y == y_end) { 22 | return 0; 23 | } 24 | else if (x != x_end) { 25 | return 1; 26 | } 27 | else { 28 | return -1; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /samples/spec/3_11_sum.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 2.8 of the spec 2 | 3 | #include 4 | 5 | /* sum integers stored between start and end, where end is not included */ 6 | int sum(array_ptr start : bounds(start, end), 7 | array_ptr end) { 8 | int result = 0; 9 | array_ptr current : bounds(start, end) = start; 10 | 11 | while (current < end) { 12 | result = *current; 13 | current += 1; 14 | } 15 | 16 | return result; 17 | } 18 | -------------------------------------------------------------------------------- /samples/spec/3_2_1_add.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.2.1 of the spec 2 | 3 | #include 4 | 5 | int add(int a checked[][2][2] : count(len), 6 | int b checked[][2][2] : count(len), 7 | int len) { 8 | for (int i = 0; i < len; i++) { 9 | a[i][0][0] += b[i][0][0]; 10 | a[i][0][1] += b[i][0][1]; 11 | a[i][1][0] += b[i][1][0]; 12 | a[i][1][1] += b[i][1][1]; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /samples/spec/3_2_1_find.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.2.1 of the spec 2 | 3 | #include 4 | 5 | int find(int key, array_ptr a: count(len), int len) { 6 | for (int i = 0; i < len; i++) { 7 | if (a[i] == key) { 8 | return i; 9 | } 10 | } 11 | return -1; 12 | } 13 | -------------------------------------------------------------------------------- /samples/spec/3_2_1_sum.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.2.1 of the spec 2 | 3 | #include 4 | 5 | int sum(array_ptr start : bounds(start, end), array_ptr end) { 6 | int result = 0; 7 | array_ptr current : bounds(start, end) = start; 8 | 9 | while (current < end) { 10 | result += *current++; 11 | } 12 | 13 | return result; 14 | } 15 | -------------------------------------------------------------------------------- /samples/spec/3_2_1_sum_extern.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.2.1 of the spec 2 | 3 | #include 4 | 5 | // external-scoped variables that hold a buffer and its length 6 | int buflen = 0; 7 | array_ptr buf : count(buflen) = NULL; 8 | 9 | int sum(void) { 10 | int result = 0; 11 | for (int i = 0; i < buflen; i++) { 12 | result += buf[i]; 13 | } 14 | return result; 15 | } 16 | -------------------------------------------------------------------------------- /samples/spec/3_2_2_find.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.2.2 of the spec 2 | 3 | #include 4 | 5 | array_ptr find(int key, 6 | array_ptr a : count(len), 7 | int len) : bounds(a, a+len) { 8 | for (int i = 0; i < len; i++) { 9 | if (a[i] == key) { 10 | return &a[i]; 11 | } 12 | } 13 | return NULL; 14 | } 15 | -------------------------------------------------------------------------------- /samples/spec/3_4_array_ptr.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.4 of the spec 2 | 3 | #include 4 | 5 | // Original Function 6 | int deref_orig(array_ptr x : bounds(x, x + c), int c) { 7 | int z = x[5]; 8 | return z; 9 | } 10 | 11 | // Function Equivalent after Code Generation 12 | int deref_code(ptr x : bounds(x, x + c), int c) { 13 | dynamic_check(x != NULL); 14 | int* t1 = x + 5; 15 | dynamic_check(t1 != NULL && x <= t1 && t1 < x + c); // simplifies to 5 < c 16 | int z = *t1; 17 | return z; 18 | } 19 | -------------------------------------------------------------------------------- /samples/spec/3_4_ptr.c: -------------------------------------------------------------------------------- 1 | // Simple Example of Checked C, from Section 3.4 of the spec 2 | 3 | #include 4 | 5 | // Original Function 6 | int deref_orig(ptr x : bounds(x, x + c), int c) { 7 | int z; 8 | z = *x; 9 | return z; 10 | } 11 | 12 | // Function Equivalent after Code Generation 13 | int deref_code(ptr x : bounds(x, x + c), int c) { 14 | int z; 15 | dynamic_check(x != NULL); 16 | dynamic_check(x <= x && x < x + c); 17 | z = *x; 18 | return z; 19 | } 20 | -------------------------------------------------------------------------------- /spec/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # ignore intermediate files created by LaTeX and BibTeX 3 | # 4 | 5 | *.aux 6 | *.bbl 7 | *.blg 8 | *.log 9 | *.toc 10 | *.out 11 | 12 | # Ignore output files created usng LaTeX too. 13 | 14 | *.pdf 15 | *.dvi 16 | -------------------------------------------------------------------------------- /spec/bounds_safety/README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | The Checked C specification is written using [LaTeX](https://latex-project.org/intro.html). 4 | LaTeX is used for preparing technical documents. LaTeX uses text-based files that work 5 | nicely with source-code control systems such as Git. The text-based files describe the 6 | content and structure of the document and some aspects of the appearance. LaTex processes 7 | the files to type set the document. 8 | 9 | # Type setting instructions 10 | 11 | You will need to have a version of LaTex installed on your computer. See the next 12 | section for information on how to obtain LaTex. To type set the specification, open a shell 13 | windows and run the following commands: 14 | 15 | pdflatex checkedc 16 | 17 | bibtex checkedc 18 | 19 | pdflatex checkedc 20 | 21 | pdflatex checkedc 22 | 23 | The multiple runs of pdflatex are needed so that cross-references converge. The 24 | resulting file will be called checkedc.pdf. 25 | 26 | # More information on LaTex. 27 | 28 | ## Obtaining LaTex 29 | There are many widely 30 | used free distributions of LaTex available. One version is [MikTex](http://www.miktex.org), 31 | which is widely used on Windows. Another version is [TexLive](http://tug.org/texlive/), 32 | which is often used on Linux system. 33 | 34 | ## Editing LaTex files 35 | 36 | Both distributions of LaTex install a nice editor for working with LaTex files called TexWorks. It has a feature where it will automatically run latex for you from the editor. Note that when using Texworks with MikTex, you should be sure to run pdflatex from the command-line before using the autorun feature so that the right packages are installed. 37 | 38 | ## Learning about LaTex 39 | 40 | For a very brief introduction to LaTex, read [A document for absolute LaTex beginners](http://ctan.org/pkg/first-latex-doc). A good starting point for learning about LaTex is a [A (Not So) Short Introduction to Latex2E] (http://ctan.org/pkg/lshort-english). 41 | 42 | -------------------------------------------------------------------------------- /spec/bounds_safety/abstract.tex: -------------------------------------------------------------------------------- 1 | % !Tex root = checkedc.tex 2 | 3 | \parbox{6.0in}{ 4 | There are large amounts of existing critical infrastructure and 5 | systems software written in C. This software is prone to 6 | low-level programming errors that lead to security vulnerabilities, 7 | correctness issues, and reliability problems. This specification describes 8 | Checked C, an extension to C designed to help improve the security and 9 | reliability of existing C code. 10 | } 11 | 12 | \vspace{11pt} 13 | 14 | \parbox{6.0in}{Checked C provides backwards-compatibility. 15 | It adds opt-in features for eliminating classes of errors that 16 | cause memory corruption, improved type-safety, and statically verifiable 17 | assertions. 18 | These features build on each other: avoiding memory corruption 19 | is needed for type-safety, and type-safety makes it easier 20 | to check properties of C programs. 21 | Checked C provides an alternative to rewriting existing C code in another 22 | language, which may be too costly or impractical.} 23 | 24 | \vspace{11pt} 25 | 26 | \parbox{6.0in}{Checked C adds new pointer types and array types 27 | with null-checking and bounds-checking. 28 | The pointer types 29 | are layout-compatible with existing pointer 30 | types, making Checked C code binary-compatible with existing C code. 31 | Pointer bounds are described using annotations on variable declarations. 32 | Bounds are checked at runtime before memory accesses. 33 | Compiler optimizations eliminate unnecessary runtime bounds checking. 34 | Static checking ensures the correctness of the bounds annotations.} 35 | 36 | \vspace{11pt} 37 | 38 | \parbox{6.0in}{Checked C also adds checked scopes. Checked scopes 39 | provide guarantees about the bounds-safety and type-safety of code 40 | in them. In checked 41 | scopes, only new bounds-checked and null-checked pointer types 42 | can be used. Type casts are also restricted to ensure type 43 | safety. Casts between void pointers and pointers to 44 | data that contains pointers are not allowed.} 45 | 46 | \vspace{11pt} 47 | 48 | \parbox{6.0in}{Checked C adds generic functions and structures 49 | and existential types. This lets many uses of void pointers be replaced 50 | with type-safe code. Generic type variables are treated as incomplete 51 | types and only single copies of functions are needed.} 52 | 53 | \vspace{11pt} -------------------------------------------------------------------------------- /spec/bounds_safety/changelog.tex: -------------------------------------------------------------------------------- 1 | \chapter*{Change log} 2 | 3 | \begin{table} 4 | \begin{tabular}{|l|l|l|} 5 | \hline 6 | Date & Author & Description \\ 7 | \hline 8 | June 21, 2023 & David Tarditi & Separate what is implemented from possible future \\ 9 | & & changes to avoid confusion. \\ 10 | \hline 11 | \end{tabular} 12 | \end{table} 13 | 14 | \pagebreak -------------------------------------------------------------------------------- /spec/bounds_safety/makefile: -------------------------------------------------------------------------------- 1 | PAPERNAME=checkedc 2 | FILES = abstract.tex \ 3 | bounds-declarations.tex \ 4 | changelog.tex \ 5 | checking-variable-bounds.tex \ 6 | core-extensions.tex \ 7 | design-alternatives.tex \ 8 | fragments.tex \ 9 | interoperation.tex \ 10 | introduction.tex \ 11 | lessons.tex \ 12 | related-work.tex \ 13 | roadmap.tex \ 14 | simple-invariants.tex \ 15 | span-compilation.tex \ 16 | void-ptr-replacements.tex \ 17 | sources.bib \ 18 | checkedc.tex 19 | 20 | all: $(PAPERNAME).pdf 21 | 22 | $(PAPERNAME).pdf: $(FILES) makefile 23 | pdflatex $(PAPERNAME) 24 | bibtex --min-crossrefs=300 $(PAPERNAME) 25 | pdflatex $(PAPERNAME) 26 | pdflatex $(PAPERNAME) 27 | 28 | clean: 29 | rm -f $(PAPERNAME).pdf *.dvi *.aux *.log *.blg *.bbl *~ 30 | -------------------------------------------------------------------------------- /spec/bounds_safety/pictures/build-pics.tex: -------------------------------------------------------------------------------- 1 | % 2 | % Simple stand-alone file for building just pictures. 3 | % Use this for a quick build/edit cycle for pictures. 4 | % 5 | 6 | \documentclass[11pt]{report} 7 | \usepackage{tikz} 8 | \usetikzlibrary{patterns} 9 | \begin{document} 10 | 11 | \include{rel-align-picture1} 12 | 13 | \relalignpic{4} 14 | 15 | \relalignpic{7} 16 | 17 | \end{document} -------------------------------------------------------------------------------- /spec/bounds_safety/pictures/rel-align-picture1.tex: -------------------------------------------------------------------------------- 1 | % This macro creates a picture of a short int array in memory with upper and 2 | % lower bound pointers y and z and a pointer to an element x of the array. 3 | % The macro takes a parameter that is the byte address of x. 4 | % 5 | % For example, \relalignpic{4} places the pointer to x at byte 4. 6 | 7 | \newcommand{\relalignpic}[1]{ 8 | \begin{tikzpicture} 9 | % use macros to name constants 10 | \newcommand{\rectsize}{20} 11 | \newcommand{\xindex}{#1} 12 | % the rectangle for the array object 13 | \filldraw[color=cyan!60] (2*\rectsize pt, 0) rectangle(8*\rectsize pt, \rectsize pt); 14 | % the rectangle for the element of the array pointed to by x 15 | \draw[pattern=north east lines] (\xindex * \rectsize pt, 0) 16 | rectangle(\xindex * \rectsize +2 * \rectsize pt, \rectsize pt); 17 | % the grid for memory cells 18 | \draw[step=\rectsize pt] (0,0) grid(12*\rectsize pt, \rectsize pt); 19 | % x, y, and z variables 20 | \draw (2* \rectsize pt + \rectsize/2, \rectsize*2.5 pt) node[name=y]{\lstinline|y|}; 21 | \draw (\xindex * \rectsize pt + \rectsize/2, \rectsize*2.5 pt) node[name=x]{\lstinline|x|}; 22 | \draw (8* \rectsize pt + \rectsize/2, \rectsize*2.5 pt) node[name=z]{\lstinline|z|}; 23 | % draw arrows from variables to memory cells 24 | \draw [->, semithick] (y.south) -- ++(0, \rectsize*-1 pt); 25 | \draw [->, semithick] (x.south) -- ++(0, \rectsize*-1 pt); 26 | \draw [->, semithick] (z.south) -- ++(0, \rectsize*-1 pt); 27 | % label memory cells 28 | \foreach \x in {0,...,11} 29 | { 30 | \draw (\x * \rectsize pt, - \rectsize / 2 pt) node[anchor=west]{a\textsubscript{\x}}; 31 | } 32 | \end{tikzpicture} 33 | } % \newcommand{\relalignpic} 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/checked_headers/redeclare_libs_explicit_linux.c: -------------------------------------------------------------------------------- 1 | // UNSUPPORTED: !linux 2 | // 3 | // Test include files for all combinations of Checked C enabled/disabled, 4 | // and implicit inclusion of checked headers enabled/disabled. By default, both 5 | // are enabled. 6 | // 7 | // Checked headers are disabled for no Checked C. 8 | // RUN: %clang -fno-checkedc-extension -E %s | FileCheck %s --check-prefix CHECK_DISABLED 9 | // RUN: %clang -fno-checkedc-extension -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 10 | // 11 | // Checked headers are enabled for Checked C and implicit inclusion. 12 | // RUN: %clang -E %s | FileCheck %s --check-prefix CHECK_ENABLED 13 | // 14 | // Checked headers are enabled because explicit inclusion overrides the 15 | // disabling of implicit inclusion. 16 | // RUN: %clang -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_ENABLED 17 | 18 | 19 | #if CHECKED_SCOPE 20 | #pragma CHECKED_SCOPE on 21 | #endif 22 | 23 | // C11 headers, supported on Linux but not Windows 24 | #include 25 | // CHECK_ENABLED: threads_checked.h 26 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 27 | // CHECK_DISABLED: threads_checked.h 28 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 29 | 30 | // Posix Headers 31 | // These header files are not present in the Windows compilation environment. 32 | #include 33 | // CHECK_ENABLED: unistd_checked.h 34 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 35 | // CHECK_DISABLED: unistd_checked.h 36 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 37 | 38 | #include 39 | // CHECK_ENABLED: socket_checked.h 40 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 41 | // CHECK_DISABLED: socket_checked.h 42 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 43 | 44 | #include 45 | // CHECK_ENABLED: stat_checked.h 46 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 47 | // CHECK_DISABLED: stat_checked.h 48 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 49 | 50 | #include 51 | // CHECK_ENABLED: inet_checked.h 52 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 53 | // CHECK_DISABLED: inet_checked.h 54 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 55 | 56 | #include 57 | // CHECK_ENABLED: grp_checked.h 58 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 59 | // CHECK_DISABLED: grp_checked.h 60 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 61 | 62 | #include 63 | // CHECK_ENABLED: netdb_checked.h 64 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 65 | // CHECK_DISABLED: netdb_checked.h 66 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 67 | 68 | #include 69 | // CHECK_ENABLED: poll_checked.h 70 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 71 | // CHECK_DISABLED: poll_checked.h 72 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 73 | 74 | #include 75 | // CHECK_ENABLED: pwd_checked.h 76 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 77 | // CHECK_DISABLED: pwd_checked.h 78 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 79 | 80 | #include 81 | // CHECK_ENABLED: syslog_checked.h 82 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 83 | // CHECK_DISABLED: syslog_checked.h 84 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 85 | 86 | #include 87 | // CHECK_ENABLED: utime_checked.h 88 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 89 | // CHECK_DISABLED: utime_checked.h 90 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 91 | 92 | -------------------------------------------------------------------------------- /tests/checked_headers/redeclare_libs_implicit.c: -------------------------------------------------------------------------------- 1 | // Feature tests of typechecking bounds-safe 2 | // interfaces for the C standard library. 3 | // 4 | // The following lines are for the LLVM test harness: 5 | // 6 | // Test include files in an unchecked scope 7 | // 8 | // RUN: %clang -fsyntax-only %s 9 | // RUN: %clang -fsyntax-only -D_FORTIFY_SOURCE=0 %s 10 | // RUN: %clang -fsyntax-only -D_FORTIFY_SOURCE=1 %s 11 | // RUN: %clang -fsyntax-only -D_FORTIFY_SOURCE=2 %s 12 | // 13 | // Test include files in a checked scope. 14 | // 15 | // RUN: %clang -fsyntax-only -DCHECKED_SCOPE=1 %s 16 | // RUN: %clang -fsyntax-only -D_FORTIFY_SOURCE=0 -DCHECKED_SCOPE=1 %s 17 | // RUN: %clang -fsyntax-only -D_FORTIFY_SOURCE=1 -DCHECKED_SCOPE=1 %s 18 | // RUN: %clang -fsyntax-only -D_FORTIFY_SOURCE=2 -DCHECKED_SCOPE=1 %s 19 | // 20 | // Test include files for all combinations of Checked C enabled/disabled, 21 | // and implicit inclusion of checked headers enabled/disabled. By default, both 22 | // are enabled. 23 | // 24 | // Checked headers are disabled for no Checked C. 25 | // RUN: %clang -fno-checkedc-extension -E %s | FileCheck %s --check-prefix CHECK_DISABLED 26 | // RUN: %clang -fno-checkedc-extension -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 27 | // 28 | // Checked headers are enabled for Checked C and implicit inclusion. 29 | // RUN: %clang -E %s | FileCheck %s --check-prefix CHECK_ENABLED 30 | // 31 | // Checked headers are disabled because implicit inclusion is disabled. 32 | // RUN: %clang -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 33 | 34 | 35 | #if CHECKED_SCOPE 36 | #pragma CHECKED_SCOPE on 37 | #endif 38 | 39 | // C Standard 40 | #include 41 | // CHECK_ENABLED: assert_checked.h 42 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 43 | // CHECK_DISABLED-NOT: assert_checked.h 44 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 45 | 46 | #include 47 | // CHECK_ENABLED: errno_checked.h 48 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 49 | // CHECK_DISABLED-NOT: errno_checked.h 50 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 51 | 52 | #include 53 | // CHECK_ENABLED: fenv_checked.h 54 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 55 | // CHECK_DISABLED-NOT: fenv_checked.h 56 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 57 | 58 | #include 59 | // CHECK_ENABLED: inttypes_checked_internal.h 60 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 61 | // CHECK_DISABLED-NOT: inttypes_checked_internal.h 62 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 63 | 64 | #include 65 | // CHECK_ENABLED: math_checked.h 66 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 67 | // CHECK_DISABLED-NOT: math_checked.h 68 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 69 | 70 | #include 71 | // CHECK_ENABLED: signal_checked.h 72 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 73 | // CHECK_DISABLED-NOT: signal_checked.h 74 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 75 | 76 | #include 77 | // CHECK_ENABLED: stdio_checked.h 78 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 79 | // CHECK_DISABLED-NOT: stdio_checked.h 80 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 81 | 82 | #include 83 | // CHECK_ENABLED: stdlib_checked.h 84 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 85 | // CHECK_DISABLED-NOT: stdlib_checked.h 86 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 87 | 88 | #include 89 | // CHECK_ENABLED: string_checked.h 90 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 91 | // CHECK_DISABLED-NOT: string_checked.h 92 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 93 | 94 | #include 95 | // CHECK_ENABLED: time_checked.h 96 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 97 | // CHECK_DISABLED-NOT: time_checked.h 98 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 99 | 100 | // Headers that are not in the C standard but are still present on Windows 101 | 102 | #include 103 | // CHECK_ENABLED: fcntl_checked.h 104 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 105 | // CHECK_DISABLED-NOT: fcntl_checked.h 106 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 107 | -------------------------------------------------------------------------------- /tests/checked_headers/redeclare_libs_implicit_linux.c: -------------------------------------------------------------------------------- 1 | // UNSUPPORTED: !linux 2 | // 3 | // Test include files for all combinations of Checked C enabled/disabled, 4 | // and implicit inclusion of checked headers enabled/disabled. By default, both 5 | // are enabled. 6 | // 7 | // Checked headers are disabled for no Checked C. 8 | // RUN: %clang -fno-checkedc-extension -E %s | FileCheck %s --check-prefix CHECK_DISABLED 9 | // RUN: %clang -fno-checkedc-extension -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 10 | // 11 | // Checked headers are enabled for Checked C and implicit inclusion. 12 | // RUN: %clang -E %s | FileCheck %s --check-prefix CHECK_ENABLED 13 | // 14 | // Checked headers are disabled because implicit inclusion is disabled. 15 | // RUN: %clang -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 16 | 17 | // C11 headers supported on Linux, but not on Windows 18 | #define _CHECKEDC_MOCKUP_THREADS 1 19 | #include 20 | // CHECK_ENABLED: threads_checked.h 21 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 22 | // CHECK_DISABLED-NOT: threads_checked.h 23 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 24 | 25 | // Posix Headers 26 | // These header files are not present in the Windows compilation environment. 27 | #include 28 | // CHECK_ENABLED: unistd_checked.h 29 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 30 | // CHECK_DISABLED-NOT: unistd_checked.h 31 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 32 | 33 | #include 34 | // CHECK_ENABLED: socket_checked.h 35 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 36 | // CHECK_DISABLED-NOT: socket_checked.h 37 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 38 | 39 | #include 40 | // CHECK_ENABLED: stat_checked.h 41 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 42 | // CHECK_DISABLED-NOT: stat_checked.h 43 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 44 | 45 | #include 46 | // CHECK_ENABLED: inet_checked.h 47 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 48 | // CHECK_DISABLED-NOT: inet_checked.h 49 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 50 | 51 | #include 52 | // CHECK_ENABLED: grp_checked.h 53 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 54 | // CHECK_DISABLED-NOT: grp_checked.h 55 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 56 | 57 | #include 58 | // CHECK_ENABLED: netdb_checked.h 59 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 60 | // CHECK_DISABLED-NOT: netdb_checked.h 61 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 62 | 63 | #include 64 | // CHECK_ENABLED: poll_checked.h 65 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 66 | // CHECK_DISABLED-NOT: poll_checked.h 67 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 68 | 69 | #include 70 | // CHECK_ENABLED: pwd_checked.h 71 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 72 | // CHECK_DISABLED-NOT: pwd_checked.h 73 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 74 | 75 | #include 76 | // CHECK_ENABLED: syslog_checked.h 77 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 78 | // CHECK_DISABLED-NOT: syslog_checked.h 79 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 80 | 81 | #include 82 | // CHECK_ENABLED: utime_checked.h 83 | // CHECK_ENABLED: #pragma CHECKED_SCOPE on 84 | // CHECK_DISABLED-NOT: utime_checked.h 85 | // CHECK_DISABLED-NOT: #pragma CHECKED_SCOPE on 86 | -------------------------------------------------------------------------------- /tests/checked_headers/redeclare_libs_mixed.c: -------------------------------------------------------------------------------- 1 | // Feature tests of typechecking bounds-safe 2 | // interfaces for the C standard library. 3 | // 4 | // Test include files for all combinations of Checked C enabled/disabled, 5 | // and implicit inclusion of checked headers enabled/disabled. By default, both 6 | // are enabled. 7 | // 8 | // Checked headers are disabled for no Checked C. 9 | // Already tested in redeclare_libs_explicit.c and redeclare_libs_implicit.c. 10 | // %clang -fno-checkedc-extension -E %s | FileCheck %s --check-prefix CHECK_DISABLED 11 | // %clang -fno-checkedc-extension -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 12 | // 13 | // Checked headers are enabled for Checked C and implicit inclusion. 14 | // Already tested in redeclare_libs_explicit.c and redeclare_libs_implicit.c. 15 | // %clang -E %s | FileCheck %s --check-prefix CHECK_ENABLED 16 | // 17 | // Checked headers are enabled/disabled depending on whether foo.h or 18 | // foo_checked.h is included for a system header file foo.h. 19 | // RUN: %clang -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_MIXED 20 | 21 | 22 | // C Standard 23 | #include 24 | // CHECK_MIXED: assert_checked.h 25 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 26 | 27 | #include 28 | // CHECK_MIXED-NOT: errno_checked.h 29 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 30 | 31 | #include 32 | // CHECK_MIXED: fenv_checked.h 33 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 34 | 35 | #include 36 | // CHECK_MIXED-NOT: inttypes_checked_internal.h 37 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 38 | 39 | #include 40 | // CHECK_MIXED: math_checked.h 41 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 42 | 43 | #include 44 | // CHECK_MIXED-NOT: signal_checked.h 45 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 46 | 47 | #include 48 | // CHECK_MIXED: stdio_checked.h 49 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 50 | 51 | #include 52 | // CHECK_MIXED-NOT: stdlib_checked.h 53 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 54 | 55 | #include 56 | // CHECK_MIXED: string_checked.h 57 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 58 | 59 | #include 60 | // CHECK_MIXED: time_checked.h 61 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 62 | 63 | // Headers that are not in the C standard but are still present on Windows 64 | 65 | #include 66 | // CHECK_MIXED-NOT: fcntl_checked.h 67 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 68 | 69 | #include 70 | // CHECK_MIXED: checkedc_extensions.h 71 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 72 | -------------------------------------------------------------------------------- /tests/checked_headers/redeclare_libs_mixed_linux.c: -------------------------------------------------------------------------------- 1 | // UNSUPPORTED: !linux 2 | // 3 | // Test include files for all combinations of Checked C enabled/disabled, 4 | // and implicit inclusion of checked headers enabled/disabled. By default, both 5 | // are enabled. 6 | // 7 | // Checked headers are disabled for no Checked C. 8 | // Already tested in redeclare_libs_explicit.c and redeclare_libs_implicit.c. 9 | // %clang -fno-checkedc-extension -E %s | FileCheck %s --check-prefix CHECK_DISABLED 10 | // %clang -fno-checkedc-extension -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_DISABLED 11 | // 12 | // Checked headers are enabled for Checked C and implicit inclusion. 13 | // Already tested in redeclare_libs_explicit.c and redeclare_libs_implicit.c. 14 | // %clang -E %s | FileCheck %s --check-prefix CHECK_ENABLED 15 | // 16 | // Checked headers are enabled/disabled depending on whether foo.h or 17 | // foo_checked.h is included for a system header file foo.h. 18 | // RUN: %clang -DNO_IMPLICIT_INCLUDE_CHECKED_HDRS -E %s | FileCheck %s --check-prefix CHECK_MIXED 19 | 20 | // C11 headers, supported on Linux but not Windows 21 | #include 22 | // CHECK_MIXED-NOT: threads_checked.h 23 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 24 | 25 | // Posix Headers 26 | // These header files are not present in the Windows compilation environment. 27 | #include 28 | // CHECK_MIXED: unistd_checked.h 29 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 30 | 31 | #include 32 | // CHECK_MIXED-NOT: socket_checked.h 33 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 34 | 35 | #include 36 | // CHECK_MIXED: stat_checked.h 37 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 38 | 39 | #include 40 | // CHECK_MIXED: inet_checked.h 41 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 42 | 43 | #include 44 | // CHECK_MIXED-NOT: grp_checked.h 45 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 46 | 47 | #include 48 | // CHECK_MIXED: netdb_checked.h 49 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 50 | 51 | #include 52 | // CHECK_MIXED-NOT: poll_checked.h 53 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 54 | 55 | #include 56 | // CHECK_MIXED: pwd_checked.h 57 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 58 | 59 | #include 60 | // CHECK_MIXED-NOT: syslog_checked.h 61 | // CHECK_MIXED-NOT: #pragma CHECKED_SCOPE on 62 | 63 | #include 64 | // CHECK_MIXED: utime_checked.h 65 | // CHECK_MIXED: #pragma CHECKED_SCOPE on 66 | -------------------------------------------------------------------------------- /tests/dynamic_checking/README.md: -------------------------------------------------------------------------------- 1 | # High-Level Dynamic Check Tests 2 | 3 | These tests all compile and run programs, making sure that their 4 | dynamic behaviour includes exiting/stopping when dynamic checks fail. 5 | 6 | ## Bounds-checking Tests 7 | 8 | There are 5 different tests of bounds checking, with each test covering a 9 | different kind of l-value-producing expression. The tests are in the 10 | bounds subdirectory: 11 | 12 | - `deref`. This is for `*` applied to variables. 13 | - `deref-arith`. This is for `*` applied to pointer arithmetic expressions. 14 | - `deref-member-expr`. This is for `*` applied to member accesses using 15 | the `.` or `->` operators. 16 | - `subscript` This is for `[]` applied to array variables. 17 | - `subscript-member-expr`. This is for `[]` applied to member accesses using 18 | `.` or the `->` operator. 19 | 20 | We still need to write tests for `.` where the base expression requires a bounds 21 | check and `->`, where the `->` incorporates a bound check. 22 | 23 | Each test is compiled 4 different ways with the following operators applied to 24 | different versions of the l-value-producing expression. 25 | Macro names are used to control the operator used in one 26 | instance of the test. The macro names are: 27 | 28 | - `TEST_READ` reads the lvalue (aka does an "l-value conversion") 29 | - `TEST_WRITE` assigns into the l-value with `=` 30 | - `TEST_INCREMENT` applies `++` (post-increment) to the l-value 31 | - `TEST_COMPOUND_ASSIGN` applies compound assignment (such as `+=`, `-=`) to the l-value 32 | Each of these tests has an unoptimized and optimized version. The optimized version ends in `-opt.c' 33 | 34 | The test file for `subscript` is re-used for `deref-arith`. The file 35 | `deref-arith` only contains test suite driver commands. 36 | 37 | This results in 56 total test configurations at the current count. There are 8 test 38 | configurations each for `deref`, `deref-artih`, and `subscript`: 4 operators 39 | using the lvalue expression x 2 optimization configurations. There are 16 test 40 | configurations for `deref-member-expr` and `subscript-member-expr`: 4 operators 41 | x 2 optimization configurations x 2 kinds of member expression operators. 42 | 43 | *Note:* do not use the words "install", "setup", "update" in test names where the files 44 | will be compiled and executed. Windows x86 has heuristics that decide executables with those 45 | words in the name need elevated privileges to run because they might be an installer, 46 | even if they don't actually install anything. Documentation is here: 47 | https://msdn.microsoft.com/en-us/enus/library/aa905330.aspx 48 | 49 | ### Optimised versions 50 | 51 | Each of these tests has an optimized counterpart, (the files with `-opt` as 52 | a filename suffix). This runs the original test, but with `-O3`, and tests 53 | against the same source file using FileCheck. This is so that we know high levels 54 | of optimization don't delete our dynamic checks. 55 | 56 | ## `Dynamic_check` Tests 57 | 58 | Tests in the `dynamic_check` subdirectory test the `dynamic_check` builtin. 59 | These are not duplicated in the same way as the tests above. 60 | -------------------------------------------------------------------------------- /tests/dynamic_checking/bounds/deref_opt.c: -------------------------------------------------------------------------------- 1 | // Test runtime bounds checking of uses of pointer dereference expressions with 2 | // optimization enabled. 3 | // 4 | // Uses are tested in read, assignment,increment, and compound assignment 5 | // expressions. 6 | // 7 | // This builds the file `deref.c` at optimisation level O3, 8 | // outputting executables at %tn. We then run these with the same arguments as 9 | // we run the unoptimised binaries with, and use FileCheck to ensure the 10 | // output is what we expected, as specified in `deref.c`. This 11 | // is run as a separate test so we know if optimisation is breaking some 12 | // dynamic checks. 13 | // 14 | // The following lines are for the clang automated test suite. 15 | // 16 | // RUN: %clang %S/deref.c -o %t1 -DTEST_READ -Werror -Wno-unused-value -Wno-check-bounds-decls-unchecked-scope -O3 %checkedc_target_flags 17 | // RUN: %checkedc_rununder %t1 pass1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-1-READ 18 | // RUN: %checkedc_rununder %t1 pass2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-2-READ 19 | // RUN: %checkedc_rununder %t1 pass3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-3-READ 20 | // RUN: %checkedc_rununder %t1 fail1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-1 21 | // RUN: %checkedc_rununder %t1 fail2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-2 22 | // RUN: %checkedc_rununder %t1 fail3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-3 23 | // RUN: %checkedc_rununder %t1 fail4 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-4 24 | // 25 | // RUN: %clang %S/deref.c -o %t2 -DTEST_WRITE -Werror -Wno-check-bounds-decls-unchecked-scope -O3 %checkedc_target_flags 26 | // RUN: %checkedc_rununder %t2 pass1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-1-WRITE 27 | // RUN: %checkedc_rununder %t2 pass2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-2-WRITE 28 | // RUN: %checkedc_rununder %t2 pass3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-3-WRITE 29 | // RUN: %checkedc_rununder %t2 fail1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-1 30 | // RUN: %checkedc_rununder %t2 fail2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-2 31 | // RUN: %checkedc_rununder %t2 fail3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-3 32 | // RUN: %checkedc_rununder %t2 fail4 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-4 33 | 34 | // RUN: %clang %S/deref.c -o %t3 -DTEST_INCREMENT -Werror -Wno-check-bounds-decls-unchecked-scope -O3 %checkedc_target_flags 35 | // RUN: %checkedc_rununder %t3 pass1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-1-INCREMENT 36 | // RUN: %checkedc_rununder %t3 pass2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-2-INCREMENT 37 | // RUN: %checkedc_rununder %t3 pass3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-3-INCREMENT 38 | // RUN: %checkedc_rununder %t3 fail1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-1 39 | // RUN: %checkedc_rununder %t3 fail2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-2 40 | // RUN: %checkedc_rununder %t3 fail3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-3 41 | // RUN: %checkedc_rununder %t3 fail4 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-4 42 | 43 | // RUN: %clang %S/deref.c -o %t4 -DTEST_COMPOUND_ASSIGN -Werror -Wno-check-bounds-decls-unchecked-scope -O3 %checkedc_target_flags 44 | // RUN: %checkedc_rununder %t4 pass1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-1-COMPOUND-ASSIGN 45 | // RUN: %checkedc_rununder %t4 pass2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-2-COMPOUND-ASSIGN 46 | // RUN: %checkedc_rununder %t4 pass3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-PASS,PASS-3-COMPOUND-ASSIGN 47 | // RUN: %checkedc_rununder %t4 fail1 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-1 48 | // RUN: %checkedc_rununder %t4 fail2 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-2 49 | // RUN: %checkedc_rununder %t4 fail3 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-3 50 | // RUN: %checkedc_rununder %t4 fail4 | FileCheck %S/deref.c --check-prefixes=CHECK,CHECK-FAIL,FAIL-4 51 | 52 | #import 53 | 54 | int main(void) { 55 | return EXIT_FAILURE; 56 | } 57 | -------------------------------------------------------------------------------- /tests/dynamic_checking/bounds/predefined_literals.c: -------------------------------------------------------------------------------- 1 | // Test bounds on predefined literals. 2 | // 3 | // RUN: %clang %s -o %t1 %checkedc_target_flags 4 | 5 | // RUN: %checkedc_rununder %t1 1 | FileCheck %s --check-prefix PASS1 6 | // RUN: %checkedc_rununder %t1 100 | FileCheck %s --check-prefix FAIL1 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void handle_error(int err) { 14 | puts("Error: out-of-bounds access of predefined literal"); 15 | _Exit(0); 16 | } 17 | 18 | void pass1(_Ptr s) { 19 | // PASS1: main 20 | // PASS1-NEXT: pass1 21 | // PASS1-NEXT: p 22 | // PASS1-NEXT: a 23 | // PASS1-NEXT: s 24 | // PASS1-NEXT: s 25 | // PASS1-NEXT: 1 26 | printf("%s\n", s); 27 | printf("%s\n", __func__); 28 | printf("%c\n", __func__[0]); 29 | printf("%c\n", __func__[1]); 30 | printf("%c\n", __func__[2]); 31 | printf("%c\n", __func__[3]); 32 | printf("%c\n", __func__[4]); 33 | } 34 | 35 | void fail1(int x) { 36 | // FAIL1: Error: out-of-bounds access of predefined literal 37 | #pragma CHECKED_SCOPE ON 38 | char c = __func__[x]; 39 | #pragma CHECKED_SCOPE OFF 40 | } 41 | 42 | int main(int argc, array_ptr argv : count(argc)) { 43 | // Set up the handler for a failing bounds check. Currently the Checked C 44 | // clang implementation raises a SIGILL or SIGTRAP when a bounds check fails, 45 | // depending on the target platform. This may change in the future. 46 | signal(SIGILL, handle_error); 47 | #if defined(__APPLE__) && defined(__aarch64__) 48 | signal(SIGTRAP, handle_error); 49 | #endif 50 | 51 | // This makes sure output is not buffered for when 52 | // we hit errors. 53 | int err = setvbuf(stdout, NULL, _IONBF, 0); 54 | if (err) { 55 | // CHECK-NOT: Error Setting Up Buffering 56 | puts("Error Setting Up Buffering"); 57 | return EXIT_FAILURE; 58 | } 59 | 60 | if (argc < 2) { 61 | // CHECK-NOT: Requires Argument 62 | puts("Requires Argument"); 63 | return EXIT_FAILURE; 64 | } 65 | 66 | int testcase = atoi(argv[1]); 67 | switch (testcase) { 68 | case 1: 69 | pass1(__func__); 70 | break; 71 | case 100: 72 | fail1(100); 73 | break; 74 | 75 | default: 76 | // CHECK-NOT: Unexpected test case 77 | puts("Unexpected test case"); 78 | return EXIT_FAILURE; 79 | } 80 | return EXIT_SUCCESS; 81 | } 82 | -------------------------------------------------------------------------------- /tests/dynamic_checking/checked_headers/ext.c: -------------------------------------------------------------------------------- 1 | // Tests for calling functions declared in checkedc_extensions.h 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang -o %t.exe %s %checkedc_target_flags 6 | // RUN: %checkedc_rununder %t.exe 7 | 8 | // expected-no-diagnostics 9 | 10 | #pragma CHECKED_SCOPE on 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | // A function with an interface similar to snprintf but without the variable 17 | // number of arguments. The purpose is to test such a call interface in checked 18 | // scope. 19 | void iface(char * restrict s _Itype( char* _Nt_array restrict) count(n-1), 20 | size_t n _Where( n > 0), 21 | const char * restrict src _Itype( const char* _Nt_array restrict)) { 22 | return; 23 | } 24 | 25 | 26 | void iface_array_ptr(char * restrict s : itype(restrict _Array_ptr) count(n), 27 | size_t n, 28 | const char * restrict src : itype(restrict _Array_ptr)) { 29 | // Enclosing the call to iface in an unchecked block to be able to pass an 30 | // argument of type _Array_ptr and bounds count(n) whose corresponding 31 | // parameter has the interface type _Nt_array_ptr and bounds count(n-1). 32 | // This avoids the compiler error: passing '_Array_ptr restrict' to 33 | // parameter of incompatible type '_Nt_array_ptr'. 34 | _Unchecked{ iface(s, n, src); } 35 | } 36 | 37 | 38 | 39 | void iface_test1(char* _Array p _Count(len), size_t len) { 40 | 41 | char buf _Checked[50]; 42 | iface_array_ptr(buf, 50, "Hello world"); 43 | iface_array_ptr(buf, 0, "Hello world"); 44 | 45 | iface_array_ptr(p, len, "Hello world"); 46 | iface_array_ptr(p, 0, "Hello world"); 47 | } 48 | 49 | void iface_test2(_Nt_array_ptr p : count(len), size_t len) { 50 | char buf _Nt_checked[50]; 51 | iface(buf, 50, "Hello world"); 52 | 53 | iface(p, len + 1, "Hello world"); 54 | } 55 | 56 | void test3(char* _Array buf _Count(len), size_t len) { 57 | _Unchecked{ snprintf_array_ptr(buf, len, "Hello world - 3"); } 58 | } 59 | 60 | int main(void) { 61 | char buf _Checked[50]; 62 | test3(buf, 50) ; 63 | char buf1 _Checked[50]; 64 | test3(buf1, 50) ; 65 | int res = strncmp_array_ptr(buf, buf1, 50); 66 | _Unchecked {printf("res: %d buf: %s buf1: %s\n", res, buf, buf1);} 67 | } 68 | -------------------------------------------------------------------------------- /tests/dynamic_checking/dynamic_check/arith-fail.c: -------------------------------------------------------------------------------- 1 | // Feature tests of dynamic checking in Checked C 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang -Xclang -verify -o %t.exe %s %checkedc_target_flags 6 | // LLVM thinks that exiting via llvm.trap() is a crash. 7 | // RUN: %checkedc_rununder %t.exe 8 | 9 | // The dynamic_check in f1 cannot be statically checked by clang yet 10 | // expected-no-diagnostics 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | void f1(int i) { 17 | // This is expected fail at runtime 18 | dynamic_check(i < 30); 19 | } 20 | 21 | void handle_error(int err) { 22 | _Exit(0); 23 | } 24 | 25 | int main(void) { 26 | // Set up the handler for a failing dynamic check. Currently the Checked C 27 | // clang implementation raises a SIGILL or SIGTRAP when a dynamic check fails, 28 | // depending on the target platform. This may change in the future. 29 | signal(SIGILL, handle_error); 30 | #if defined(__APPLE__) && defined(__aarch64__) 31 | signal(SIGTRAP, handle_error); 32 | #endif 33 | 34 | f1(50); 35 | 36 | return 1; 37 | } 38 | -------------------------------------------------------------------------------- /tests/dynamic_checking/dynamic_check/arith-pass.c: -------------------------------------------------------------------------------- 1 | // Feature tests of dynamic checking in Checked C 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang -Xclang -verify -o %t.exe %s %checkedc_target_flags 6 | // RUN: %checkedc_rununder %t.exe 7 | 8 | // expected-no-diagnostics 9 | 10 | #include 11 | 12 | void f1(int i) { 13 | dynamic_check(i < 30); 14 | } 15 | 16 | int main(void) { 17 | f1(10); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /tests/dynamic_checking/dynamic_check/simple-fail.c: -------------------------------------------------------------------------------- 1 | // Feature tests of dynamic checking in Checked C 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN %clang -### 6 | // RUN: %clang -Xclang -verify -o %t.exe %s %checkedc_target_flags 7 | // RUN: %checkedc_rununder %t.exe 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void handle_error(int err) { 15 | _Exit(0); 16 | } 17 | 18 | int main(void) { 19 | // Set up the handler for a failing dynamic check. Currently the Checked C 20 | // clang implementation raises a SIGILL or SIGTRAP when a dynamic check fails, 21 | // depending on the target platform. This may change in the future. 22 | signal(SIGILL, handle_error); 23 | #if defined(__APPLE__) && defined(__aarch64__) 24 | signal(SIGTRAP, handle_error); 25 | #endif 26 | 27 | // This is expected fail at runtime. It is simple enough for clang to issue a warning 28 | dynamic_check(false); // expected-warning {{dynamic check will always fail}} 29 | 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /tests/dynamic_checking/dynamic_check/simple-pass.c: -------------------------------------------------------------------------------- 1 | // Feature tests of dynamic checking in Checked C 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang -Xclang -verify -o %t.exe %s %checkedc_target_flags 6 | // RUN: %checkedc_rununder %t.exe 7 | 8 | // expected-no-diagnostics 9 | 10 | #include 11 | #include 12 | 13 | int main(void) { 14 | dynamic_check(true); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /tests/exist_types_runtest/callbacks.c: -------------------------------------------------------------------------------- 1 | // This test shows how existential types can be used in combination 2 | // with generic functions and structs to create type-safe callback library 3 | // and client code. 4 | // 5 | // RUN: %clang %s -o %t1 %checkedc_target_flags 6 | 7 | // RUN: %checkedc_rununder %t1 -DARR | FileCheck %s --check-prefix TEST 8 | 9 | 10 | #include 11 | #include 12 | 13 | // Library code 14 | 15 | #define MAX_CB 100 16 | 17 | typedef int event_id; 18 | 19 | #define EVENT_START 0 20 | #define EVENT_PAUSE 1 21 | #define EVENT_STOP 2 22 | 23 | struct cb_info _For_any(T) { 24 | T *data; 25 | void (*cb)(event_id id, T *data); 26 | }; 27 | 28 | struct map_entry { 29 | event_id id; 30 | _Exists(T, struct cb_info) info; 31 | }; 32 | 33 | int num_entries = 0; 34 | struct map_entry cb_map[MAX_CB]; 35 | 36 | _For_any(T) void reg_cb(event_id id, struct cb_info info) { 37 | _Exists(A, struct cb_info) opaque_info = _Pack(info, _Exists(A, struct cb_info), T); 38 | struct map_entry entry; 39 | entry.id = id; 40 | entry.info = opaque_info; 41 | cb_map[num_entries] = entry; 42 | num_entries += 1; 43 | } 44 | 45 | void handle(event_id id) { 46 | for (int i = 0; i < num_entries; i++) { 47 | if (cb_map[i].id == id) { 48 | _Unpack (T) struct cb_info cb_inf = cb_map[i].info; 49 | cb_inf.cb(id, cb_inf.data); 50 | } 51 | } 52 | } 53 | 54 | // User code 55 | void cb_start(event_id id, char *task_name) { 56 | printf("cb_start: id = %d, task_name = %s\n", id, task_name); 57 | } 58 | 59 | void cb_pause(event_id id, int *resume_in) { 60 | printf("cb_pause: id = %d, resume_in = %ds\n", id, *resume_in); 61 | } 62 | 63 | struct continue_info { 64 | int follow_by; 65 | }; 66 | 67 | void cb_stop(event_id id, struct continue_info *info) { 68 | printf("cb_stop: id = %d, follow_by = %d\n", id, info->follow_by); 69 | } 70 | 71 | void client_register() { 72 | struct cb_info start_info = { "task1", &cb_start }; 73 | struct cb_info start_info2 = { "task2", &cb_start }; 74 | 75 | // Unfortunately, we need to malloc the client-passed arguments to the callback. 76 | // This is because type parameters can only appear as pointers inside generic structs. 77 | // Eventually, we relax this constraint. 78 | int *resume_in = (int *) malloc(sizeof(int)); 79 | *resume_in = 42; 80 | struct cb_info pause_info = { resume_in, &cb_pause }; 81 | 82 | struct continue_info *cont_info = (struct continue_info *) malloc(sizeof(struct continue_info)); 83 | cont_info->follow_by = 100; 84 | struct cb_info stop_info = { cont_info, &cb_stop }; 85 | 86 | reg_cb(EVENT_START, start_info); 87 | reg_cb(EVENT_START, start_info2); 88 | reg_cb(EVENT_PAUSE, pause_info); 89 | reg_cb(EVENT_STOP, stop_info); 90 | } 91 | 92 | int main(int argc, char *argv[]) { 93 | client_register(); 94 | handle(EVENT_START); 95 | // TEST: cb_start: id = 0, task_name = task1 96 | // TEST: cb_start: id = 0, task_name = task2 97 | 98 | handle(EVENT_PAUSE); 99 | // TEST: cb_pause: id = 1, resume_in = 42s 100 | 101 | handle(EVENT_STOP); 102 | // TEST: cb_stop: id = 2, follow_by = 100 103 | 104 | handle(EVENT_PAUSE); 105 | // TEST: cb_pause: id = 1, resume_in = 42s 106 | handle(EVENT_PAUSE); 107 | // TEST: cb_pause: id = 1, resume_in = 42s 108 | } 109 | 110 | 111 | -------------------------------------------------------------------------------- /tests/exist_types_runtest/counters.c: -------------------------------------------------------------------------------- 1 | // Run-time test for existential types 2 | // There are no expected failures in the execution of this test. 3 | // We're just checking that using _Pack, _Unpack and existentials 4 | // works as inteded. 5 | // The test itself implement a simple counter interface in two different ways: 6 | // with a regular counter and a mod 2 counter. 7 | // We run the two counters in a loop, and then check that the output matches 8 | // what we expect. 9 | // 10 | // RUN: %clang %s -o %t1 %checkedc_target_flags 11 | 12 | // RUN: %checkedc_rununder %t1 -DARR | FileCheck %s --check-prefix TEST 13 | 14 | #include 15 | #include 16 | 17 | struct Counter _For_any(T) { 18 | T *state; 19 | void (*inc)(T *st); 20 | void (*dec)(T *st); 21 | int (*getVal)(); 22 | }; 23 | 24 | // Regular counter 25 | 26 | void incIntCounter(int *x) { 27 | *x = (*x) + 1; 28 | } 29 | 30 | void decIntCounter(int *x) { 31 | *x = (*x) - 1; 32 | } 33 | 34 | int getValIntCounter(int *x) { 35 | return *x; 36 | } 37 | 38 | _Exists(T, struct Counter) getCounter() { 39 | struct Counter ct; 40 | int *x = malloc(sizeof(int)); 41 | *x = 0; 42 | ct.state = x; 43 | ct.inc = incIntCounter; 44 | ct.dec = decIntCounter; 45 | ct.getVal = getValIntCounter; 46 | return _Pack(ct, _Exists(T, struct Counter), int); 47 | } 48 | 49 | // Mod2 counter 50 | 51 | void toggleMod2Counter(char *x) { 52 | *x = !(*x); 53 | } 54 | 55 | int getValMod2Counter(char *x) { 56 | return *x; 57 | } 58 | 59 | _Exists(T, struct Counter) getMod2Counter() { 60 | struct Counter ct; 61 | char *x = malloc(sizeof(char)); 62 | *x = 0; 63 | ct.state = x; 64 | ct.inc = toggleMod2Counter; 65 | ct.dec = toggleMod2Counter; 66 | ct.getVal = getValMod2Counter; 67 | return _Pack(ct, _Exists(T, struct Counter), char); 68 | } 69 | 70 | int main(int argc, char *argv[]) { 71 | _Exists(T, struct Counter) counters[2]; 72 | counters[0] = getCounter(); 73 | counters[1] = getMod2Counter(); 74 | 75 | for (int i = 0; i < 2; i++) { 76 | _Unpack (U) struct Counter unpackCt = counters[i]; 77 | for (int j = 0; j < 10; j++) { 78 | printf("counter = %d\n", unpackCt.getVal(unpackCt.state)); 79 | unpackCt.inc(unpackCt.state); 80 | } 81 | printf("---\n"); 82 | } 83 | 84 | // TEST: counter = 0 85 | // TEST: counter = 1 86 | // TEST: counter = 2 87 | // TEST: counter = 3 88 | // TEST: counter = 4 89 | // TEST: counter = 5 90 | // TEST: counter = 6 91 | // TEST: counter = 7 92 | // TEST: counter = 8 93 | // TEST: counter = 9 94 | // TEST: --- 95 | // TEST: counter = 0 96 | // TEST: counter = 1 97 | // TEST: counter = 0 98 | // TEST: counter = 1 99 | // TEST: counter = 0 100 | // TEST: counter = 1 101 | // TEST: counter = 0 102 | // TEST: counter = 1 103 | // TEST: counter = 0 104 | // TEST: counter = 1 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /tests/parsing/pointer-larger-int/lit.local.cfg: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # On 32-bit windows a pointer is not larger than int 4 | if not re.match(r'^i686-pc.*-(windows-msvc|windows-gnu)$', config.target_triple): 5 | config.available_features.add('pointer-larger-int') 6 | 7 | if not 'pointer-larger-int' in config.available_features: 8 | config.unsupported = True -------------------------------------------------------------------------------- /tests/parsing/pointer-larger-int/member_bounds.c: -------------------------------------------------------------------------------- 1 | // Feature tests of parsing new Checked C member bounds declarations. 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang_cc1 -verify %s 6 | 7 | #include 8 | 9 | _Static_assert(sizeof(void*) > sizeof(int), 10 | "Pointers must be larger than ints"); 11 | 12 | // Unions of pointers and integers, where the least significant 13 | // bit is used as a tag. 14 | 15 | // We tag integers with 1 instead of trying to tag pointers with 1. 16 | // Null pointers tagged with 1 are not allowed by the current 17 | // Checked C definition. 18 | 19 | #define is_tagged_int(p) ((int)(p) & 1) 20 | #define untag_int(p) ((p) & ~1) 21 | 22 | union U4 { 23 | array_ptr ip : bounds(ip, is_tagged_int(ip) ? ip : ip + 5); // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr'}} 24 | int i; 25 | }; 26 | -------------------------------------------------------------------------------- /tests/parsing/typevariable/forany_parsing.c: -------------------------------------------------------------------------------- 1 | // Tests to make sure _For_any specifier is parsed correctly. 2 | // 3 | // More specifically, we are testing for correctness of _For_any specifier. 4 | // 1) _For_any specifier is correctly parsed along with new type polymorphism. 5 | // 2) _For_any specifier correctly enters a new scope and function declaration 6 | // or definition is registered to a correct scope. 7 | // For this test file, we expect that there are no errors. 8 | // 9 | // RUN: %clang_cc1 -verify %s 10 | // expected-no-diagnostics 11 | 12 | // Testing for function declaration with function body, with parameters 13 | _For_any(T, S) T* _Single TestDefinitionWithParameter(T* _Single at, T* _Single bt, _Ptr cs) { 14 | _Ptr newT = at; 15 | return newT; 16 | } 17 | 18 | // Testing for function declaration without function body, without parameters. 19 | _For_any(R) R* _Single TestDeclarationWithNoParameter(void); 20 | // Testing for function declaration without function body, with parameters 21 | _For_any(Q) Q* _Single TestDeclarationWithParameter(Q* _Single aq, _Ptr bq, _Ptr cq); 22 | 23 | int callPolymorphicTypes() { 24 | int num = 0; 25 | _Ptr x = # 26 | // Testing to make sure function declaration is registered in decl scope 27 | // outside of forany scope. 28 | TestDefinitionWithParameter(x, x, x); 29 | TestDeclarationWithNoParameter(); 30 | TestDeclarationWithParameter(x, x, x); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /tests/parsing/typevariable/forany_parsing_error.c: -------------------------------------------------------------------------------- 1 | // Tests to make sure _For_any errors are produced correctly. 2 | // 3 | // More specifically, we are testing for following errors. 4 | // 1) _For_any() must have a list of type variables within the parentheses. 5 | // 2) Make sure type declaration syntax error is caught. 6 | // 3) _For_any scope should be confined within function declaration. 7 | // 8 | // RUN: %clang_cc1 -verify %s 9 | 10 | _For_any(R) R* _Single foo(void); 11 | // Testing scope created by for any specifier is exited successfully. 12 | R *thisShouldProduceError; //expected-error{{unknown type name 'R'}} 13 | _For_any() void foo2(void); // expected-error{{expected type variable identifier}} 14 | _For_any(R, ) _Ptr foo3(void); // expected-error{{expected type variable identifier}} 15 | _For_any(R T) R* _Single foo4(void); // expected-error{{expected , or )}} 16 | -------------------------------------------------------------------------------- /tests/parsing/typevariable/generic_func_parsing.c: -------------------------------------------------------------------------------- 1 | // Tests to make sure generic function call is parsed correctly. 2 | // 3 | // More specifically, we are testing for below cases to parse and not error : 4 | // 1) When calling a generic function, type specification in <> is parsed. We 5 | // do not yet care whether the number of type variables in function 6 | // declaration is consistent with number of types specified in function call 7 | // 2) An expression that may be ambiguous to generic function call is a 8 | // comparison expression. ex) foo < bar; Make sure this isn't going to break 9 | // 10 | // RUN: %clang_cc1 -verify %s 11 | // expected-no-diagnostics 12 | 13 | _For_any(T) T* _Single foo(T* _Single a, T* _Single b) { 14 | return a; 15 | } 16 | 17 | void bar() { 18 | return; 19 | } 20 | 21 | void callPolymorphicTypes() { 22 | int num = 0; 23 | _Ptr x = # 24 | // This line tests that the compiler is parsing generic function call. 25 | foo(x, x); 26 | // This line tests that the compiler is parsing non generic function call. 27 | bar(); 28 | int a, b; 29 | // This line tests that the compiler parses comparison not generic function 30 | if (a < b) {}; 31 | } -------------------------------------------------------------------------------- /tests/parsing/typevariable/generic_func_parsing_error.c: -------------------------------------------------------------------------------- 1 | // Tests to make sure parsing errors for generic function calls are detected 2 | // properly. 3 | // 4 | // RUN: %clang_cc1 -verify %s 5 | 6 | _For_any(T) T* _Single Foo(T* _Single a, T* _Single b) { 7 | return a; 8 | } 9 | 10 | void CallGenericFunction() { 11 | int num = 0; 12 | _Ptr x = # 13 | Foo(x, x); //expected-error{{cannot combine with previous 'int' declaration specifier}} 14 | Foo(x, x); //expected-error{{expected a type}} 15 | Foo(x, x); //expected-error{{expected a type argument list for a generic function call}} 16 | } 17 | -------------------------------------------------------------------------------- /tests/runtime_operations/README.md: -------------------------------------------------------------------------------- 1 | # Runtime operations 2 | 3 | Test runtime operations fpr the Checked C extension that do not involve 4 | dynamic checking. This covers operations such as assignments of 5 | checked pointer values and implicit conversion. 6 | -------------------------------------------------------------------------------- /tests/runtime_operations/assignments.c: -------------------------------------------------------------------------------- 1 | // The following lines are for the clang automated test suite 2 | // 3 | // RUN: %clang -fcheckedc-extension %s -o %t -Werror 4 | // RUN: %t | FileCheck %s --check-prefixes=CHECK 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | static char *test : itype(ptr); 11 | char p = 5; 12 | static char *init _Itype(char* _Single) = &p; 13 | 14 | int testfn(char *buf : count(len), size_t len) 15 | _Checked { 16 | test = init; 17 | return 0; 18 | } 19 | 20 | 21 | int main(int argc, char**_Array argv : count(argc)) { 22 | // CHECK: Starting test 23 | puts("Starting test"); 24 | testfn(init, 1); 25 | if (test && *test == 5) { 26 | // CHECK: Finishing test successfully 27 | puts("Finishing test successfully"); 28 | return EXIT_SUCCESS; 29 | } 30 | else 31 | return EXIT_FAILURE; 32 | } 33 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff1.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | ptr f21(int i) { 12 | } // expected-error {{control reaches end of function with checked pointer return type}} 13 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff2.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | ptr f22(int i) { 12 | if (i) 13 | return 0; 14 | } // expected-error {{control may reach end of function with checked pointer return type}} 15 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff3.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | int f23(array_ptr p : count(1)) : bounds(p, p + 1) { 12 | } // expected-error {{control reaches end of function with return bounds}} 13 | 14 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff4.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | int f24(array_ptr p : count(1)) : bounds(p, p + 1) { 12 | if (p) 13 | return 0; 14 | } // expected-error {{control may reach end of function with return bounds}} 15 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff5.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | int f25(void) checked { 12 | } // expected-error {{control reaches end of checked function body}} 13 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff6.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | int f25(int i) checked { 12 | if (i) 13 | return 0; 14 | } // expected-error {{control may reach end of checked function body}} 15 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff7.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | checked int f27(void) { 12 | } // expected-error {{control reaches end of checked function body}} 13 | -------------------------------------------------------------------------------- /tests/static_checking/returns/falloff8.c: -------------------------------------------------------------------------------- 1 | // Test that falling off ends of functions is not allowed for checked code. 2 | // This is tested by a set of files because clang suppresses these analysis-based 3 | // errors after the first one occurs. 4 | // 5 | // The following lines are for the LLVM test harness: 6 | // 7 | // RUN: %clang_cc1 -verify %s 8 | 9 | #include 10 | 11 | checked int f28(int i) { 12 | if (i) 13 | return 0; 14 | } // expected-error {{control may reach end of checked function body}} 15 | -------------------------------------------------------------------------------- /tests/static_checking/returns/funcbody.c: -------------------------------------------------------------------------------- 1 | // Tests that incorrect returns in function bodies are not allowed for checked 2 | // code. 3 | // 4 | // The following lines are for the LLVM test harness: 5 | // 6 | // RUN: %clang_cc1 -verify %s 7 | 8 | #include 9 | 10 | // Returning a value when none is expected. 11 | void f1(void) checked { 12 | return 5; // expected-error {{void function 'f1' cannot return a value in a checked scope}} 13 | } 14 | 15 | checked void f2(void) { 16 | ptr p = 0; 17 | return p; // expected-error {{void function 'f2' cannot return a value in a checked scope}} 18 | } 19 | 20 | void f3(void) checked { 21 | array_ptr p = 0; 22 | return p; // expected-error {{void function 'f3' cannot return a value in a checked scope}} 23 | } 24 | 25 | // Failing to return a value when one is expected. 26 | ptr f10(void) { 27 | return; // expected-error {{function 'f10' with checked pointer return type must return a value}} 28 | } 29 | 30 | int f11(void) checked { 31 | return; // expected-error {{non-void function 'f11' must return a value in a checked scope}} 32 | } 33 | 34 | int f12(array_ptr p) : bounds(p, p + 1) checked { 35 | return; // expected-error {{non-void function 'f12' must return a value when there are return bounds}} 36 | } 37 | 38 | 39 | array_ptr f13(void) : count(5) checked { 40 | return; // expected-error {{function 'f13' with checked pointer return type must return a value}} 41 | } 42 | 43 | array_ptr f14(void) : count(5) { 44 | return; // expected-error {{function 'f14' with checked pointer return type must return a value}} 45 | } 46 | -------------------------------------------------------------------------------- /tests/typechecking/checked_scope_bounds_only.c: -------------------------------------------------------------------------------- 1 | // Feature tests of typechecking of uses of checked scopes with the 2 | // _Bounds_only modifier. 3 | // 4 | // This builds the file checked_scope_basic.c, #defining BOUNDS_ONLY to 1. 5 | // 6 | // The following line is for the LLVM test harness: 7 | // 8 | // RUN: %clang_cc1 -Wno-unused-value -Wno-pointer-bool-conversion -verify -verify-ignore-unexpected=note -DBOUNDS_ONLY=1 %S/checked_scope_basic.c 9 | // 10 | 11 | #import 12 | 13 | int main(void) { 14 | return EXIT_FAILURE; 15 | } 16 | -------------------------------------------------------------------------------- /tests/typechecking/checked_scope_pragma_bounds_only.c: -------------------------------------------------------------------------------- 1 | // Feature tests of typechecking of uses of checked scopes introduced by 2 | // #pragma CHECKED_SCOPE with the _Bounds_only modifier. 3 | // 4 | // This builds the file checked_scope_pragma.c, #defining BOUNDS_ONLY to 1. 5 | // 6 | // The following line is for the LLVM test harness: 7 | // 8 | // RUN: %clang_cc1 -Wno-unused-value -Wno-pointer-bool-conversion -verify -verify-ignore-unexpected=note -DBOUNDS_ONLY=1 %S/checked_scope_pragma.c 9 | // 10 | #import 11 | 12 | int main(void) { 13 | return EXIT_FAILURE; 14 | } 15 | -------------------------------------------------------------------------------- /tests/typechecking/errno-use.c: -------------------------------------------------------------------------------- 1 | // Quick test for errno bounds safe interface 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang -fsyntax-only -Werror %s 6 | 7 | #include 8 | #include 9 | 10 | #pragma CHECKED_SCOPE ON 11 | 12 | void f1(void) 13 | { 14 | errno = 0; 15 | } 16 | -------------------------------------------------------------------------------- /tests/typechecking/generic_functions.c: -------------------------------------------------------------------------------- 1 | // Test type checking of generic function calls. 2 | // 3 | // RUN: %clang_cc1 -verify -verify-ignore-unexpected=note %s 4 | 5 | // 6 | // Test mismatches between the number of type variables and type arguments. 7 | // 8 | _For_any(T) int oneTypeVariable(_Ptr a, _Ptr b) { 9 | return 0; 10 | } 11 | 12 | _For_any(T, S, R, V) int manyTypeVariables(_Ptr t, _Ptr s, _Ptr r, _Ptr v) { 13 | return 0; 14 | } 15 | 16 | void CallGenericFunction(void) { 17 | int a = 0, b = 0, c = 0, d = 0; 18 | _Ptr ap = &a; 19 | _Ptr bp = &b; 20 | _Ptr cp = &c; 21 | _Ptr dp = &d; 22 | 23 | oneTypeVariable(ap, bp); //expected-error {{mismatch between the number of types listed and number of type variables}} 24 | oneTypeVariable<>(ap, bp); //expected-error {{mismatch between the number of types listed and number of type variables}} 25 | manyTypeVariables(ap, bp, cp, dp); //expected-error {{mismatch between the number of types listed and number of type variables}} 26 | manyTypeVariables<>(ap, bp, cp, dp); //expected-error {{mismatch between the number of types listed and number of type variables}} 27 | } 28 | 29 | // 30 | // Test that generic functions without prototype are not allowed. 31 | // 32 | 33 | // Declaration of a generic no-prototype function. 34 | _For_any(T) T *func1(); // expected-error {{expected prototype for a generic function}} 35 | 36 | // Declaration of old-style K&R function definition. 37 | _For_any(T) void func2(x, y) // expected-error {{expected prototype for a generic function}} 38 | T *x; 39 | T *y; 40 | { 41 | } 42 | 43 | -------------------------------------------------------------------------------- /tests/typechecking/itype_generic_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | // Test type checking of itype generic function calls. 3 | // 4 | // RUN: %clang_cc1 -verify -verify-ignore-unexpected=note %s 5 | 6 | // 7 | // Test mismatches between the number of type variables and type arguments. 8 | // 9 | _Itype_for_any(T) void* oneTypeVariable(void* a : itype(_Ptr), void* b : itype(_Ptr)) : itype(_Ptr) { 10 | return a; 11 | } 12 | 13 | _Itype_for_any(T, Q) void* manyTypeVariables(void* a _Itype(T* _Single), void* b _Itype(Q* _Single)) _Itype(Q* _Single) { 14 | return b; 15 | } 16 | 17 | 18 | _Itype_for_any(T) 19 | void* validItypeGenericFunction(int a, void* b : itype(_Ptr), void* c : itype(_Ptr)) : itype(_Ptr); 20 | 21 | _Itype_for_any(T) 22 | void* validItypeGenericFunction(int a, void* b _Itype(T* _Single) , void* c _Itype(T* _Single) ) _Itype(T* _Single) { 23 | T* _Single m = b; 24 | return m; 25 | } 26 | 27 | 28 | void CallItypeGenericFunctions(void) { 29 | int a = 0, b = 0, c = 0, d = 0; 30 | _Ptr ap = &a; 31 | _Ptr bp = &b; 32 | _Ptr cp = &c; 33 | _Ptr dp = &d; 34 | 35 | oneTypeVariable(ap, bp); //expected-error {{mismatch between the number of types listed and number of type variables}} 36 | oneTypeVariable<>(ap, bp); //expected-error {{mismatch between the number of types listed and number of type variables}} 37 | manyTypeVariables(ap, bp); 38 | manyTypeVariables<>(ap, bp); //expected-error {{mismatch between the number of types listed and number of type variables}} 39 | 40 | float y = 5.5, z = 0.0; 41 | _Ptr p2 = &y; 42 | _Ptr p = &z; 43 | checked { 44 | p = validItypeGenericFunction(5, p2, p2); 45 | //Checked scope expects type arguments 46 | validItypeGenericFunction(5, 0, 0); //expected-error {{expected a type argument list for a bounds-safe interface call in a checked scope}} 47 | } 48 | unchecked{ 49 | void * p3 = (void *) p2; 50 | //Unchecked scope. Type arguments are not mandated. 51 | float *p4 = validItypeGenericFunction(5, p3, p3); 52 | _Ptr p5 = validItypeGenericFunction(5,p2,p2); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /tests/typechecking/itype_generic_structs.c: -------------------------------------------------------------------------------- 1 | // Test interaction of generic structs with interface types (itypes) 2 | // 3 | // RUN: %clang_cc1 -verify -verify-ignore-unexpected=note %s 4 | 5 | #include 6 | 7 | // 8 | // Test that substitution applies to interface types of struct fields. 9 | // 10 | void TestItypeInGeneric() { 11 | struct Foo _For_any(T) { 12 | T *x : itype(_Ptr); 13 | }; 14 | 15 | struct Foo intFoo; 16 | int *x = intFoo.x; 17 | 18 | struct Foo charFoo; 19 | char *c = charFoo.x; 20 | 21 | checked { 22 | int *x = intFoo.x; // expected-error {{local variable in a checked scope must have a checked type}} 23 | _Ptr x2 = intFoo.x; 24 | 25 | char *c = charFoo.x; // expected-error {{local variable in a checked scope must have a checked type}} 26 | _Ptr c2 = charFoo.x; 27 | } 28 | } 29 | 30 | // 31 | // Test that we can parse an _Itype_for_any clause in a definition. 32 | // 33 | void TestItypeForAnyInDef() { 34 | struct Foo _Itype_for_any(T, U) { 35 | }; 36 | } 37 | 38 | // 39 | // Test generic bounds safe interface in checked and unchecked scopes. 40 | // 41 | void TestItypeForAnyScopes() { 42 | struct Foo _Itype_for_any(T) { 43 | void *x : itype(_Ptr); 44 | }; 45 | 46 | // In an unchecked scope, if no type args are specified, we use void args. 47 | struct Foo foo1; 48 | void *x1 = foo1.x; // ok: uses declared type (void*) for field 49 | _Ptr y1 = foo1.x; // ok: uses bounds-safe interface (_Ptr) 50 | 51 | struct Foo foo2; 52 | char *x2 = foo2.x; // ok: conversion from _Ptr to char* 53 | _Ptr y2 = foo2.x; // ok: conversion from void* to _Ptr 54 | 55 | _Checked { 56 | struct Foo foo3; // expected-error {{expected a type argument list for a struct with a bounds-safe interface in a checked scope}} 57 | 58 | struct Foo foo4; 59 | _Ptr x4 = foo4.x; // ok: widening conversion 60 | _Ptr y4 = foo4.x; // expected-error {{initializing '_Ptr' with an expression of incompatible type '_Ptr'}} 61 | _Ptr z4 = foo4.x; 62 | } 63 | } 64 | 65 | // 66 | // Test new compatibilty rules in bounds interfaces. 67 | // 68 | void TestListIType() { 69 | struct List _Itype_for_any(T) { 70 | void *head : itype(_Ptr); 71 | struct List *next : itype(_Ptr >); 72 | }; 73 | } 74 | 75 | // 76 | // Test that we can detect expanding cycles that go through 77 | // itypes. 78 | // 79 | void TestExpandingCycles() { 80 | struct FooGood _Itype_for_any(T) { 81 | struct FooGood *next : itype(_Ptr >); // ok: cycle is non-expanding 82 | }; 83 | 84 | // Expanding cycle with one node. 85 | struct FooBad _Itype_for_any(T) { // expected-error {{expanding cycle in struct definition}} 86 | struct FooBad *next : itype(_Ptr > >); // itype causes expanding cycle 87 | }; 88 | 89 | // Expanding cycle with three nodes. 90 | // The cycle passes through both for_any and itype_forany nodes. 91 | struct A _For_any(T); 92 | struct B _Itype_for_any(T); 93 | struct C _Itype_for_any(T); 94 | 95 | struct A _For_any(T) { 96 | struct B *b; 97 | }; 98 | 99 | struct B _Itype_for_any(T) { 100 | struct C *c: itype(_Ptr > >); 101 | }; 102 | 103 | struct C _Itype_for_any(T) { // expected-error {{expanding cycle in struct definition}} 104 | struct A *a; 105 | }; 106 | } 107 | -------------------------------------------------------------------------------- /tests/typechecking/malloc_free.c: -------------------------------------------------------------------------------- 1 | // Feature tests for type checking Checked C bounds-safe interface 2 | // type annotations. 3 | // 4 | // The following lines are for the LLVM test harness: 5 | // 6 | // RUN: %clang -fsyntax-only -Werror %s 7 | 8 | #include 9 | #include 10 | 11 | #pragma CHECKED_SCOPE ON 12 | 13 | // Test you can always `free` a `malloc`d unchecked pointer 14 | void f1(void) unchecked { 15 | int *x = malloc(sizeof(int)); 16 | free(x); 17 | } 18 | 19 | // Test you can always `free` a `calloc`d unchecked pointer 20 | void f2(void) unchecked { 21 | int *x = calloc(1, sizeof(int)); 22 | free(x); 23 | } 24 | 25 | // Test you can always `free` a `realloc`d unchecked pointer 26 | void f3(void) unchecked { 27 | int *x = malloc(sizeof(int)); 28 | int *y = realloc(x, 2 * sizeof(int)); 29 | free(y); 30 | } 31 | 32 | // Test you can always `free` a `aligned_alloc`d unchecked pointer 33 | void f4(void) unchecked { 34 | int *x = aligned_alloc(_Alignof(int), sizeof(int)); 35 | free(x); 36 | } 37 | 38 | // Test you can always `free` a `malloc`d ptr 39 | void f11(void) { 40 | int* _Single x = malloc _TyArgs(int) (sizeof(int)); 41 | free(x); 42 | } 43 | 44 | // Test you can always `free` a `calloc`d ptr 45 | void f12(void) unchecked { 46 | // Intentionally vary test from f11: type argument can be omitted 47 | // in an unchecked scope. 48 | ptr x = calloc(1, sizeof(int)); 49 | free(x); 50 | } 51 | 52 | // Test you can always `free` a `realloc`d ptr 53 | void f13(void) unchecked { 54 | // Intentionally vary test from f11: type argument can be omitted 55 | // in an unchecked scope. 56 | ptr x = malloc(sizeof(int)); 57 | ptr y = realloc(x, 2 * sizeof(int)); 58 | free(y); 59 | } 60 | 61 | // Test you can always `free` a `aligned_alloc`d ptr 62 | void f14(void) { 63 | ptr x = aligned_alloc(_Alignof(int), sizeof(int)); 64 | free(x); 65 | } 66 | 67 | // Test you can always `free` a `malloc`d array_ptr 68 | void f21(void) { 69 | array_ptr x : count(4) = malloc(4 * sizeof(int)); 70 | free(x); 71 | } 72 | 73 | // Test you can always `free` a `calloc`d array_ptr 74 | void f22(void) { 75 | array_ptr x : count(4) = calloc(4, sizeof(int)); 76 | free(x); 77 | } 78 | 79 | // Test you can always `free` a `realloc`d array_ptr 80 | void f23(void) { 81 | int* _Array x _Count(4) = malloc _TyArgs(int) (4 * sizeof(int)); 82 | int* _Array y _Count(8) = realloc _TyArgs(int) (x, 8 * sizeof(int)); 83 | free _TyArgs(int) (y); 84 | } 85 | 86 | // Test you can always `free` a `aligned_alloc`d array_ptr 87 | void f24(void) { 88 | array_ptr x : count(4) = aligned_alloc(_Alignof(int), 4 * sizeof(int)); 89 | free(x); 90 | } 91 | -------------------------------------------------------------------------------- /tests/typechecking/pointer-larger-int/bounds.c: -------------------------------------------------------------------------------- 1 | // Feature tests of typechecking new Checked C bounds declarations. 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang_cc1 -Wno-check-bounds-decls -verify -verify-ignore-unexpected=note %s 6 | 7 | #include 8 | 9 | _Static_assert(sizeof(void*) > sizeof(int), 10 | "Pointers must be larger than ints"); 11 | 12 | enum E1 { 13 | EnumVal1, 14 | EnumVal2 15 | }; 16 | 17 | void int_local_var_bounds_decl(void) { 18 | // bounds declarations are allowed for integer variables to support 19 | // casting of pointers to integers and back. We usually expect this 20 | // to happen within expressions, but to allow uniform use of language 21 | // features, we allow bounds on integer-typed variables. 22 | int a1 checked[5]; 23 | 24 | // byte_count 25 | int t21 _Byte_count(5 * sizeof(int)) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr'}} 26 | 27 | // bounds 28 | int t25 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr'}} 29 | long int t26 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr'}} 30 | unsigned long int t27 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr'}} 31 | enum E1 t28 _Bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr'}} 32 | } 33 | -------------------------------------------------------------------------------- /tests/typechecking/pointer-larger-int/lit.local.cfg: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # On 32-bit windows a pointer is not larger than int 4 | if not re.match(r'^i686-pc.*-(windows-msvc|windows-gnu)$', config.target_triple): 5 | config.available_features.add('pointer-larger-int') 6 | 7 | if not 'pointer-larger-int' in config.available_features: 8 | config.unsupported = True -------------------------------------------------------------------------------- /tests/typechecking/pointer-larger-long/bounds.c: -------------------------------------------------------------------------------- 1 | // Feature tests of typechecking new Checked C bounds declarations. 2 | // 3 | // The following lines are for the LLVM test harness: 4 | // 5 | // RUN: %clang_cc1 -Wno-check-bounds-decls -verify -verify-ignore-unexpected=note %s 6 | 7 | #include 8 | 9 | _Static_assert(sizeof(void*) > sizeof(long), 10 | "Pointers must be larger than longs"); 11 | 12 | void int_local_var_bounds_decl(void) { 13 | // bounds declarations are allowed for integer variables to support 14 | // casting of pointers to integers and back. We usually expect this 15 | // to happen within expressions, but to allow uniform use of language 16 | // features, we allow bounds on integer-typed variables. 17 | int a1 checked[5]; 18 | 19 | long int t22 : byte_count(5 * sizeof(int)) = (long int)a1; // expected-warning {{cast to smaller integer type 'long' from '_Array_ptr'}} 20 | unsigned long int t23 : byte_count(5 * sizeof(int)) = (unsigned long int) a1; // expected-warning {{cast to smaller integer type 'unsigned long' from '_Array_ptr'}} 21 | } 22 | -------------------------------------------------------------------------------- /tests/typechecking/pointer-larger-long/lit.local.cfg: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # On 64-bit windows a pointer is larger than long 4 | if re.match(r'^x86_64.*-(windows-msvc|windows-gnu)$', config.target_triple): 5 | config.available_features.add('pointer-larger-long') 6 | 7 | if not 'pointer-larger-long' in config.available_features: 8 | config.unsupported = True -------------------------------------------------------------------------------- /tests/typechecking/pointer-sized-long-long/function_casts.c: -------------------------------------------------------------------------------- 1 | // These are some platform-specific tests to go with 2 | // the tests in ../function_casts.c 3 | // 4 | // The following line is for the LLVM test harness: 5 | // RUN: %clang_cc1 -fcheckedc-extension -verify %s 6 | // 7 | 8 | #include 9 | 10 | int f0(int a) { 11 | return a; 12 | } 13 | 14 | void local_convert(int(*f1)(int), ptr f2) { 15 | // There's no good reason to do this to any function pointers 16 | // and it's definitely not safe. 17 | ptr local_weird_unsafe1 = (ptr)~(long long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 18 | ptr local_weird_unsafe2 = (ptr)~(long long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 19 | ptr local_weird_unsafe3 = (ptr)~(long long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 20 | ptr local_weird_unsafe4 = (ptr)(long long)!(long long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 21 | ptr local_weird_unsafe5 = (ptr)(long long)!(long long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 22 | ptr local_weird_unsafe6 = (ptr)(long long)!(long long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 23 | ptr local_weird_unsafe7 = (ptr) + (long long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 24 | ptr local_weird_unsafe8 = (ptr) + (long long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 25 | ptr local_weird_unsafe9 = (ptr) + (long long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 26 | ptr local_weird_unsafe10 = (ptr) - (long long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 27 | ptr local_weird_unsafe11 = (ptr) - (long long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 28 | ptr local_weird_unsafe12 = (ptr) - (long long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 29 | 30 | } -------------------------------------------------------------------------------- /tests/typechecking/pointer-sized-long-long/lit.local.cfg: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # On 64-bit windows a pointer is the same size as long long 4 | if re.match(r'^x86_64.*-(windows-msvc|windows-gnu)$', config.target_triple): 5 | config.available_features.add('pointer-sized-long-long') 6 | 7 | if not 'pointer-sized-long-long' in config.available_features: 8 | config.unsupported = True -------------------------------------------------------------------------------- /tests/typechecking/pointer-sized-long-long/pointer_casts.c: -------------------------------------------------------------------------------- 1 | // Check Pointer Casts on platforms where pointers and `long long`s are the same size 2 | // In particular, this includes 64-bit windows. 3 | 4 | // To configure the list of platforms, change lit.local.cfg in this directory 5 | // to make the 'pointer-sized-long-long' feature available 6 | 7 | // RUN: %clang_cc1 -std=c11 -verify -verify-ignore-unexpected=note -fcheckedc-extension %s 8 | 9 | #include 10 | 11 | _Static_assert(sizeof(void*) == sizeof(long long), 12 | "Pointers and long longs must be the same size"); 13 | 14 | struct S1 { 15 | int len; 16 | // bound declaration on a long-typed member. 17 | long long p : bounds((char *)p, (char *)p + len); 18 | }; 19 | 20 | extern struct S1 f1(); // expected-error {{function with no prototype cannot have a return type that is a structure with a member with a checked type}} 21 | 22 | extern void f2(); 23 | extern void f2(struct S1); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a structure with a member with a checked type}} 24 | 25 | extern void f3(); 26 | extern void f3(long long p : bounds((char *)p, (char *)p + len), int len); 27 | 28 | extern void f4(long long p : bounds((char *)p, (char *)p + len), int len); 29 | extern void f4(); 30 | 31 | // 32 | // Spot-check other attempts at creating no prototype functions that return 33 | // a checked value. 34 | // 35 | 36 | enum E1 { 37 | EnumVal1, 38 | EnumVal2 39 | }; 40 | 41 | // 42 | // Valid bounds declarations for integer-typed global variables. 43 | // 44 | 45 | int s1 checked[16]; 46 | 47 | // byte_count 48 | long long g21 : byte_count(5 * sizeof(int)) = (long long)s1; 49 | long long int g22 : byte_count(5 * sizeof(int)) = (long long int)s1; 50 | unsigned long long int g23 : byte_count(5 * sizeof(int)) = (unsigned long long int) s1; 51 | // TODO: Enum size is implementation-defined 52 | // enum E1 g24 : byte_count(8) = EnumVal1; 53 | 54 | // bounds 55 | long long g25 : bounds(s1, s1 + 5) = (long long)s1; 56 | long long int g26 : bounds(s1, s1 + 5) = (long long)s1; 57 | unsigned long long int g27 : bounds(s1, s1 + 5) = (long long)s1; 58 | // TODO: Enum size is implementation-defined 59 | // enum E1 g28 : bounds(s1, s1 + 5) = (int)s1; 60 | 61 | extern int f10(int a, _Array_ptr b, _Array_ptr p : bounds(b, b + a)); 62 | extern int f10(int a, _Array_ptr b, 63 | _Array_ptr p : bounds(b, (_Array_ptr) (long long) b + a)); 64 | extern int f10(int a, _Array_ptr b, 65 | _Array_ptr p : bounds(b, (_Array_ptr) (short) b + a)); // expected-error {{function redeclaration has conflicting parameter bounds}} \ 66 | // expected-warning 2 {{cast to smaller integer type 'short' from '_Array_ptr'}} \ 67 | // expected-warning 2 {{cast to '_Array_ptr' from smaller integer type 'short'}} 68 | 69 | extern int f11(int a, _Array_ptr b, _Array_ptr p : bounds(b, b + a)); 70 | extern int f11(int a, _Array_ptr b, 71 | _Array_ptr p : bounds(b, (_Array_ptr) (void *) (long long) b + a)); 72 | -------------------------------------------------------------------------------- /tests/typechecking/pointer-sized-long/function_casts.c: -------------------------------------------------------------------------------- 1 | // These are some platform-specific tests to go with 2 | // the tests in ../function_casts.c 3 | // 4 | // The following line is for the LLVM test harness: 5 | // RUN: %clang_cc1 -verify %s 6 | // 7 | 8 | #include 9 | 10 | int f0(int a) { 11 | return a; 12 | } 13 | 14 | void local_convert(int(*f1)(int), int (*_Single f2)(int)) { 15 | // There's no good reason to do this to any function pointers 16 | // and it's definitely not safe. 17 | ptr local_weird_unsafe1 = (ptr)~(long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 18 | ptr local_weird_unsafe2 = (ptr)~(long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 19 | ptr local_weird_unsafe3 = (ptr)~(long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 20 | ptr local_weird_unsafe4 = (ptr)(long)!(long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 21 | ptr local_weird_unsafe5 = (ptr)(long)!(long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 22 | ptr local_weird_unsafe6 = (ptr)(long)!(long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 23 | ptr local_weird_unsafe7 = (ptr) + (long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 24 | ptr local_weird_unsafe8 = (ptr) + (long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 25 | ptr local_weird_unsafe9 = (ptr) + (long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 26 | ptr local_weird_unsafe10 = (ptr) - (long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 27 | int (*_Single local_weird_unsafe11)(int) = (int (*_Single )(int)) - (long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 28 | int (*_Single local_weird_unsafe12)(int) = (int (*_Single )(int)) - (long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr'}} 29 | 30 | } -------------------------------------------------------------------------------- /tests/typechecking/pointer-sized-long/lit.local.cfg: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | # On 64-bit windows a pointer is not the same size as long 5 | if not re.match(r'^x86_64.*-(windows-msvc|windows-gnu)$', config.target_triple): 6 | config.available_features.add('pointer-sized-long') 7 | 8 | if not 'pointer-sized-long' in config.available_features: 9 | config.unsupported = True -------------------------------------------------------------------------------- /tests/typechecking/pointer-sized-long/pointer_casts.c: -------------------------------------------------------------------------------- 1 | // Check Pointer Casts on platforms where pointers and `long`s are the same size 2 | // This pretty much only excludes 64-bit windows 3 | 4 | // To configure the list of platforms, change lit.local.cfg in this directory 5 | // to make the 'pointer-sized-long' feature available 6 | 7 | // RUN: %clang_cc1 -verify -verify-ignore-unexpected=note %s 8 | 9 | #include 10 | 11 | _Static_assert(sizeof(void*) == sizeof(long), 12 | "Pointers and longs must be the same size"); 13 | 14 | struct S1 { 15 | int len; 16 | // bound declaration on a long-typed member. 17 | long p _Bounds((char *)p, (char *)p + len); 18 | }; 19 | 20 | extern struct S1 f1(); // expected-error {{function with no prototype cannot have a return type that is a structure with a member with a checked type}} 21 | 22 | extern void f2(); 23 | extern void f2(struct S1); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a structure with a member with a checked type}} 24 | 25 | extern void f3(); 26 | extern void f3(long p : bounds((char *)p, (char *)p + len), int len); 27 | 28 | extern void f4(long p _Bounds((char *)p, (char *)p + len), int len); 29 | extern void f4(); 30 | 31 | // 32 | // Valid bounds declarations for integer-typed global variables. 33 | // 34 | 35 | enum E1 { 36 | EnumVal1, 37 | EnumVal2 38 | }; 39 | 40 | // 41 | // Valid bounds declarations for integer-typed global variables. 42 | // 43 | 44 | int s1 checked[16]; 45 | 46 | // byte_count 47 | // Cannot initialize this at compile time. 48 | // short int g20 : byte_count(5 * sizeof(int)) = (short int) s1; 49 | long g21 : byte_count(5 * sizeof(int)) = (long)s1; 50 | long int g22 : byte_count(5 * sizeof(int)) = (long int)s1; 51 | unsigned long int g23 : byte_count(5 * sizeof(int)) = (unsigned long int) s1; 52 | // TODO: Enum size is implementation-defined 53 | // enum E1 g24 : byte_count(8) = EnumVal1; 54 | 55 | // bounds 56 | long g25 : bounds(s1, s1 + 5) = (long)s1; 57 | long int g26 : bounds(s1, s1 + 5) = (long)s1; 58 | unsigned long int g27 : bounds(s1, s1 + 5) = (long)s1; 59 | // TODO: Enum size is implementation-defined 60 | // enum E1 g28 : bounds(s1, s1 + 5) = (int)s1; 61 | 62 | // Check that casts between pointers and long ints do not affect 63 | // equivalence of bounds 64 | 65 | extern int f10(int a, _Array_ptr b, _Array_ptr p : bounds(b, b + a)); 66 | extern int f10(int a, _Array_ptr b, 67 | _Array_ptr p : bounds(b, (_Array_ptr) (long) b + a)); 68 | extern int f10(int a, _Array_ptr b, 69 | _Array_ptr p : bounds(b, (_Array_ptr) (short) b + a)); // expected-error {{function redeclaration has conflicting parameter bounds}} \ 70 | // expected-warning 2 {{cast to '_Array_ptr' from smaller integer type 'short'}} \ 71 | // expected-warning 2 {{cast to smaller integer type 'short' from '_Array_ptr'}} 72 | 73 | extern int f11(int a, int* _Array b, char* _Array p _Bounds(b, b + a)); 74 | extern int f11(int a, int* _Array b, 75 | char* _Array p _Bounds(b, (int* _Array) (void *) (long) b + a)); 76 | 77 | --------------------------------------------------------------------------------