]> granicus.if.org Git - icu/commitdiff
ICU-8235 do not call memcpy()/memmove()/... with a NULL/invalid source pointer
authorMarkus Scherer <markus.icu@gmail.com>
Thu, 7 Jun 2012 00:14:54 +0000 (00:14 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Thu, 7 Jun 2012 00:14:54 +0000 (00:14 +0000)
X-SVN-Rev: 31914

icu4c/source/common/cmemory.c
icu4c/source/common/cmemory.h
icu4c/source/common/cstring.h
icu4c/source/common/unicode/ustring.h
icu4c/source/common/ustring.cpp

index d0839215207878f04ce97d7cd02ea23588f7b592..cd3ccac6c9be34a93fcd2a24a7ff7d8534f4b0af 100644 (file)
 #include "unicode/uclean.h"
 #include "cmemory.h"
 #include "putilimp.h"
+#include "uassert.h"
 #include <stdlib.h>
 
-/* uprv_malloc(0) returns a pointer to this read-only data. */                
+/* uprv_malloc(0) returns a pointer to this read-only data. */
 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0};
 
 /* Function Pointers for user-supplied heap functions  */
@@ -42,6 +43,29 @@ static int n=0;
 static long b=0; 
 #endif
 
+#if U_DEBUG
+
+static char gValidMemorySink = 0;
+
+U_CAPI void uprv_checkValidMemory(const void *p, size_t n) {
+    /*
+     * Access the memory to ensure that it's all valid.
+     * Load and save a computed value to try to ensure that the compiler
+     * does not throw away the whole loop.
+     * A thread analyzer might complain about un-mutexed access to gValidMemorySink
+     * which is true but harmless because no one ever uses the value in gValidMemorySink.
+     */
+    const char *s = (const char *)p;
+    char c = gValidMemorySink;
+    size_t i;
+    U_ASSERT(p != NULL);
+    for(i = 0; i < n; ++i) {
+        c ^= s[i];
+    }
+    gValidMemorySink = c;
+}
+
+#endif  /* U_DEBUG */
 
 U_CAPI void * U_EXPORT2
 uprv_malloc(size_t s) {
index 78db8c529ceb86d6d14255206eddb5d794e910c5..cbaceba0325ee3adba6f1064c608ae195a1ccdb7 100644 (file)
 #include <stdio.h>
 #endif
 
+#if U_DEBUG
+
+/*
+ * The C++ standard requires that the source pointer for memcpy() & memmove()
+ * is valid, not NULL, and not at the end of an allocated memory block.
+ * In debug mode, we read one byte from the source point to verify that it's
+ * a valid, readable pointer.
+ */
+
+U_CAPI void uprv_checkValidMemory(const void *p, size_t n);
+
+#define uprv_memcpy(dst, src, size) ( \
+    uprv_checkValidMemory(src, 1), \
+    U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size))
+#define uprv_memmove(dst, src, size) ( \
+    uprv_checkValidMemory(src, 1), \
+    U_STANDARD_CPP_NAMESPACE memmove(dst, src, size))
+
+#else
+
 #define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
 #define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
+
+#endif  /* U_DEBUG */
+
 #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
 #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
 
index e7cea641bbb52704ac6fcc5334bd48b5b8954f04..64b68ffabb26bcb915626ed4d115e942d37bb771 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1997-2011, International Business Machines
+*   Copyright (C) 1997-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
 #define CSTRING_H 1
 
 #include "unicode/utypes.h"
+#include "cmemory.h"
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 
 #define uprv_strcpy(dst, src) U_STANDARD_CPP_NAMESPACE  strcpy(dst, src)
-#define uprv_strncpy(dst, src, size) U_STANDARD_CPP_NAMESPACE strncpy(dst, src, size)
 #define uprv_strlen(str) U_STANDARD_CPP_NAMESPACE strlen(str)
 #define uprv_strcmp(s1, s2) U_STANDARD_CPP_NAMESPACE strcmp(s1, s2)
-#define uprv_strncmp(s1, s2, n) U_STANDARD_CPP_NAMESPACE strncmp(s1, s2, n)
 #define uprv_strcat(dst, src) U_STANDARD_CPP_NAMESPACE strcat(dst, src)
-#define uprv_strncat(dst, src, n) U_STANDARD_CPP_NAMESPACE strncat(dst, src, n)
 #define uprv_strchr(s, c) U_STANDARD_CPP_NAMESPACE strchr(s, c)
 #define uprv_strstr(s, c) U_STANDARD_CPP_NAMESPACE strstr(s, c)
 #define uprv_strrchr(s, c) U_STANDARD_CPP_NAMESPACE strrchr(s, c)
 
+#if U_DEBUG
+
+#define uprv_strncpy(dst, src, size) ( \
+    uprv_checkValidMemory(src, 1), \
+    U_STANDARD_CPP_NAMESPACE strncpy(dst, src, size))
+#define uprv_strncmp(s1, s2, n) ( \
+    uprv_checkValidMemory(s1, 1), \
+    uprv_checkValidMemory(s2, 1), \
+    U_STANDARD_CPP_NAMESPACE strncmp(s1, s2, n))
+#define uprv_strncat(dst, src, n) ( \
+    uprv_checkValidMemory(src, 1), \
+    U_STANDARD_CPP_NAMESPACE strncat(dst, src, n))
+
+#else
+
+#define uprv_strncpy(dst, src, size) U_STANDARD_CPP_NAMESPACE strncpy(dst, src, size)
+#define uprv_strncmp(s1, s2, n) U_STANDARD_CPP_NAMESPACE strncmp(s1, s2, n)
+#define uprv_strncat(dst, src, n) U_STANDARD_CPP_NAMESPACE strncat(dst, src, n)
+
+#endif  /* U_DEBUG */
+
 /**
  * Is c an ASCII-repertoire letter a-z or A-Z?
  * Note: The implementation is specific to whether ICU is compiled for
index 388bc74a4093a6cfb52f3a034d298764dbe28e3a..9c05edcb3b2bb091a421a89ec27e37594e06da9b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 1998-2010, International Business Machines
+*   Copyright (C) 1998-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *
@@ -146,8 +146,8 @@ u_strcat(UChar     *dst,
  * If <code>n&lt;=0</code> then dst is not modified.
  *
  * @param dst The destination string.
- * @param src The source string.
- * @param n The maximum number of characters to append.
+ * @param src The source string (can be NULL/invalid if n<=0).
+ * @param n The maximum number of characters to append; no-op if <=0.
  * @return A pointer to <code>dst</code>.
  * @stable ICU 2.0
  */
@@ -550,9 +550,9 @@ u_strCaseCompare(const UChar *s1, int32_t length1,
  * Compare two ustrings for bitwise equality. 
  * Compares at most <code>n</code> characters.
  *
- * @param ucs1 A string to compare.
- * @param ucs2 A string to compare.
- * @param n The maximum number of characters to compare.
+ * @param ucs1 A string to compare (can be NULL/invalid if n<=0).
+ * @param ucs2 A string to compare (can be NULL/invalid if n<=0).
+ * @param n The maximum number of characters to compare; always returns 0 if n<=0.
  * @return 0 if <code>s1</code> and <code>s2</code> are bitwise equal; a negative
  * value if <code>s1</code> is bitwise less than <code>s2</code>; a positive
  * value if <code>s1</code> is bitwise greater than <code>s2</code>.
@@ -667,8 +667,8 @@ u_strcpy(UChar     *dst,
  * if the length of <code>src</code> is less than <code>n</code>.
  *
  * @param dst The destination string.
- * @param src The source string.
- * @param n The maximum number of characters to copy.
+ * @param src The source string (can be NULL/invalid if n<=0).
+ * @param n The maximum number of characters to copy; no-op if <=0.
  * @return A pointer to <code>dst</code>.
  * @stable ICU 2.0
  */
@@ -742,8 +742,8 @@ U_STABLE char* U_EXPORT2 u_austrncpy(char *dst,
 /**
  * Synonym for memcpy(), but with UChars only.
  * @param dest The destination string
- * @param src The source string
- * @param count The number of characters to copy
+ * @param src The source string (can be NULL/invalid if count<=0)
+ * @param count The number of characters to copy; no-op if <=0
  * @return A pointer to <code>dest</code>
  * @stable ICU 2.0
  */
@@ -753,8 +753,8 @@ u_memcpy(UChar *dest, const UChar *src, int32_t count);
 /**
  * Synonym for memmove(), but with UChars only.
  * @param dest The destination string
- * @param src The source string
- * @param count The number of characters to move
+ * @param src The source string (can be NULL/invalid if count<=0)
+ * @param count The number of characters to move; no-op if <=0
  * @return A pointer to <code>dest</code>
  * @stable ICU 2.0
  */
index 3210cfc215e2ec4d59c039beee5bd9a5d3baa67b..dd4f727ba1a550a6ce77c94515316961268b5d4f 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1998-2011, International Business Machines
+*   Copyright (C) 1998-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
@@ -1112,12 +1112,18 @@ u_strHasMoreChar32Than(const UChar *s, int32_t length, int32_t number) {
 
 U_CAPI UChar * U_EXPORT2
 u_memcpy(UChar *dest, const UChar *src, int32_t count) {
-    return (UChar *)uprv_memcpy(dest, src, count*U_SIZEOF_UCHAR);
+    if(count > 0) {
+        uprv_memcpy(dest, src, count*U_SIZEOF_UCHAR);
+    }
+    return dest;
 }
 
 U_CAPI UChar * U_EXPORT2
 u_memmove(UChar *dest, const UChar *src, int32_t count) {
-    return (UChar *)uprv_memmove(dest, src, count*U_SIZEOF_UCHAR);
+    if(count > 0) {
+        uprv_memmove(dest, src, count*U_SIZEOF_UCHAR);
+    }
+    return dest;
 }
 
 U_CAPI UChar * U_EXPORT2