Fix Class::IsInSamePackage to not read beyond the end of a StringPiece.
Fix length of string piece to be size_type rather than int because expecting
negatively sized strings is a bad idea and we should use unsigned types to
defensively guard against mistakes.
Remove max_size and capacity since the return type is inconsistent between
Google and the STL, and we don't need the functions.
Add a bound check in libartd to operator[] accesses.
Change-Id: I1b87a03d8fbd95e7dbb106745e304d1083898075
diff --git a/runtime/base/stringpiece.h b/runtime/base/stringpiece.h
index 2dde245..b8de308 100644
--- a/runtime/base/stringpiece.h
+++ b/runtime/base/stringpiece.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+#ifndef ART_RUNTIME_BASE_STRINGPIECE_H_
+#define ART_RUNTIME_BASE_STRINGPIECE_H_
+
+#include <string.h>
+#include <string>
+
+namespace art {
+
// A string-like object that points to a sized piece of memory.
//
// Functions or methods may use const StringPiece& parameters to accept either
@@ -21,74 +29,75 @@
// a StringPiece. The implicit conversion means that it is often appropriate
// to include this .h file in other files rather than forward-declaring
// StringPiece as would be appropriate for most other Google classes.
-//
-// Systematic usage of StringPiece is encouraged as it will reduce unnecessary
-// conversions from "const char*" to "string" and back again.
-
-#ifndef ART_RUNTIME_BASE_STRINGPIECE_H_
-#define ART_RUNTIME_BASE_STRINGPIECE_H_
-
-#include <string.h>
-#include <algorithm>
-#include <cstddef>
-#include <iosfwd>
-#include <string>
-
-namespace art {
-
class StringPiece {
- private:
- const char* ptr_;
- int length_;
-
public:
+ // standard STL container boilerplate
+ typedef char value_type;
+ typedef const char* pointer;
+ typedef const char& reference;
+ typedef const char& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ static constexpr size_type npos = size_type(-1);
+ typedef const char* const_iterator;
+ typedef const char* iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
// We provide non-explicit singleton constructors so users can pass
// in a "const char*" or a "string" wherever a "StringPiece" is
// expected.
- StringPiece() : ptr_(NULL), length_(0) { }
- StringPiece(const char* str) // NOLINT
- : ptr_(str), length_((str == NULL) ? 0 : static_cast<int>(strlen(str))) { }
- StringPiece(const std::string& str) // NOLINT
- : ptr_(str.data()), length_(static_cast<int>(str.size())) { }
- StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { }
+ StringPiece() : ptr_(nullptr), length_(0) { }
+ StringPiece(const char* str) // NOLINT implicit constructor desired
+ : ptr_(str), length_((str == nullptr) ? 0 : strlen(str)) { }
+ StringPiece(const std::string& str) // NOLINT implicit constructor desired
+ : ptr_(str.data()), length_(str.size()) { }
+ StringPiece(const char* offset, size_t len) : ptr_(offset), length_(len) { }
// data() may return a pointer to a buffer with embedded NULs, and the
// returned buffer may or may not be null terminated. Therefore it is
// typically a mistake to pass data() to a routine that expects a NUL
// terminated string.
const char* data() const { return ptr_; }
- int size() const { return length_; }
- int length() const { return length_; }
+ size_type size() const { return length_; }
+ size_type length() const { return length_; }
bool empty() const { return length_ == 0; }
void clear() {
- ptr_ = NULL;
+ ptr_ = nullptr;
length_ = 0;
}
- void set(const char* data, int len) {
+ void set(const char* data, size_type len) {
ptr_ = data;
length_ = len;
}
void set(const char* str) {
ptr_ = str;
- if (str != NULL)
- length_ = static_cast<int>(strlen(str));
- else
+ if (str != nullptr) {
+ length_ = strlen(str);
+ } else {
length_ = 0;
+ }
}
- void set(const void* data, int len) {
+ void set(const void* data, size_type len) {
ptr_ = reinterpret_cast<const char*>(data);
length_ = len;
}
- char operator[](int i) const { return ptr_[i]; }
+#if defined(NDEBUG)
+ char operator[](size_type i) const {
+ return ptr_[i];
+ }
+#else
+ char operator[](size_type i) const;
+#endif
- void remove_prefix(int n) {
+ void remove_prefix(size_type n) {
ptr_ += n;
length_ -= n;
}
- void remove_suffix(int n) {
+ void remove_suffix(size_type n) {
length_ -= n;
}
@@ -121,18 +130,6 @@
(memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
}
- // standard STL container boilerplate
- typedef char value_type;
- typedef const char* pointer;
- typedef const char& reference;
- typedef const char& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- static const size_type npos;
- typedef const char* const_iterator;
- typedef const char* iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
iterator begin() const { return ptr_; }
iterator end() const { return ptr_ + length_; }
const_reverse_iterator rbegin() const {
@@ -141,11 +138,8 @@
const_reverse_iterator rend() const {
return const_reverse_iterator(ptr_);
}
- // STLS says return size_type, but Google says return int
- int max_size() const { return length_; }
- int capacity() const { return length_; }
- int copy(char* buf, size_type n, size_type pos = 0) const;
+ size_type copy(char* buf, size_type n, size_type pos = 0) const;
size_type find(const StringPiece& s, size_type pos = 0) const;
size_type find(char c, size_type pos = 0) const;
@@ -153,13 +147,19 @@
size_type rfind(char c, size_type pos = npos) const;
StringPiece substr(size_type pos, size_type n = npos) const;
+
+ private:
+ // Pointer to char data, not necessarily zero terminated.
+ const char* ptr_;
+ // Length of data.
+ size_type length_;
};
// This large function is defined inline so that in a fairly common case where
// one of the arguments is a literal, the compiler can elide a lot of the
// following comparisons.
inline bool operator==(const StringPiece& x, const StringPiece& y) {
- int len = x.size();
+ StringPiece::size_type len = x.size();
if (len != y.size()) {
return false;
}
@@ -169,7 +169,7 @@
if (p1 == p2) {
return true;
}
- if (len <= 0) {
+ if (len == 0) {
return true;
}