/* * Copyright (c) 2019 Google Inc. All rights reserved * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * LLVM UBSan handler signatures and data structures. * * Clang's headers for this are C++, so we cannot use them directly. * This ia a C-styled rewrite. * See LLVM's ubsan_handlers.h for reference. */ #pragma once #include #include "ubsan_value.h" const char* type_check_kinds[] = {"load of", "store to", "reference binding to", "member access within", "member call on", "constructor call on", "downcast of", "downcast of", "upcast of", "cast to virtual base of", "_Nonnull binding to", "dynamic operation on"}; struct type_mismatch_data { struct source_location loc; const struct type_descriptor* type; uint8_t log_alignment; uint8_t type_check_kind; }; struct alignment_assumption_data { struct source_location loc; struct source_location assumption_loc; const struct type_descriptor* type; }; struct overflow_data { struct source_location loc; const struct type_descriptor* type; }; struct shift_out_of_bounds_data { struct source_location loc; const struct type_descriptor* lhs_type; const struct type_descriptor* rhs_type; }; struct out_of_bounds_data { struct source_location loc; const struct type_descriptor* array_type; const struct type_descriptor* index_type; }; struct unreachable_data { struct source_location loc; }; struct vla_bound_data { struct source_location loc; const struct type_descriptor* type; }; struct float_cast_overflow_data { struct source_location loc; const struct type_descriptor* from_type; const struct type_descriptor* to_type; }; struct invalid_value_data { struct source_location loc; const struct type_descriptor* type; }; enum implicit_conversion_check_kind { ICK_LEGACY_TRUNC = 0, ICK_UNSIGNED_TRUNC = 1, ICK_SIGNED_TRUNC = 2, ICK_SIGN_CHANGE = 3, ICK_SIGNED_TRUNC_OR_SIGN_CHANGE = 4, }; static const char* implicit_conversion_check_kinds[] = { "legacy truncation", "unsigned truncation", "signed truncation", "sign change", "signed truncation or sign change", }; struct implicit_conversion_data { struct source_location loc; const struct type_descriptor* from_type; const struct type_descriptor* to_type; uint8_t check_kind; }; enum builtin_check_kind { BCK_CTZ_PASSED_ZERO = 0, BCK_CLZ_PASSED_ZERO = 1, }; struct invalid_builtin_data { struct source_location loc; uint8_t check_kind; }; struct function_type_mismatch_data { struct source_location loc; const struct type_descriptor* type; }; struct non_null_return_data { struct source_location attr_loc; }; struct non_null_arg_data { struct source_location loc; struct source_location attr_loc; int arg_index; }; struct pointer_overflow_data { struct source_location loc; }; enum cfi_type_check_kind { CFI_TCK_VCALL, CFI_TCK_NVCALL, CFI_TCK_DERIVED_CAST, CFI_TCK_UNRELATED_CAST, CFI_TCK_ICALL, CFI_TCK_NVMFCALL, CFI_TCK_VMFCALL }; struct cfi_check_fail_data { uint8_t check_kind; struct source_location loc; const struct type_descriptor* type; }; #define UBSAN_HANDLER(checkname, ...) \ __attribute__((noinline)) void __ubsan_handle_##checkname(__VA_ARGS__) UBSAN_HANDLER(type_mismatch, struct type_mismatch_data* data, value_handle_t val); UBSAN_HANDLER(alignment_assumption, struct alignment_assumption_data* data, value_handle_t val, value_handle_t alignment, value_handle_t offset); UBSAN_HANDLER(add_overflow, struct overflow_data* data, value_handle_t lhs, value_handle_t rhs); UBSAN_HANDLER(sub_overflow, struct overflow_data* data, value_handle_t lhs, value_handle_t rhs); UBSAN_HANDLER(mul_overflow, struct overflow_data* data, value_handle_t lhs, value_handle_t rhs); UBSAN_HANDLER(negate_overflow, struct overflow_data* data, value_handle_t val); UBSAN_HANDLER(divrem_overflow, struct overflow_data* data, value_handle_t lhs, value_handle_t rhs); UBSAN_HANDLER(shift_out_of_bounds, struct shift_out_of_bounds_data* data, value_handle_t lhs, value_handle_t rhs); UBSAN_HANDLER(out_of_bounds, struct out_of_bounds_data* data, value_handle_t index); UBSAN_HANDLER(builtin_unreachable, struct unreachable_data* data); UBSAN_HANDLER(missing_return, struct unreachable_data* data); UBSAN_HANDLER(vla_bound_not_positive, struct vla_bound_data* data, value_handle_t bound); UBSAN_HANDLER(float_cast_overflow, struct float_cast_overflow_data* data, value_handle_t from); UBSAN_HANDLER(load_invalid_value, struct invalid_value_data* data, value_handle_t val); UBSAN_HANDLER(implicit_conversion, struct implicit_conversion_data* data, value_handle_t src, value_handle_t dst); UBSAN_HANDLER(invalid_builtin, struct invalid_builtin_data* data); UBSAN_HANDLER(function_type_mismatch, struct function_type_mismatch_data* data, value_handle_t val); UBSAN_HANDLER(nonnull_return_v1, struct non_null_return_data* data, struct source_location loc); UBSAN_HANDLER(nullability_return_v1, struct non_null_return_data* data, struct source_location loc); UBSAN_HANDLER(nonnull_arg, struct non_null_arg_data* data); UBSAN_HANDLER(nullability_arg, struct non_null_arg_data* data); UBSAN_HANDLER(pointer_overflow, struct pointer_overflow_data* data, value_handle_t base, value_handle_t result); UBSAN_HANDLER(cfi_check_fail, struct cfi_check_fail_data* data, value_handle_t func, uintptr_t vtable_is_valid); UBSAN_HANDLER(cfi_check_fail_abort, struct cfi_check_fail_data* data, value_handle_t func, uintptr_t vtable_is_valid); UBSAN_HANDLER(vla_bound_not_positive, struct vla_bound_data* data, value_handle_t val);