From e288f690afdef701f76b7f85e25ca6bdf647716f Mon Sep 17 00:00:00 2001 From: Explorer09 Date: Thu, 2 Jun 2016 18:30:18 +0800 Subject: [PATCH 1/3] Don't check if (!str) in xStrdup This effectively reverts "Stricter strdup." 4674b4a7320bb6b003a4e3b3840027573691e60d If str is NULL upon the calling of strdup(), it should crash with SIGSEGV. Just let it crash. Adding the "if (!str) fail();" code serves nothing but bloat. --- XAlloc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/XAlloc.c b/XAlloc.c index 34a444f2..010d761d 100644 --- a/XAlloc.c +++ b/XAlloc.c @@ -44,9 +44,6 @@ void* xRealloc(void* ptr, size_t size) { } char* xStrdup(const char* str) { - if (!str) { - fail(); - } char* data = strdup(str); if (!data) { fail(); From 3297616efa05565b7944a83b11a9aabcdde08986 Mon Sep 17 00:00:00 2001 From: Explorer09 Date: Thu, 2 Jun 2016 20:38:24 +0800 Subject: [PATCH 2/3] Add assert and __attribute__((nonnull)) on xStrdup __attribute__((nonnull)) will help catching "calling with NULL" mistake on compile time. I also convert xStrdup into a macro, that will do assert() inline when the code is *not* built with -DNDEBUG . For release builds (with -DNDEBUG), preprocessor trick will ensure that generated code remains the same. --- XAlloc.c | 15 ++++++++++++++- XAlloc.h | 14 +++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/XAlloc.c b/XAlloc.c index 010d761d..5bda74ed 100644 --- a/XAlloc.c +++ b/XAlloc.c @@ -5,6 +5,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include #include #include #include @@ -43,7 +44,19 @@ void* xRealloc(void* ptr, size_t size) { return data; } -char* xStrdup(const char* str) { +#undef xStrdup +#undef xStrdup_ +#ifdef NDEBUG +# define xStrdup_ xStrdup +#else +# define xStrdup(str_) (assert(str_), xStrdup_(str_)) +#endif + +#if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +char* xStrdup_(const char* str) __attribute__((nonnull)); +#endif // GNU C 3.3 or later + +char* xStrdup_(const char* str) { char* data = strdup(str); if (!data) { fail(); diff --git a/XAlloc.h b/XAlloc.h index 3cc060d9..22a6e8ab 100644 --- a/XAlloc.h +++ b/XAlloc.h @@ -15,6 +15,18 @@ void* xCalloc(size_t nmemb, size_t size); void* xRealloc(void* ptr, size_t size); -char* xStrdup(const char* str); +#undef xStrdup +#undef xStrdup_ +#ifdef NDEBUG +# define xStrdup_ xStrdup +#else +# define xStrdup(str_) (assert(str_), xStrdup_(str_)) +#endif + +#if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +char* xStrdup_(const char* str) __attribute__((nonnull)); +#endif // GNU C 3.3 or later + +char* xStrdup_(const char* str); #endif From c0e37bc5f50497d422f25bb82f3396168eb146a2 Mon Sep 17 00:00:00 2001 From: Explorer09 Date: Fri, 3 Jun 2016 10:14:27 +0800 Subject: [PATCH 3/3] Fix xStrdup debug build failure & allow Clang to use ((nonnull)) --- XAlloc.c | 10 +++++++--- XAlloc.h | 9 +++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/XAlloc.c b/XAlloc.c index 5bda74ed..5f2e9a4b 100644 --- a/XAlloc.c +++ b/XAlloc.c @@ -5,12 +5,12 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#include #include #include #include /*{ +#include #include }*/ @@ -52,9 +52,13 @@ void* xRealloc(void* ptr, size_t size) { # define xStrdup(str_) (assert(str_), xStrdup_(str_)) #endif -#if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +#ifndef __has_attribute // Clang's macro +# define __has_attribute(x) 0 +#endif +#if (__has_attribute(nonnull) || \ + ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))) char* xStrdup_(const char* str) __attribute__((nonnull)); -#endif // GNU C 3.3 or later +#endif // __has_attribute(nonnull) || GNU C 3.3 or later char* xStrdup_(const char* str) { char* data = strdup(str); diff --git a/XAlloc.h b/XAlloc.h index 22a6e8ab..eaebb087 100644 --- a/XAlloc.h +++ b/XAlloc.h @@ -7,6 +7,7 @@ #define _GNU_SOURCE #endif +#include #include void* xMalloc(size_t size); @@ -23,9 +24,13 @@ void* xRealloc(void* ptr, size_t size); # define xStrdup(str_) (assert(str_), xStrdup_(str_)) #endif -#if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +#ifndef __has_attribute // Clang's macro +# define __has_attribute(x) 0 +#endif +#if (__has_attribute(nonnull) || \ + ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))) char* xStrdup_(const char* str) __attribute__((nonnull)); -#endif // GNU C 3.3 or later +#endif // __has_attribute(nonnull) || GNU C 3.3 or later char* xStrdup_(const char* str);