diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index a1a13efa22..9869538cf6 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -504,6 +504,8 @@ class MyClasspath : public Classpath { object charArray = makeCharArray(t, length); for (int i = 0; i < length; ++i) { + expect(t, (byteArrayBody(t, array, offset + i) & 0x80) == 0); + charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i); } @@ -5039,7 +5041,7 @@ jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) jobject pool = reinterpret_cast(arguments[0]); jint index = arguments[1]; - object array = singletonObject(t, *pool, index - 1); + object array = parseUtf8(t, singletonObject(t, *pool, index - 1)); return reinterpret_cast (makeLocalReference diff --git a/src/machine.cpp b/src/machine.cpp index 828de31fc0..0d0ad96865 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -727,7 +727,7 @@ finalizeObject(Thread* t, object o, const char* name) } unsigned -readByte(Stream& s, unsigned* value) +readByte(AbstractStream& s, unsigned* value) { if (*value == NoByte) { return s.read1(); @@ -739,8 +739,9 @@ readByte(Stream& s, unsigned* value) } object -parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, - unsigned sourceIndex, unsigned byteA, unsigned byteB) +parseUtf8NonAscii(Thread* t, AbstractStream& s, object bytesSoFar, + unsigned byteCount, unsigned sourceIndex, unsigned byteA, + unsigned byteB) { PROTECT(t, bytesSoFar); @@ -792,7 +793,7 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, } object -parseUtf8(Thread* t, Stream& s, unsigned length) +parseUtf8(Thread* t, AbstractStream& s, unsigned length) { object value = makeByteArray(t, length + 1); unsigned vi = 0; @@ -830,6 +831,14 @@ parseUtf8(Thread* t, Stream& s, unsigned length) return value; } +object +makeByteArray(Thread* t, Stream& s, unsigned length) +{ + object value = makeByteArray(t, length + 1); + s.read(reinterpret_cast(&byteArrayBody(t, value, 0)), length); + return value; +} + void removeByteArray(Thread* t, object o) { @@ -885,10 +894,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) case CONSTANT_Utf8: { if (singletonObject(t, pool, i) == 0) { - object value = parseUtf8(t, s, s.read2()); - if (objectClass(t, value) == type(t, Machine::ByteArrayType)) { - value = internByteArray(t, value); - } + object value = internByteArray(t, makeByteArray(t, s, s.read2())); set(t, pool, SingletonBody + (i * BytesPerWord), value); if(DebugClassReader) { @@ -916,7 +922,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) unsigned si = s.read2() - 1; parsePoolEntry(t, s, index, pool, si); - object value = singletonObject(t, pool, si); + object value = parseUtf8(t, singletonObject(t, pool, si)); value = t->m->classpath->makeString (t, value, 0, cast(value, BytesPerWord) - 1); value = intern(t, value); @@ -4886,6 +4892,62 @@ parseUtf8(Thread* t, const char* data, unsigned length) return ::parseUtf8(t, s, length); } +object +parseUtf8(Thread* t, object array) +{ + for (unsigned i = 0; i < byteArrayLength(t, array) - 1; ++i) { + if (byteArrayBody(t, array, i) & 0x80) { + goto slow_path; + } + } + + return array; + + slow_path: + class Client: public Stream::Client { + public: + Client(Thread* t): t(t) { } + + virtual void handleError() { + // vm::abort(t); + } + + private: + Thread* t; + } client(t); + + class MyStream: public AbstractStream { + public: + class MyProtector: public Thread::Protector { + public: + MyProtector(Thread* t, MyStream* s): + Protector(t), s(s) + { } + + virtual void visit(Heap::Visitor* v) { + v->visit(&(s->array)); + } + + MyStream* s; + }; + + MyStream(Thread* t, Client* client, object array): + AbstractStream(client, byteArrayLength(t, array) - 1), + array(array), + protector(t, this) + { } + + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { + memcpy(dst, &byteArrayBody(protector.t, array, offset), size); + } + + object array; + MyProtector protector; + } s(t, &client, array); + + return ::parseUtf8(t, s, byteArrayLength(t, array) - 1); +} + object getCaller(Thread* t, unsigned target, bool skipMethodInvoke) { diff --git a/src/machine.h b/src/machine.h index f71788572d..08eab4c894 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2525,6 +2525,9 @@ emptyMethod(Thread* t, object method) object parseUtf8(Thread* t, const char* data, unsigned length); +object +parseUtf8(Thread* t, object array); + object parseClass(Thread* t, object loader, const uint8_t* data, unsigned length, Machine::Type throwType = Machine::NoClassDefFoundErrorType); diff --git a/src/stream.h b/src/stream.h index a08bf3b1a0..a46ad315d8 100644 --- a/src/stream.h +++ b/src/stream.h @@ -15,15 +15,15 @@ namespace vm { -class Stream { +class AbstractStream { public: class Client { public: virtual void handleError() = 0; }; - Stream(Client* client, const uint8_t* data, unsigned size): - client(client), data(data), size(size), position_(0) + AbstractStream(Client* client, unsigned size): + client(client), size(size), position_(0) { } unsigned position() { @@ -42,13 +42,13 @@ class Stream { } } - void read(uint8_t* data, unsigned size) { + void read(uint8_t* dst, unsigned size) { if (size > this->size - position_) { - memset(data, 0, size); + memset(dst, 0, size); client->handleError(); } else { - memcpy(data, this->data + position_, size); + copy(dst, position_, size); position_ += size; } } @@ -85,13 +85,29 @@ class Stream { return read8(); } + protected: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) = 0; + private: Client* client; - const uint8_t* data; unsigned size; unsigned position_; }; +class Stream: public AbstractStream { + public: + Stream(Client* client, const uint8_t* data, unsigned size): + AbstractStream(client, size), data(data) + { } + + private: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { + memcpy(dst, data + offset, size); + } + + const uint8_t* data; +}; + } // namespace vm #endif//STREAM_H diff --git a/test/Misc.java b/test/Misc.java index 450f23d2b0..620897332f 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,4 +1,12 @@ public class Misc { + private static class μClass { + public int μField; + + public void μMethod(int i) { + μField = i; + } + } + private interface Bar { public int baz(); } @@ -237,5 +245,10 @@ public class Misc { System.out.println(new char[] { 'h', 'i' }); expect(! (((Object) new int[0]) instanceof Object[])); + + { μClass μInstance = new μClass(); + μInstance.μMethod(8933); + expect(μInstance.μField == 8933); + } } }