From 9d87d7695731ed27ab80da71d5e162982eeeda3a Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 13 May 2015 20:27:49 +0200 Subject: [PATCH] Abort on overlapping memcpy. --- kernel/libk.cpp | 6 ++++++ libc/include/libk.h | 2 ++ libc/string/memcpy.c | 28 +++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/kernel/libk.cpp b/kernel/libk.cpp index 0bd4cf31..baa301a9 100644 --- a/kernel/libk.cpp +++ b/kernel/libk.cpp @@ -96,6 +96,12 @@ void libk_abort(void) Sortix::PanicF("abort()"); } +extern "C" +void libk_overlapping_memcpy(void) +{ + Sortix::PanicF("Overlapping memcpy detected"); +} + extern "C" void libk_random_lock(void) { diff --git a/libc/include/libk.h b/libc/include/libk.h index 32a11987..498c766d 100644 --- a/libc/include/libk.h +++ b/libc/include/libk.h @@ -41,6 +41,8 @@ __attribute__((noreturn)) void libk_stack_chk_fail(void); __attribute__((noreturn)) void libk_abort(void); +__attribute__((noreturn)) +void libk_overlapping_memcpy(void); void libk_random_lock(void); void libk_random_unlock(void); bool libk_hasentropy(size_t); diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c index ede0db88..6ee6fda3 100644 --- a/libc/string/memcpy.c +++ b/libc/string/memcpy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * Copyright (c) 2011, 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,9 +17,15 @@ * Copy memory between non-overlapping regions. */ +#include #include +#include #include +#if defined(__is_sortix_libk) +#include +#endif + inline static void* memcpy_slow(void* restrict dst_ptr, const void* restrict src_ptr, @@ -36,6 +42,26 @@ void* memcpy(void* restrict dst_ptr, const void* restrict src_ptr, size_t size) { + if ( dst_ptr == src_ptr || !size ) + return dst_ptr; + + void* dst_end = (char*) dst_ptr + size; + const void* src_end = (const const char*) src_ptr + size; + if ( (dst_ptr < src_ptr && src_ptr < dst_end) || + (src_ptr < dst_ptr && dst_ptr < src_end) ) + { +#if defined(__is_sortix_libk) + libk_overlapping_memcpy(); +#else + struct scram_undefined_behavior info; + info.filename = __FILE__; + info.line = __LINE__; + info.column = 0; + info.violation = "overlapping memcpy"; + scram(SCRAM_UNDEFINED_BEHAVIOR, &info); +#endif + } + #if 8 < __SIZEOF_LONG__ #warning "you should add support for your unexpectedly large unsigned long." return memcpy_slow(dst_ptr, src_ptr, size);