ubsan.h
1 /* 2 * Copyright (c) 2018 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #ifndef _UBSAN_H_ 30 #define _UBSAN_H_ 31 32 #include <stdint.h> 33 #include <stdbool.h> 34 35 struct san_type_desc { 36 uint16_t type; // 0: integer, 1: float 37 union { 38 struct { 39 uint16_t issigned : 1; 40 uint16_t width : 15; 41 }; /* int descriptor */ 42 struct { 43 uint16_t float_desc; 44 }; /* float descriptor */ 45 }; 46 const char name[]; 47 }; 48 49 struct san_src_loc { 50 const char *filename; 51 uint32_t line; 52 uint32_t col; 53 }; 54 55 struct ubsan_overflow_desc { 56 struct san_src_loc loc; 57 struct san_type_desc *ty; 58 }; 59 60 struct ubsan_unreachable_desc { 61 struct san_src_loc loc; 62 }; 63 64 struct ubsan_shift_desc { 65 struct san_src_loc loc; 66 struct san_type_desc *lhs_t; 67 struct san_type_desc *rhs_t; 68 }; 69 70 struct ubsan_align_desc { 71 struct san_src_loc loc; 72 struct san_type_desc *ty; 73 uint8_t align; 74 uint8_t kind; 75 }; 76 77 struct ubsan_ptroverflow_desc { 78 struct san_src_loc loc; 79 }; 80 81 struct ubsan_oob_desc { 82 struct san_src_loc loc; 83 struct san_type_desc *array_ty; 84 struct san_type_desc *index_ty; 85 }; 86 87 struct ubsan_load_invalid_desc { 88 struct san_src_loc loc; 89 struct san_type_desc *type; 90 }; 91 92 struct ubsan_nullability_arg_desc { 93 struct san_src_loc loc; 94 struct san_src_loc attr_loc; 95 int arg_index; 96 }; 97 98 struct ubsan_nullability_ret_desc { 99 struct san_src_loc loc; 100 }; 101 102 struct ubsan_missing_ret_desc { 103 struct san_src_loc loc; 104 }; 105 106 struct ubsan_float_desc { 107 struct san_src_loc loc; 108 struct san_type_desc *type_from; 109 struct san_type_desc *type_to; 110 }; 111 112 struct ubsan_implicit_conv_desc { 113 struct san_src_loc loc; 114 struct san_type_desc *type_from; 115 struct san_type_desc *type_to; 116 unsigned char kind; 117 }; 118 119 struct ubsan_func_type_mismatch_desc { 120 struct san_src_loc loc; 121 struct san_type_desc *type; 122 }; 123 124 struct ubsan_vla_bound_desc { 125 struct san_src_loc loc; 126 struct san_type_desc *type; 127 }; 128 129 struct ubsan_invalid_builtin { 130 struct san_src_loc loc; 131 unsigned char kind; 132 }; 133 134 enum { 135 UBSAN_OVERFLOW_add = 1, 136 UBSAN_OVERFLOW_sub, 137 UBSAN_OVERFLOW_mul, 138 UBSAN_OVERFLOW_divrem, 139 UBSAN_OVERFLOW_negate, 140 UBSAN_UNREACHABLE, 141 UBSAN_SHIFT, 142 UBSAN_ALIGN, 143 UBSAN_POINTER_OVERFLOW, 144 UBSAN_OOB, 145 UBSAN_TYPE_MISMATCH, 146 UBSAN_LOAD_INVALID_VALUE, 147 UBSAN_NULLABILITY_ARG, 148 UBSAN_NULLABILITY_RETURN, 149 UBSAN_MISSING_RETURN, 150 UBSAN_FLOAT_CAST_OVERFLOW, 151 UBSAN_IMPLICIT_CONVERSION, 152 UBSAN_FUNCTION_TYPE_MISMATCH, 153 UBSAN_VLA_BOUND_NOT_POSITIVE, 154 UBSAN_INVALID_BUILTIN, 155 UBSAN_VIOLATION_MAX 156 }; 157 158 struct ubsan_violation { 159 uint8_t ubsan_type; 160 uint64_t lhs; 161 uint64_t rhs; 162 union { 163 struct ubsan_overflow_desc *overflow; 164 struct ubsan_unreachable_desc *unreachable; 165 struct ubsan_shift_desc *shift; 166 struct ubsan_align_desc *align; 167 struct ubsan_ptroverflow_desc *ptroverflow; 168 struct ubsan_oob_desc *oob; 169 struct ubsan_load_invalid_desc *invalid; 170 struct ubsan_nullability_arg_desc *nonnull_arg; 171 struct ubsan_nullability_ret_desc *nonnull_ret; 172 struct ubsan_missing_ret_desc *missing_ret; 173 struct ubsan_float_desc *flt; 174 struct ubsan_implicit_conv_desc *implicit; 175 struct ubsan_func_type_mismatch_desc *func_mismatch; 176 struct ubsan_vla_bound_desc *vla_bound; 177 struct ubsan_invalid_builtin *invalid_builtin; 178 const char *func; 179 }; 180 struct san_src_loc *loc; 181 }; 182 183 struct ubsan_buf { 184 size_t ub_logged; 185 size_t ub_buf_size; 186 char *ub_buf; 187 }; 188 189 void ubsan_log_append(struct ubsan_violation *); 190 void ubsan_format(struct ubsan_violation *, struct ubsan_buf *); 191 192 /* 193 * UBSan ABI 194 */ 195 196 void __ubsan_handle_add_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 197 void __ubsan_handle_add_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 198 void __ubsan_handle_builtin_unreachable(struct ubsan_unreachable_desc *); 199 void __ubsan_handle_divrem_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 200 void __ubsan_handle_divrem_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 201 void __ubsan_handle_float_cast_overflow(struct ubsan_float_desc *, uint64_t); 202 void __ubsan_handle_float_cast_overflow_abort(struct ubsan_float_desc *, uint64_t); 203 void __ubsan_handle_function_type_mismatch(struct ubsan_func_type_mismatch_desc*, uint64_t); 204 void __ubsan_handle_function_type_mismatch_abort(struct ubsan_func_type_mismatch_desc *, uint64_t); 205 void __ubsan_handle_implicit_conversion(struct ubsan_implicit_conv_desc *, uint64_t, uint64_t); 206 void __ubsan_handle_implicit_conversion_abort(struct ubsan_implicit_conv_desc *, uint64_t, uint64_t); 207 void __ubsan_handle_invalid_builtin(struct ubsan_invalid_builtin *); 208 void __ubsan_handle_invalid_builtin_abort(struct ubsan_invalid_builtin *); 209 void __ubsan_handle_load_invalid_value(struct ubsan_load_invalid_desc *, uint64_t); 210 void __ubsan_handle_load_invalid_value_abort(struct ubsan_load_invalid_desc *, uint64_t); 211 void __ubsan_handle_missing_return(struct ubsan_missing_ret_desc *); 212 void __ubsan_handle_missing_return_abort(struct ubsan_missing_ret_desc *); 213 void __ubsan_handle_mul_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 214 void __ubsan_handle_mul_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 215 void __ubsan_handle_negate_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 216 void __ubsan_handle_negate_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 217 void __ubsan_handle_nonnull_arg(struct ubsan_nullability_arg_desc *); 218 void __ubsan_handle_nonnull_arg_abort(struct ubsan_nullability_arg_desc *); 219 void __ubsan_handle_nonnull_return_v1(struct ubsan_nullability_ret_desc *, uint64_t); 220 void __ubsan_handle_nonnull_return_v1_abort(struct ubsan_nullability_ret_desc *, uint64_t); 221 void __ubsan_handle_nullability_arg(struct ubsan_nullability_arg_desc *); 222 void __ubsan_handle_nullability_arg_abort(struct ubsan_nullability_arg_desc *); 223 void __ubsan_handle_nullability_return_v1(struct ubsan_nullability_ret_desc *, uint64_t); 224 void __ubsan_handle_nullability_return_v1_abort(struct ubsan_nullability_ret_desc *, uint64_t); 225 void __ubsan_handle_out_of_bounds(struct ubsan_oob_desc *, uint64_t idx); 226 void __ubsan_handle_out_of_bounds_abort(struct ubsan_oob_desc *, uint64_t idx); 227 void __ubsan_handle_pointer_overflow(struct ubsan_ptroverflow_desc *, uint64_t lhs, uint64_t rhs); 228 void __ubsan_handle_pointer_overflow_abort(struct ubsan_ptroverflow_desc *, uint64_t lhs, uint64_t rhs); 229 void __ubsan_handle_shift_out_of_bounds(struct ubsan_shift_desc *, uint64_t lhs, uint64_t rhs); 230 void __ubsan_handle_shift_out_of_bounds_abort(struct ubsan_shift_desc *, uint64_t lhs, uint64_t rhs); 231 void __ubsan_handle_sub_overflow(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 232 void __ubsan_handle_sub_overflow_abort(struct ubsan_overflow_desc *, uint64_t lhs, uint64_t rhs); 233 void __ubsan_handle_type_mismatch_v1(struct ubsan_align_desc *, uint64_t val); 234 void __ubsan_handle_type_mismatch_v1_abort(struct ubsan_align_desc *, uint64_t val); 235 void __ubsan_handle_vla_bound_not_positive(struct ubsan_vla_bound_desc *, uint64_t); 236 void __ubsan_handle_vla_bound_not_positive_abort(struct ubsan_vla_bound_desc *, uint64_t); 237 238 #endif /* _UBSAN_H_ */