Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ HelenOS.config	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -379,4 +379,10 @@
 ! CONFIG_DEBUG (y/n)
 
+% Sanitize undefined behavior (userspace)
+! CONFIG_UBSAN (n/y)
+
+% Sanitize undefined behavior (kernel)
+! CONFIG_UBSAN_KERNEL (n/y)
+
 % Deadlock detection support for spinlocks
 ! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n)
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ kernel/Makefile	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -106,4 +106,8 @@
 ifeq ($(CONFIG_DEBUG),y)
 	COMMON_CFLAGS += -Werror
+endif
+
+ifeq ($(CONFIG_UBSAN_KERNEL),y)
+	COMMON_CFLAGS += -fsanitize=undefined
 endif
 
@@ -209,4 +213,5 @@
 	generic/src/lib/ra.c \
 	generic/src/lib/rd.c \
+	generic/src/lib/ubsan.c \
 	generic/src/printf/printf_core.c \
 	generic/src/printf/printf.c \
Index: kernel/generic/include/lib/memfnc.h
===================================================================
--- kernel/generic/include/lib/memfnc.h	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ kernel/generic/include/lib/memfnc.h	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -51,4 +51,7 @@
     __attribute__((nonnull(1, 2)))
     ATTRIBUTE_OPTIMIZE("-fno-tree-loop-distribute-patterns") DO_NOT_DISCARD;
+extern int memcmp(const void *, const void *, size_t len)
+    __attribute__((nonnull(1, 2)))
+    ATTRIBUTE_OPTIMIZE("-fno-tree-loop-distribute-patterns") DO_NOT_DISCARD;
 
 #define alloca(size) __builtin_alloca((size))
Index: kernel/generic/include/mem.h
===================================================================
--- kernel/generic/include/mem.h	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ kernel/generic/include/mem.h	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -48,4 +48,5 @@
 #define memset(dst, val, cnt)  __builtin_memset((dst), (val), (cnt))
 #define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
+#define memcmp(s1, s2, cnt)    __builtin_memcmp((s1), (s2), (cnt))
 
 extern void memsetb(void *, size_t, uint8_t)
Index: kernel/generic/src/lib/memfnc.c
===================================================================
--- kernel/generic/src/lib/memfnc.c	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ kernel/generic/src/lib/memfnc.c	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -87,4 +87,31 @@
 }
 
+/** Compare two memory areas.
+ *
+ * @param s1  Pointer to the first area to compare.
+ * @param s2  Pointer to the second area to compare.
+ * @param len Size of the areas in bytes.
+ *
+ * @return Zero if areas have the same contents. If they differ,
+ *	   the sign of the result is the same as the sign of the
+ *	   difference of the first pair of different bytes.
+ *
+ */
+int memcmp(const void *s1, const void *s2, size_t len)
+{
+	uint8_t *u1 = (uint8_t *) s1;
+	uint8_t *u2 = (uint8_t *) s2;
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if (*u1 != *u2)
+			return (int)(*u1) - (int)(*u2);
+		++u1;
+		++u2;
+	}
+
+	return 0;
+}
+
 /** @}
  */
Index: kernel/generic/src/lib/ubsan.c
===================================================================
--- kernel/generic/src/lib/ubsan.c	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
+++ kernel/generic/src/lib/ubsan.c	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2016, Linaro Limited
+ */
+
+/* Modified for HelenOS use by Jiří Zárevúcky. */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <panic.h>
+#include <mem.h>
+
+#define PRINTF(...) printf(__VA_ARGS__)
+#define ubsan_panic() panic("... aborting ...")
+
+struct source_location {
+	const char *file_name;
+	uint32_t line;
+	uint32_t column;
+};
+
+struct type_descriptor {
+	uint16_t type_kind;
+	uint16_t type_info;
+	char type_name[];
+};
+
+struct type_mismatch_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+	unsigned long alignment;
+	unsigned char type_check_kind;
+};
+
+struct overflow_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+};
+
+struct shift_out_of_bounds_data {
+	struct source_location loc;
+	struct type_descriptor *lhs_type;
+	struct type_descriptor *rhs_type;
+};
+
+struct out_of_bounds_data {
+	struct source_location loc;
+	struct type_descriptor *array_type;
+	struct type_descriptor *index_type;
+};
+
+struct unreachable_data {
+	struct source_location loc;
+};
+
+struct vla_bound_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+};
+
+struct invalid_value_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+};
+
+struct nonnull_arg_data {
+	struct source_location loc;
+};
+
+struct nonnull_return_data {
+	struct source_location loc;
+	struct source_location attr_loc;
+};
+
+/*
+ * When compiling with -fsanitize=undefined the compiler expects functions
+ * with the following signatures. The functions are never called directly,
+ * only when undefined behavior is detected in instrumented code.
+ */
+void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr);
+void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_mul_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long old_val);
+void __ubsan_handle_divrem_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, unsigned long idx);
+void __ubsan_handle_unreachable(struct unreachable_data *data);
+void __ubsan_handle_missing_return(struct unreachable_data *data);
+void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, unsigned long bound);
+void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, unsigned long val);
+#if __GCC_VERSION < 60000
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no);
+#else
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data);
+#endif
+void __ubsan_handle_nonnull_return(struct nonnull_return_data *data);
+
+static void print_loc(const char *func, struct source_location *loc)
+{
+	const char *f = func;
+	const char func_prefix[] = "__ubsan_handle";
+
+	if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1))
+		f += sizeof(func_prefix);
+
+	PRINTF("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32 "\n",
+	    f, loc->file_name, loc->line, loc->column);
+}
+
+void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
+    unsigned long ptr)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_add_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_sub_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_mul_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_negate_overflow(struct overflow_data *data,
+    unsigned long old_val)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_divrem_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	PRINTF("LHS type: %s, value: %lu, RHS type: %s, value: %lu\n",
+	    data->lhs_type->type_name, lhs, data->rhs_type->type_name, rhs);
+	ubsan_panic();
+}
+
+void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
+    unsigned long idx)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_unreachable(struct unreachable_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_missing_return(struct unreachable_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
+    unsigned long bound)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
+    unsigned long val)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+#if __GCC_VERSION < 60000
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+#else
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+#endif
+
+void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ uspace/Makefile.common	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -190,4 +190,8 @@
 endif
 
+ifeq ($(CONFIG_UBSAN),y)
+	DEFAULT_CFLAGS += -fsanitize=undefined
+endif
+
 ifeq ($(COMPILER),clang)
 	DEFAULT_CFLAGS += \
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ uspace/lib/c/Makefile	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -165,4 +165,5 @@
 	generic/pio_trace.c \
 	generic/qsort.c \
+	generic/ubsan.c \
 	generic/uuid.c \
 	generic/vbd.c \
Index: uspace/lib/c/generic/ubsan.c
===================================================================
--- uspace/lib/c/generic/ubsan.c	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
+++ uspace/lib/c/generic/ubsan.c	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2016, Linaro Limited
+ */
+
+/* Modified for HelenOS use by Jiří Zárevúcky. */
+
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <mem.h>
+#include <io/kio.h>
+
+#define PRINTF(...) kio_printf(__VA_ARGS__)
+#define ubsan_panic() abort()
+
+struct source_location {
+	const char *file_name;
+	uint32_t line;
+	uint32_t column;
+};
+
+struct type_descriptor {
+	uint16_t type_kind;
+	uint16_t type_info;
+	char type_name[];
+};
+
+struct type_mismatch_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+	unsigned long alignment;
+	unsigned char type_check_kind;
+};
+
+struct overflow_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+};
+
+struct shift_out_of_bounds_data {
+	struct source_location loc;
+	struct type_descriptor *lhs_type;
+	struct type_descriptor *rhs_type;
+};
+
+struct out_of_bounds_data {
+	struct source_location loc;
+	struct type_descriptor *array_type;
+	struct type_descriptor *index_type;
+};
+
+struct unreachable_data {
+	struct source_location loc;
+};
+
+struct vla_bound_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+};
+
+struct invalid_value_data {
+	struct source_location loc;
+	struct type_descriptor *type;
+};
+
+struct nonnull_arg_data {
+	struct source_location loc;
+};
+
+struct nonnull_return_data {
+	struct source_location loc;
+	struct source_location attr_loc;
+};
+
+/*
+ * When compiling with -fsanitize=undefined the compiler expects functions
+ * with the following signatures. The functions are never called directly,
+ * only when undefined behavior is detected in instrumented code.
+ */
+void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr);
+void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_mul_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long old_val);
+void __ubsan_handle_divrem_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, unsigned long idx);
+void __ubsan_handle_unreachable(struct unreachable_data *data);
+void __ubsan_handle_missing_return(struct unreachable_data *data);
+void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, unsigned long bound);
+void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, unsigned long val);
+#if __GCC_VERSION < 60000
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no);
+#else
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data);
+#endif
+void __ubsan_handle_nonnull_return(struct nonnull_return_data *data);
+
+static void print_loc(const char *func, struct source_location *loc)
+{
+	const char *f = func;
+	const char func_prefix[] = "__ubsan_handle";
+
+	if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1))
+		f += sizeof(func_prefix);
+
+	PRINTF("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32 "\n",
+	    f, loc->file_name, loc->line, loc->column);
+}
+
+void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
+    unsigned long ptr)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_add_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_sub_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_mul_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_negate_overflow(struct overflow_data *data,
+    unsigned long old_val)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_divrem_overflow(struct overflow_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
+    unsigned long lhs,
+    unsigned long rhs)
+{
+	print_loc(__func__, &data->loc);
+	PRINTF("LHS type: %s, value: %lu, RHS type: %s, value: %lu\n",
+	    data->lhs_type->type_name, lhs, data->rhs_type->type_name, rhs);
+	ubsan_panic();
+}
+
+void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
+    unsigned long idx)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_unreachable(struct unreachable_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_missing_return(struct unreachable_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
+    unsigned long bound)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
+    unsigned long val)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+
+#if __GCC_VERSION < 60000
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+#else
+void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
+#endif
+
+void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
+{
+	print_loc(__func__, &data->loc);
+	ubsan_panic();
+}
Index: uspace/srv/fs/fat/fat_fat.c
===================================================================
--- uspace/srv/fs/fat/fat_fat.c	(revision abf8bd83815e2b5576079beb43f800b6af69cf8d)
+++ uspace/srv/fs/fat/fat_fat.c	(revision 2f7d77c6250db2dbaf4fc40c073fd148af44fd39)
@@ -967,5 +967,5 @@
 		 */
 		if (!FAT_IS_FAT12(bs) &&
-		    ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
+		    ((e0 >> 8) != ((fat_cluster_t) FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
 			return ENOTSUP;
 	}
