-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for ubsan (Undefined Behavior Sanitization) (#271)
- Loading branch information
1 parent
3d492fc
commit 07173a9
Showing
8 changed files
with
282 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/** | ||
* @file | ||
* @see https://wiki.osdev.org/Undefined_Behavior_Sanitization | ||
*/ | ||
#ifndef UBSAN_H | ||
#define UBSAN_H | ||
|
||
#include <stdint.h> | ||
|
||
typedef struct ubsan_type | ||
{ | ||
uint16_t kind; | ||
uint16_t info; | ||
char name[]; | ||
} ubsan_type_t; | ||
|
||
typedef struct ubsan_source_location | ||
{ | ||
const char* file; | ||
uint32_t line; | ||
uint32_t column; | ||
} ubsan_source_location_t; | ||
|
||
typedef struct ubsan_mismatch_v1_data | ||
{ | ||
ubsan_source_location_t location; | ||
ubsan_type_t* type; | ||
uint8_t alignment; | ||
uint8_t kind; | ||
} ubsan_mismatch_v1_data_t; | ||
|
||
typedef struct ubsan_overflow_data | ||
{ | ||
ubsan_source_location_t location; | ||
ubsan_type_t* type; | ||
} ubsan_overflow_data_t; | ||
|
||
typedef struct ubsan_shift_out_of_bounds_data | ||
{ | ||
ubsan_source_location_t location; | ||
ubsan_type_t* lhs_type; | ||
ubsan_type_t* rhs_type; | ||
} ubsan_shift_out_of_bounds_data_t; | ||
|
||
typedef struct ubsan_out_of_bounds_data | ||
{ | ||
ubsan_source_location_t location; | ||
ubsan_type_t* array_type; | ||
ubsan_type_t* index_type; | ||
} ubsan_out_of_bounds_data_t; | ||
|
||
typedef struct ubsan_invalid_value_data | ||
{ | ||
ubsan_source_location_t location; | ||
ubsan_type_t* type; | ||
} ubsan_invalid_value_data_t; | ||
|
||
typedef struct ubsan_float_cast_overflow_data | ||
{ | ||
ubsan_source_location_t location; | ||
ubsan_type_t* from_type; | ||
ubsan_type_t* to_type; | ||
} ubsan_float_cast_overflow_data_t; | ||
|
||
typedef struct ubsan_pointer_overflow_data | ||
{ | ||
ubsan_source_location_t location; | ||
} ubsan_pointer_overflow_data_t; | ||
|
||
// TODO: check why it is _v1 | ||
void __ubsan_handle_type_mismatch_v1(ubsan_mismatch_v1_data_t* data, | ||
uintptr_t ptr); | ||
|
||
void __ubsan_handle_add_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs); | ||
|
||
void __ubsan_handle_sub_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs); | ||
|
||
void __ubsan_handle_mul_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs); | ||
|
||
void __ubsan_handle_negate_overflow(ubsan_overflow_data_t* data, | ||
void* old_value); | ||
|
||
void __ubsan_handle_divrem_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs); | ||
|
||
void __ubsan_handle_shift_out_of_bounds(ubsan_shift_out_of_bounds_data_t* data, | ||
void* lhs, | ||
void* rhs); | ||
|
||
void __ubsan_handle_out_of_bounds(ubsan_out_of_bounds_data_t* data, | ||
void* index); | ||
|
||
void __ubsan_handle_load_invalid_value(ubsan_invalid_value_data_t* data, | ||
void* value); | ||
|
||
void __ubsan_handle_float_cast_overflow(ubsan_float_cast_overflow_data_t* data, | ||
void* from); | ||
|
||
void __ubsan_handle_pointer_overflow(ubsan_pointer_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#include "ubsan.h" | ||
#include <stdio.h> | ||
|
||
#ifdef __is_libk | ||
|
||
#include <kernel/panic.h> | ||
|
||
#endif | ||
|
||
#define UNUSED(x) (void)(x) | ||
|
||
void ubsan_panic_at(ubsan_source_location_t* location, const char* error); | ||
|
||
void __ubsan_handle_type_mismatch_v1(ubsan_mismatch_v1_data_t* data, | ||
uintptr_t ptr) | ||
{ | ||
const char* error = "type mismatch"; | ||
|
||
if (!ptr) { | ||
error = "null pointer access"; | ||
} else if (data->alignment && (ptr & (data->alignment - 1))) { | ||
error = "unaligned access"; | ||
} | ||
|
||
ubsan_panic_at(&data->location, error); | ||
} | ||
|
||
void __ubsan_handle_add_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs) | ||
{ | ||
UNUSED(*lhs); | ||
UNUSED(*rhs); | ||
|
||
ubsan_panic_at(&data->location, "add overflow"); | ||
} | ||
|
||
void __ubsan_handle_sub_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs) | ||
{ | ||
UNUSED(*lhs); | ||
UNUSED(*rhs); | ||
|
||
ubsan_panic_at(&data->location, "sub overflow"); | ||
} | ||
|
||
void __ubsan_handle_mul_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs) | ||
{ | ||
UNUSED(*lhs); | ||
UNUSED(*rhs); | ||
|
||
ubsan_panic_at(&data->location, "mul overflow"); | ||
} | ||
|
||
void __ubsan_handle_negate_overflow(ubsan_overflow_data_t* data, | ||
void* old_value) | ||
{ | ||
UNUSED(*old_value); | ||
|
||
ubsan_panic_at(&data->location, "negation overflow"); | ||
} | ||
|
||
void __ubsan_handle_divrem_overflow(ubsan_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs) | ||
{ | ||
UNUSED(*lhs); | ||
UNUSED(*rhs); | ||
|
||
ubsan_panic_at(&data->location, "negation overflow"); | ||
} | ||
|
||
void __ubsan_handle_shift_out_of_bounds(ubsan_shift_out_of_bounds_data_t* data, | ||
void* lhs, | ||
void* rhs) | ||
{ | ||
UNUSED(*lhs); | ||
UNUSED(*rhs); | ||
|
||
ubsan_panic_at(&data->location, "shift out of bounds"); | ||
} | ||
|
||
void __ubsan_handle_out_of_bounds(ubsan_out_of_bounds_data_t* data, void* index) | ||
{ | ||
UNUSED(*index); | ||
|
||
ubsan_panic_at(&data->location, "shift out of bounds"); | ||
} | ||
|
||
void __ubsan_handle_load_invalid_value(ubsan_invalid_value_data_t* data, | ||
void* value) | ||
{ | ||
UNUSED(*value); | ||
|
||
ubsan_panic_at(&data->location, "invalid value load"); | ||
} | ||
|
||
void __ubsan_handle_float_cast_overflow(ubsan_float_cast_overflow_data_t* data, | ||
void* from) | ||
{ | ||
UNUSED(*from); | ||
|
||
ubsan_panic_at(&data->location, "float cast overflow"); | ||
} | ||
|
||
void __ubsan_handle_pointer_overflow(ubsan_pointer_overflow_data_t* data, | ||
void* lhs, | ||
void* rhs) | ||
{ | ||
UNUSED(*lhs); | ||
UNUSED(*rhs); | ||
|
||
ubsan_panic_at(&data->location, "pointer overflow"); | ||
} | ||
|
||
void ubsan_panic_at(ubsan_source_location_t* location, const char* error) | ||
{ | ||
#ifdef __is_libk | ||
if (location) { | ||
PANIC("ubsan: file=%s line=%d column=%d error=%s", | ||
location->file, | ||
location->line, | ||
location->column, | ||
error); | ||
} else { | ||
PANIC("ubsan: file=(unknown) line=(unknown) column=(unknown) error=%s", | ||
error); | ||
} | ||
#else | ||
if (location) { | ||
printf("ubsan: file=%s line=%d column=%d error=%s\n", | ||
location->file, | ||
location->line, | ||
location->column, | ||
error); | ||
} else { | ||
printf("ubsan: file=(unknown) line=(unknown) column=(unknown) error=%s\n", | ||
error); | ||
} | ||
// TODO: use `abort()` | ||
#endif | ||
} |