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]);
 }
 
 /**