summaryrefslogtreecommitdiff
path: root/include/llvm/ADT
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-05-20 19:24:12 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-05-20 19:24:12 +0000
commit6d5502eb4966fb2f81fe951d0acf11cfa5cd4acf (patch)
tree5982645c94efdfc95064ae37c960327071fc24db /include/llvm/ADT
parent0e29ed081b24359978916b997e91e3e1e2293915 (diff)
downloadllvm-6d5502eb4966fb2f81fe951d0acf11cfa5cd4acf.tar.gz
llvm-6d5502eb4966fb2f81fe951d0acf11cfa5cd4acf.tar.bz2
llvm-6d5502eb4966fb2f81fe951d0acf11cfa5cd4acf.tar.xz
Add asserts in StringRef to make sure we avoid undefined behavior:
-strlen should not be called with NULL. Also guarantee that StringRef's Length is 0 if Data is NULL. -memcmp should not be called with NULL (even if size is 0) Patch by Matthieu Monrocq! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131747 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r--include/llvm/ADT/StringRef.h27
1 files changed, 20 insertions, 7 deletions
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index dcc6aa2897..8396921744 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -46,7 +46,14 @@ namespace llvm {
// integer works around this bug.
static size_t min(size_t a, size_t b) { return a < b ? a : b; }
static size_t max(size_t a, size_t b) { return a > b ? a : b; }
-
+
+ // Workaround memcmp issue with null pointers (undefined behavior)
+ // by providing a specialized version
+ static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
+ if (Length == 0) { return 0; }
+ return ::memcmp(Lhs,Rhs,Length);
+ }
+
public:
/// @name Constructors
/// @{
@@ -56,11 +63,17 @@ namespace llvm {
/// Construct a string ref from a cstring.
/*implicit*/ StringRef(const char *Str)
- : Data(Str), Length(::strlen(Str)) {}
+ : Data(Str) {
+ assert(Str && "StringRef cannot be built from a NULL argument");
+ Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior
+ }
/// Construct a string ref from a pointer and length.
/*implicit*/ StringRef(const char *data, size_t length)
- : Data(data), Length(length) {}
+ : Data(data), Length(length) {
+ assert((data || length == 0) &&
+ "StringRef cannot be built from a NULL argument with non-null length");
+ }
/// Construct a string ref from an std::string.
/*implicit*/ StringRef(const std::string &Str)
@@ -104,7 +117,7 @@ namespace llvm {
/// compare() when the relative ordering of inequal strings isn't needed.
bool equals(StringRef RHS) const {
return (Length == RHS.Length &&
- memcmp(Data, RHS.Data, RHS.Length) == 0);
+ compareMemory(Data, RHS.Data, RHS.Length) == 0);
}
/// equals_lower - Check for string equality, ignoring case.
@@ -116,7 +129,7 @@ namespace llvm {
/// is lexicographically less than, equal to, or greater than the \arg RHS.
int compare(StringRef RHS) const {
// Check the prefix for a mismatch.
- if (int Res = memcmp(Data, RHS.Data, min(Length, RHS.Length)))
+ if (int Res = compareMemory(Data, RHS.Data, min(Length, RHS.Length)))
return Res < 0 ? -1 : 1;
// Otherwise the prefixes match, so we only need to check the lengths.
@@ -183,13 +196,13 @@ namespace llvm {
/// startswith - Check if this string starts with the given \arg Prefix.
bool startswith(StringRef Prefix) const {
return Length >= Prefix.Length &&
- memcmp(Data, Prefix.Data, Prefix.Length) == 0;
+ compareMemory(Data, Prefix.Data, Prefix.Length) == 0;
}
/// endswith - Check if this string ends with the given \arg Suffix.
bool endswith(StringRef Suffix) const {
return Length >= Suffix.Length &&
- memcmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
+ compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
}
/// @}