Merge change If8e2929a
* changes:
Don't allocate arbitrary-length buffers on the stack.
diff --git a/libcore/NativeCode.mk b/libcore/NativeCode.mk
index 0dfad3b..57c4903 100644
--- a/libcore/NativeCode.mk
+++ b/libcore/NativeCode.mk
@@ -74,7 +74,7 @@
# Extract out the allowed LOCAL_* variables. Note: $(sort) also
# removes duplicates.
-core_c_includes := $(sort $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
+core_c_includes := $(sort dalvik/libcore/include $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
core_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES))
core_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES))
@@ -118,4 +118,4 @@
# TODO: Figure out cacerts.bks for the host.
-endif
\ No newline at end of file
+endif
diff --git a/libcore/include/LocalArray.h b/libcore/include/LocalArray.h
new file mode 100644
index 0000000..85b5a49
--- /dev/null
+++ b/libcore/include/LocalArray.h
@@ -0,0 +1,55 @@
+#ifndef LOCAL_ARRAY_H_included
+#define LOCAL_ARRAY_H_included
+
+#include <cstddef>
+#include <new>
+
+/**
+ * A fixed-size array with a size hint. That number of bytes will be allocated
+ * on the stack, and used if possible, but if more bytes are requested at
+ * construction time, a buffer will be allocated on the heap (and deallocated
+ * by the destructor).
+ *
+ * The API is intended to be a compatible subset of C++0x's std::array.
+ */
+template <size_t STACK_BYTE_COUNT>
+class LocalArray {
+public:
+ /**
+ * Allocates a new fixed-size array of the given size. If this size is
+ * less than or equal to the template parameter STACK_BYTE_COUNT, an
+ * internal on-stack buffer will be used. Otherwise a heap buffer will
+ * be allocated.
+ */
+ LocalArray(size_t desiredByteCount) : mSize(desiredByteCount) {
+ if (desiredByteCount > STACK_BYTE_COUNT) {
+ mPtr = new char[mSize];
+ } else {
+ mPtr = &mOnStackBuffer[0];
+ }
+ }
+
+ /**
+ * Frees the heap-allocated buffer, if there was one.
+ */
+ ~LocalArray() {
+ if (mPtr != &mOnStackBuffer[0]) {
+ delete[] mPtr;
+ }
+ }
+
+ // Capacity.
+ size_t size() { return mSize; }
+ bool empty() { return mSize == 0; }
+
+ // Element access.
+ char& operator[](size_t n) { return mPtr[n]; }
+ const char& operator[](size_t n) const { return mPtr[n]; }
+
+private:
+ char mOnStackBuffer[STACK_BYTE_COUNT];
+ char* mPtr;
+ size_t mSize;
+};
+
+#endif // LOCAL_ARRAY_H_included
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 3f58736..b4b6d92 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -25,6 +25,7 @@
#include "AndroidSystemNatives.h"
#include "JNIHelp.h"
+#include "LocalArray.h"
#include "jni.h"
#include <arpa/inet.h>
@@ -485,13 +486,10 @@
return NULL;
}
- // We need to reserve two extra bytes for the possible '[' and ']'.
- char ipString[INET6_ADDRSTRLEN + 2];
+ // Convert the String to UTF bytes.
size_t byteCount = env->GetStringUTFLength(javaString);
- if (byteCount + 1 > sizeof(ipString)) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "string too long");
- return NULL;
- }
+ LocalArray<INET6_ADDRSTRLEN> bytes(byteCount + 1);
+ char* ipString = &bytes[0];
env->GetStringUTFRegion(javaString, 0, env->GetStringLength(javaString), ipString);
// Accept IPv6 addresses (only) in square brackets for compatibility.
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index 538b7f3..1a6c3ae 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "OpenSSLSocketImpl"
-#include <cutils/log.h>
-#include <jni.h>
-#include <JNIHelp.h>
+#include "JNIHelp.h"
+#include "LocalArray.h"
+#include "cutils/log.h"
+#include "jni.h"
#include <stdio.h>
#include <string.h>
@@ -53,14 +54,12 @@
* stored in a freshly-allocated BIO memory buffer.
*/
static BIO *stringToMemBuf(JNIEnv* env, jstring string) {
- BIO *result = BIO_new(BIO_s_mem());
- jsize length = env->GetStringUTFLength(string);
- char buf[length + 1];
-
- env->GetStringUTFRegion(string, 0, env->GetStringLength(string), buf);
- buf[length] = '\0';
+ jsize byteCount = env->GetStringUTFLength(string);
+ LocalArray<1024> buf(byteCount + 1);
+ env->GetStringUTFRegion(string, 0, env->GetStringLength(string), &buf[0]);
- BIO_puts(result, buf);
+ BIO* result = BIO_new(BIO_s_mem());
+ BIO_puts(result, &buf[0]);
return result;
}
diff --git a/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 9192b1a..701dbd9 100644
--- a/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "ExpatParser"
+#include "JNIHelp.h"
+#include "LocalArray.h"
#include "jni.h"
#include "utils/Log.h"
-#include "JNIHelp.h"
#include <string.h>
#include <utils/misc.h>
@@ -1242,30 +1243,24 @@
static jint getAttributeIndex(JNIEnv* env, jobject clazz,
jint attributePointer, jstring uri, jstring localName) {
const char** attributes = (const char**) attributePointer;
- int uriLength = env->GetStringUTFLength(uri);
-
- if (uriLength == 0) {
+ int uriByteCount = env->GetStringUTFLength(uri);
+ if (uriByteCount == 0) {
// If there's no URI, then a local name works just like a qName.
return getAttributeIndexForQName(
env, clazz, attributePointer, localName);
}
- int localNameLength = env->GetStringUTFLength(localName);
- // Create string in the same format used by Expat: "uri|localName"
- // TODO: do we have a guarantee that uriLength and localNameLength are small?
- char concatenated[uriLength + localNameLength + 2];
+ // Create string in the same format used by Expat: "uri|localName\0".
+ // Note that we need byte counts to size the array but Unicode char counts
+ // for GetStringUTFRegion indexes and counts.
+ int localNameByteCount = env->GetStringUTFLength(localName);
+ LocalArray<1024> concatenated(uriByteCount + 1 + localNameByteCount + 1);
+ env->GetStringUTFRegion(uri, 0, env->GetStringLength(uri), &concatenated[0]);
+ concatenated[uriByteCount] = '|';
+ env->GetStringUTFRegion(localName, 0, env->GetStringLength(localName),
+ &concatenated[uriByteCount + 1]);
- // Append uri.
- env->GetStringUTFRegion(uri, 0, uriLength, concatenated);
-
- // Separator.
- concatenated[uriLength] = '|';
-
- // Append local name.
- env->GetStringUTFRegion(localName, 0, localNameLength,
- concatenated + uriLength + 1);
-
- return findAttributeByName(attributes, concatenated);
+ return findAttributeByName(attributes, &concatenated[0]);
}
/**