mirror of
https://github.com/corda/corda.git
synced 2025-01-31 16:35:43 +00:00
fix OpenJDK JCE support
This primarily required additions to classpath-openjdk.cpp to intercept ZipFile, ZipEntry, and JarFile native methods to consult embedded encryption policy jars when required.
This commit is contained in:
parent
874890e317
commit
78790a0f68
5
makefile
5
makefile
@ -90,7 +90,9 @@ ifneq ($(openjdk),)
|
|||||||
openjdk-jar-dep = $(build)/openjdk-jar.dep
|
openjdk-jar-dep = $(build)/openjdk-jar.dep
|
||||||
classpath-jar-dep = $(openjdk-jar-dep)
|
classpath-jar-dep = $(openjdk-jar-dep)
|
||||||
javahome = $(embed-prefix)/javahomeJar
|
javahome = $(embed-prefix)/javahomeJar
|
||||||
javahome-files = lib/zi lib/currency.data
|
javahome-files = lib/zi lib/currency.data lib/security/java.security \
|
||||||
|
lib/security/java.policy lib/security/cacerts \
|
||||||
|
lib/security/local_policy.jar lib/security/US_export_policy.jar
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
javahome-files += lib/tzmappings
|
javahome-files += lib/tzmappings
|
||||||
endif
|
endif
|
||||||
@ -905,5 +907,6 @@ $(openjdk-jar-dep):
|
|||||||
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" && \
|
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" && \
|
||||||
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jsse.jar")" && \
|
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jsse.jar")" && \
|
||||||
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jce.jar")" && \
|
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jce.jar")" && \
|
||||||
|
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/ext/sunjce_provider.jar")" && \
|
||||||
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/resources.jar")")
|
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/resources.jar")")
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
@ -224,6 +224,9 @@ class MyClasspath : public Classpath {
|
|||||||
sb.append("/lib/jce.jar");
|
sb.append("/lib/jce.jar");
|
||||||
sb.append(s->pathSeparator());
|
sb.append(s->pathSeparator());
|
||||||
sb.append(javaHome);
|
sb.append(javaHome);
|
||||||
|
sb.append("/lib/ext/sunjce_provider.jar");
|
||||||
|
sb.append(s->pathSeparator());
|
||||||
|
sb.append(javaHome);
|
||||||
sb.append("/lib/resources.jar");
|
sb.append("/lib/resources.jar");
|
||||||
sb.append('\0');
|
sb.append('\0');
|
||||||
|
|
||||||
@ -400,6 +403,13 @@ class MyClasspath : public Classpath {
|
|||||||
unsigned filePathField;
|
unsigned filePathField;
|
||||||
unsigned fileDescriptorFdField;
|
unsigned fileDescriptorFdField;
|
||||||
unsigned fileInputStreamFdField;
|
unsigned fileInputStreamFdField;
|
||||||
|
unsigned zipFileJzfileField;
|
||||||
|
unsigned zipEntryNameField;
|
||||||
|
unsigned zipEntryTimeField;
|
||||||
|
unsigned zipEntryCrcField;
|
||||||
|
unsigned zipEntrySizeField;
|
||||||
|
unsigned zipEntryCsizeField;
|
||||||
|
unsigned zipEntryMethodField;
|
||||||
bool ranNetOnLoad;
|
bool ranNetOnLoad;
|
||||||
char buffer[BufferSize];
|
char buffer[BufferSize];
|
||||||
};
|
};
|
||||||
@ -925,6 +935,438 @@ closeFile(Thread* t, object method, uintptr_t* arguments)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ZipFile {
|
||||||
|
public:
|
||||||
|
class Entry {
|
||||||
|
public:
|
||||||
|
Entry(unsigned hash, const uint8_t* start, Entry* next):
|
||||||
|
hash(hash), start(start), next(next), entry(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Entry(int64_t entry):
|
||||||
|
hash(0), start(0), next(0), entry(entry)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
unsigned hash;
|
||||||
|
const uint8_t* start;
|
||||||
|
Entry* next;
|
||||||
|
int64_t entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
ZipFile(Thread* t, System::Region* region, unsigned entryCount):
|
||||||
|
region(region),
|
||||||
|
entryCount(entryCount),
|
||||||
|
indexSize(nextPowerOfTwo(entryCount)),
|
||||||
|
index(reinterpret_cast<ZipFile::Entry**>
|
||||||
|
(t->m->heap->allocate(sizeof(ZipFile::Entry*) * indexSize))),
|
||||||
|
file(0)
|
||||||
|
{
|
||||||
|
memset(index, 0, sizeof(ZipFile::Entry*) * indexSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile(int64_t file):
|
||||||
|
region(0), entryCount(0), indexSize(0), index(0), file(file)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
System::Region* region;
|
||||||
|
unsigned entryCount;
|
||||||
|
unsigned indexSize;
|
||||||
|
Entry** index;
|
||||||
|
int64_t file;
|
||||||
|
Entry entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
openZipFile(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object path = reinterpret_cast<object>(arguments[0]);
|
||||||
|
int mode = arguments[1];
|
||||||
|
int64_t lastModified; memcpy(&lastModified, arguments + 2, 8);
|
||||||
|
|
||||||
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||||
|
|
||||||
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1);
|
||||||
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||||
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
||||||
|
|
||||||
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
||||||
|
if (ef.jar) {
|
||||||
|
if (ef.jarLength == 0 or ef.pathLength == 0) {
|
||||||
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
||||||
|
if (finder == 0) {
|
||||||
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
System::Region* r = finder->find(ef.path);
|
||||||
|
if (r == 0) {
|
||||||
|
throwNew(t, Machine::FileNotFoundExceptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* start = r->start();
|
||||||
|
const uint8_t* end = start + r->length();
|
||||||
|
unsigned entryCount = 0;
|
||||||
|
for (const uint8_t* p = end - CentralDirectorySearchStart; p > start;) {
|
||||||
|
if (get4(p) == CentralDirectorySignature) {
|
||||||
|
p = start + centralDirectoryOffset(p);
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
if (get4(p) == EntrySignature) {
|
||||||
|
++ entryCount;
|
||||||
|
|
||||||
|
p = endOfEntry(p);
|
||||||
|
} else {
|
||||||
|
goto make;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
-- p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make:
|
||||||
|
ZipFile* file = new
|
||||||
|
(t->m->heap->allocate
|
||||||
|
(sizeof(ZipFile) + (sizeof(ZipFile::Entry) * entryCount)))
|
||||||
|
ZipFile(t, r, entryCount);
|
||||||
|
|
||||||
|
{ unsigned position = 0;
|
||||||
|
for (const uint8_t* p = end - CentralDirectorySearchStart; p > start;) {
|
||||||
|
if (get4(p) == CentralDirectorySignature) {
|
||||||
|
p = start + centralDirectoryOffset(p);
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
if (get4(p) == EntrySignature) {
|
||||||
|
unsigned h = hash(fileName(p), fileNameLength(p));
|
||||||
|
unsigned i = h & (file->indexSize - 1);
|
||||||
|
|
||||||
|
file->index[i] = new (file->entries + (position++))
|
||||||
|
ZipFile::Entry(h, p, file->index[i]);
|
||||||
|
|
||||||
|
p = endOfEntry(p);
|
||||||
|
} else {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
-- p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return reinterpret_cast<int64_t>(file);
|
||||||
|
} else {
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(new (t->m->heap->allocate(sizeof(ZipFile))) ZipFile
|
||||||
|
(longValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, path, mode, lastModified))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getZipFileEntryCount(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
||||||
|
if (file->region) {
|
||||||
|
return file->entryCount;
|
||||||
|
} else {
|
||||||
|
return intValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile::Entry*
|
||||||
|
find(ZipFile* file, const char* path, unsigned pathLength)
|
||||||
|
{
|
||||||
|
unsigned i = hash(path) & (file->indexSize - 1);
|
||||||
|
for (ZipFile::Entry* e = file->index[i]; e; e = e->next) {
|
||||||
|
const uint8_t* p = e->start;
|
||||||
|
if (equal(path, pathLength, fileName(p), fileNameLength(p))) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
object path = reinterpret_cast<object>(arguments[2]);
|
||||||
|
bool addSlash = arguments[3];
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
||||||
|
if (file->region) {
|
||||||
|
THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 2);
|
||||||
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||||
|
replace('\\', '/', RUNTIME_ARRAY_BODY(p));
|
||||||
|
if (addSlash) {
|
||||||
|
RUNTIME_ARRAY_BODY(p)[stringLength(t, path)] = '/';
|
||||||
|
RUNTIME_ARRAY_BODY(p)[stringLength(t, path) + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>(find(file, p, stringLength(t, path)));
|
||||||
|
} else {
|
||||||
|
int64_t entry = longValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file, path, addSlash));
|
||||||
|
|
||||||
|
return entry ? reinterpret_cast<int64_t>
|
||||||
|
(new (t->m->heap->allocate(sizeof(ZipFile::Entry)))
|
||||||
|
ZipFile::Entry(entry)) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getNextZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
int index = arguments[2];
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
||||||
|
if (file->region) {
|
||||||
|
return reinterpret_cast<int64_t>(file->entries + index);
|
||||||
|
} else {
|
||||||
|
int64_t entry = longValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file, index));
|
||||||
|
|
||||||
|
return entry ? reinterpret_cast<int64_t>
|
||||||
|
(new (t->m->heap->allocate(sizeof(ZipFile::Entry)))
|
||||||
|
ZipFile::Entry(entry)) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
initializeZipEntryFields(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
int64_t peer; memcpy(&peer, arguments + 1, 8);
|
||||||
|
|
||||||
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
||||||
|
if (entry->start) {
|
||||||
|
PROTECT(t, this_);
|
||||||
|
|
||||||
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||||
|
|
||||||
|
unsigned nameLength = fileNameLength(entry->start);
|
||||||
|
object array = makeByteArray(t, nameLength + 1);
|
||||||
|
memcpy(&byteArrayBody(t, array, 0), fileName(entry->start), nameLength);
|
||||||
|
byteArrayBody(t, array, nameLength) = 0;
|
||||||
|
|
||||||
|
object name = t->m->classpath->makeString
|
||||||
|
(t, array, 0, byteArrayLength(t, array) - 1);
|
||||||
|
|
||||||
|
set(t, this_, cp->zipEntryNameField, name);
|
||||||
|
|
||||||
|
cast<int64_t>(this_, cp->zipEntryTimeField)
|
||||||
|
= fileTime(entry->start);
|
||||||
|
cast<int64_t>(this_, cp->zipEntryCrcField)
|
||||||
|
= fileCRC(entry->start);
|
||||||
|
cast<int64_t>(this_, cp->zipEntrySizeField)
|
||||||
|
= uncompressedSize(entry->start);
|
||||||
|
cast<int64_t>(this_, cp->zipEntryCsizeField)
|
||||||
|
= compressedSize(entry->start);
|
||||||
|
cast<int64_t>(this_, cp->zipEntryMethodField)
|
||||||
|
= compressionMethod(entry->start);
|
||||||
|
} else {
|
||||||
|
t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
this_, entry->entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getZipFileEntryMethod(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
||||||
|
if (entry->start) {
|
||||||
|
return compressionMethod(entry->start);
|
||||||
|
} else {
|
||||||
|
return intValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, entry->entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getZipFileEntryCompressedSize(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
||||||
|
if (entry->start) {
|
||||||
|
return compressedSize(entry->start);
|
||||||
|
} else {
|
||||||
|
return longValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, entry->entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getZipFileEntryUncompressedSize(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(peer);
|
||||||
|
if (entry->start) {
|
||||||
|
return uncompressedSize(entry->start);
|
||||||
|
} else {
|
||||||
|
return longValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, entry->entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
freeZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t filePeer; memcpy(&filePeer, arguments, 8);
|
||||||
|
int64_t entryPeer; memcpy(&entryPeer, arguments + 2, 8);
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(filePeer);
|
||||||
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(entryPeer);
|
||||||
|
if (file->region == 0) {
|
||||||
|
t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file, entry->entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
readZipFileEntry(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t filePeer; memcpy(&filePeer, arguments, 8);
|
||||||
|
int64_t entryPeer; memcpy(&entryPeer, arguments + 2, 8);
|
||||||
|
int64_t position; memcpy(&position, arguments + 4, 8);
|
||||||
|
object buffer = reinterpret_cast<object>(arguments[6]);
|
||||||
|
int offset = arguments[7];
|
||||||
|
int length = arguments[8];
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(filePeer);
|
||||||
|
ZipFile::Entry* entry = reinterpret_cast<ZipFile::Entry*>(entryPeer);
|
||||||
|
if (file->region) {
|
||||||
|
unsigned size = uncompressedSize(entry->start);
|
||||||
|
if (position >= size) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + length > size) {
|
||||||
|
length = size - position;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&byteArrayBody(t, buffer, offset),
|
||||||
|
fileData(file->region->start() + localHeaderOffset(entry->start))
|
||||||
|
+ position,
|
||||||
|
length);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
} else {
|
||||||
|
return intValue
|
||||||
|
(t, t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file, entry->entry, position, buffer, offset, length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getZipMessage(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
||||||
|
if (file->region) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getJarFileMetaInfEntryNames(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||||
|
|
||||||
|
int64_t peer = cast<int64_t>(this_, cp->zipFileJzfileField);
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
||||||
|
if (file->region) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
// OpenJDK's Java_java_util_jar_JarFile_getMetaInfEntryNames
|
||||||
|
// implementation expects to find a pointer to an instance of its
|
||||||
|
// jzfile structure in the ZipFile.jzfile field of the object we
|
||||||
|
// pass in. However, we can't pass this_ in, because its
|
||||||
|
// ZipFile.jzfile field points to a ZipFile instance, not a
|
||||||
|
// jzfile. So we pass in a temporary object instead which has the
|
||||||
|
// desired pointer at the same offset. We assume here that
|
||||||
|
// ZipFile.jzfile is the first field in that class and that
|
||||||
|
// Java_java_util_jar_JarFile_getMetaInfEntryNames will not look
|
||||||
|
// for any other fields in the object.
|
||||||
|
object pseudoThis = makeLong(t, file->file);
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
pseudoThis));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
closeZipFile(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
|
ZipFile* file = reinterpret_cast<ZipFile*>(peer);
|
||||||
|
if (file->region) {
|
||||||
|
file->region->dispose();
|
||||||
|
t->m->heap->free(file, sizeof(ZipFile)
|
||||||
|
+ (sizeof(ZipFile::Entry) * file->entryCount));
|
||||||
|
} else {
|
||||||
|
t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal
|
||||||
|
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||||
|
0, file->file);
|
||||||
|
|
||||||
|
t->m->heap->free(file, sizeof(ZipFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64_t JNICALL
|
int64_t JNICALL
|
||||||
getBootstrapResource(Thread* t, object, uintptr_t* arguments)
|
getBootstrapResource(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
@ -1092,6 +1534,102 @@ interceptFileOperations(Thread* t)
|
|||||||
voidPointer(closeFile));
|
voidPointer(closeFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ object zipEntryClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/util/zip/ZipEntry");
|
||||||
|
if (zipEntryClass == 0) return;
|
||||||
|
|
||||||
|
object zipEntryNameField = findFieldInClass2
|
||||||
|
(t, zipEntryClass, "name", "Ljava/lang/String;");
|
||||||
|
if (zipEntryNameField == 0) return;
|
||||||
|
|
||||||
|
cp->zipEntryNameField = fieldOffset(t, zipEntryNameField);
|
||||||
|
|
||||||
|
object zipEntryTimeField = findFieldInClass2
|
||||||
|
(t, zipEntryClass, "time", "J");
|
||||||
|
if (zipEntryTimeField == 0) return;
|
||||||
|
|
||||||
|
cp->zipEntryTimeField = fieldOffset(t, zipEntryTimeField);
|
||||||
|
|
||||||
|
object zipEntryCrcField = findFieldInClass2
|
||||||
|
(t, zipEntryClass, "crc", "J");
|
||||||
|
if (zipEntryCrcField == 0) return;
|
||||||
|
|
||||||
|
cp->zipEntryCrcField = fieldOffset(t, zipEntryCrcField);
|
||||||
|
|
||||||
|
object zipEntrySizeField = findFieldInClass2
|
||||||
|
(t, zipEntryClass, "size", "J");
|
||||||
|
if (zipEntrySizeField == 0) return;
|
||||||
|
|
||||||
|
cp->zipEntrySizeField = fieldOffset(t, zipEntrySizeField);
|
||||||
|
|
||||||
|
object zipEntryCsizeField = findFieldInClass2
|
||||||
|
(t, zipEntryClass, "csize", "J");
|
||||||
|
if (zipEntryCsizeField == 0) return;
|
||||||
|
|
||||||
|
cp->zipEntryCsizeField = fieldOffset(t, zipEntryCsizeField);
|
||||||
|
|
||||||
|
object zipEntryMethodField = findFieldInClass2
|
||||||
|
(t, zipEntryClass, "method", "I");
|
||||||
|
if (zipEntryMethodField == 0) return;
|
||||||
|
|
||||||
|
cp->zipEntryMethodField = fieldOffset(t, zipEntryMethodField);
|
||||||
|
|
||||||
|
intercept(t, zipEntryClass, "initFields", "(J)V",
|
||||||
|
voidPointer(initializeZipEntryFields));
|
||||||
|
}
|
||||||
|
|
||||||
|
{ object zipFileClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/util/zip/ZipFile");
|
||||||
|
if (zipFileClass == 0) return;
|
||||||
|
|
||||||
|
object zipFileJzfileField = findFieldInClass2
|
||||||
|
(t, zipFileClass, "jzfile", "J");
|
||||||
|
if (zipFileJzfileField == 0) return;
|
||||||
|
|
||||||
|
cp->zipFileJzfileField = fieldOffset(t, zipFileJzfileField);
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJ)J",
|
||||||
|
voidPointer(openZipFile));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getTotal", "(J)I",
|
||||||
|
voidPointer(getZipFileEntryCount));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getEntry", "(JLjava/lang/String;Z)J",
|
||||||
|
voidPointer(getZipFileEntry));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getNextEntry", "(JI)J",
|
||||||
|
voidPointer(getNextZipFileEntry));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getMethod", "(J)I",
|
||||||
|
voidPointer(getZipFileEntryMethod));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "freeEntry", "(JJ)V",
|
||||||
|
voidPointer(freeZipFileEntry));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "read", "(JJJ[BII)I",
|
||||||
|
voidPointer(readZipFileEntry));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getCSize", "(J)J",
|
||||||
|
voidPointer(getZipFileEntryCompressedSize));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getSize", "(J)J",
|
||||||
|
voidPointer(getZipFileEntryUncompressedSize));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "getZipMessage", "(J)Ljava/lang/String;",
|
||||||
|
voidPointer(getZipMessage));
|
||||||
|
|
||||||
|
intercept(t, zipFileClass, "close", "(J)V",
|
||||||
|
voidPointer(closeZipFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
{ object jarFileClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/util/jar/JarFile");
|
||||||
|
if (jarFileClass == 0) return;
|
||||||
|
|
||||||
|
intercept(t, jarFileClass, "getMetaInfEntryNames", "()[Ljava/lang/String;",
|
||||||
|
voidPointer(getJarFileMetaInfEntryNames));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
const char* const fsClassName = "java/io/WinNTFileSystem";
|
const char* const fsClassName = "java/io/WinNTFileSystem";
|
||||||
|
10
src/common.h
10
src/common.h
@ -537,6 +537,16 @@ replace(char a, char b, char* dst, const char* src)
|
|||||||
dst[i] = 0;
|
dst[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
equal(const void* a, unsigned al, const void* b, unsigned bl)
|
||||||
|
{
|
||||||
|
if (al == bl) {
|
||||||
|
return memcmp(a, b, al) == 0;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Machine;
|
class Machine;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
|
@ -41,16 +41,6 @@ copy(Allocator* allocator, const char* a)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
equal(const void* a, unsigned al, const void* b, unsigned bl)
|
|
||||||
{
|
|
||||||
if (al == bl) {
|
|
||||||
return memcmp(a, b, al) == 0;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Element {
|
class Element {
|
||||||
public:
|
public:
|
||||||
class Iterator {
|
class Iterator {
|
||||||
@ -233,9 +223,6 @@ class DataRegion: public System::Region {
|
|||||||
|
|
||||||
class JarIndex {
|
class JarIndex {
|
||||||
public:
|
public:
|
||||||
static const unsigned LocalHeaderSize = 30;
|
|
||||||
static const unsigned HeaderSize = 46;
|
|
||||||
|
|
||||||
enum CompressionMethod {
|
enum CompressionMethod {
|
||||||
Stored = 0,
|
Stored = 0,
|
||||||
Deflated = 8
|
Deflated = 8
|
||||||
@ -262,78 +249,6 @@ class JarIndex {
|
|||||||
memset(table, 0, sizeof(Node*) * capacity);
|
memset(table, 0, sizeof(Node*) * capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t get2(const uint8_t* p) {
|
|
||||||
return
|
|
||||||
(static_cast<uint16_t>(p[1]) << 8) |
|
|
||||||
(static_cast<uint16_t>(p[0]) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t get4(const uint8_t* p) {
|
|
||||||
return
|
|
||||||
(static_cast<uint32_t>(p[3]) << 24) |
|
|
||||||
(static_cast<uint32_t>(p[2]) << 16) |
|
|
||||||
(static_cast<uint32_t>(p[1]) << 8) |
|
|
||||||
(static_cast<uint32_t>(p[0]) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t signature(const uint8_t* p) {
|
|
||||||
return get4(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t compressionMethod(const uint8_t* centralHeader) {
|
|
||||||
return get2(centralHeader + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t compressedSize(const uint8_t* centralHeader) {
|
|
||||||
return get4(centralHeader + 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t uncompressedSize(const uint8_t* centralHeader) {
|
|
||||||
return get4(centralHeader + 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t fileNameLength(const uint8_t* centralHeader) {
|
|
||||||
return get2(centralHeader + 28);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t extraFieldLength(const uint8_t* centralHeader) {
|
|
||||||
return get2(centralHeader + 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t commentFieldLength(const uint8_t* centralHeader) {
|
|
||||||
return get2(centralHeader + 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t localHeaderOffset(const uint8_t* centralHeader) {
|
|
||||||
return get4(centralHeader + 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t localFileNameLength(const uint8_t* localHeader) {
|
|
||||||
return get2(localHeader + 26);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t localExtraFieldLength(const uint8_t* localHeader) {
|
|
||||||
return get2(localHeader + 28);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t centralDirectoryOffset(const uint8_t* centralHeader) {
|
|
||||||
return get4(centralHeader + 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8_t* fileName(const uint8_t* centralHeader) {
|
|
||||||
return centralHeader + 46;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8_t* fileData(const uint8_t* localHeader) {
|
|
||||||
return localHeader + LocalHeaderSize + localFileNameLength(localHeader) +
|
|
||||||
localExtraFieldLength(localHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8_t* endOfEntry(const uint8_t* p) {
|
|
||||||
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) +
|
|
||||||
commentFieldLength(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JarIndex* make(System* s, Allocator* allocator, unsigned capacity) {
|
static JarIndex* make(System* s, Allocator* allocator, unsigned capacity) {
|
||||||
return new
|
return new
|
||||||
(allocator->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
(allocator->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
||||||
@ -347,14 +262,14 @@ class JarIndex {
|
|||||||
|
|
||||||
const uint8_t* start = region->start();
|
const uint8_t* start = region->start();
|
||||||
const uint8_t* end = start + region->length();
|
const uint8_t* end = start + region->length();
|
||||||
const uint8_t* p = end - 22;
|
const uint8_t* p = end - CentralDirectorySearchStart;
|
||||||
// Find end of central directory record
|
// Find end of central directory record
|
||||||
while (p > start) {
|
while (p > start) {
|
||||||
if (signature(p) == 0x06054b50) {
|
if (signature(p) == CentralDirectorySignature) {
|
||||||
p = region->start() + centralDirectoryOffset(p);
|
p = region->start() + centralDirectoryOffset(p);
|
||||||
|
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
if (signature(p) == 0x02014b50) {
|
if (signature(p) == EntrySignature) {
|
||||||
index = index->add(hash(fileName(p), fileNameLength(p)), p);
|
index = index->add(hash(fileName(p), fileNameLength(p)), p);
|
||||||
|
|
||||||
p = endOfEntry(p);
|
p = endOfEntry(p);
|
||||||
@ -495,8 +410,8 @@ class JarElement: public Element {
|
|||||||
virtual const char* next(unsigned* size) {
|
virtual const char* next(unsigned* size) {
|
||||||
if (position < index->position) {
|
if (position < index->position) {
|
||||||
JarIndex::Node* n = index->nodes + (position++);
|
JarIndex::Node* n = index->nodes + (position++);
|
||||||
*size = JarIndex::fileNameLength(n->entry);
|
*size = fileNameLength(n->entry);
|
||||||
return reinterpret_cast<const char*>(JarIndex::fileName(n->entry));
|
return reinterpret_cast<const char*>(fileName(n->entry));
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
88
src/finder.h
88
src/finder.h
@ -17,6 +17,94 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
const unsigned LocalHeaderSize = 30;
|
||||||
|
const unsigned HeaderSize = 46;
|
||||||
|
|
||||||
|
const unsigned CentralDirectorySignature = 0x06054b50;
|
||||||
|
const unsigned EntrySignature = 0x02014b50;
|
||||||
|
|
||||||
|
const unsigned CentralDirectorySearchStart = 22;
|
||||||
|
|
||||||
|
inline uint16_t get2(const uint8_t* p) {
|
||||||
|
return
|
||||||
|
(static_cast<uint16_t>(p[1]) << 8) |
|
||||||
|
(static_cast<uint16_t>(p[0]) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t get4(const uint8_t* p) {
|
||||||
|
return
|
||||||
|
(static_cast<uint32_t>(p[3]) << 24) |
|
||||||
|
(static_cast<uint32_t>(p[2]) << 16) |
|
||||||
|
(static_cast<uint32_t>(p[1]) << 8) |
|
||||||
|
(static_cast<uint32_t>(p[0]) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t signature(const uint8_t* p) {
|
||||||
|
return get4(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t compressionMethod(const uint8_t* centralHeader) {
|
||||||
|
return get2(centralHeader + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t fileTime(const uint8_t* centralHeader) {
|
||||||
|
return get4(centralHeader + 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t fileCRC(const uint8_t* centralHeader) {
|
||||||
|
return get4(centralHeader + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t compressedSize(const uint8_t* centralHeader) {
|
||||||
|
return get4(centralHeader + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t uncompressedSize(const uint8_t* centralHeader) {
|
||||||
|
return get4(centralHeader + 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t fileNameLength(const uint8_t* centralHeader) {
|
||||||
|
return get2(centralHeader + 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t extraFieldLength(const uint8_t* centralHeader) {
|
||||||
|
return get2(centralHeader + 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t commentFieldLength(const uint8_t* centralHeader) {
|
||||||
|
return get2(centralHeader + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t localHeaderOffset(const uint8_t* centralHeader) {
|
||||||
|
return get4(centralHeader + 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t localFileNameLength(const uint8_t* localHeader) {
|
||||||
|
return get2(localHeader + 26);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t localExtraFieldLength(const uint8_t* localHeader) {
|
||||||
|
return get2(localHeader + 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader) {
|
||||||
|
return get4(centralHeader + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const uint8_t* fileName(const uint8_t* centralHeader) {
|
||||||
|
return centralHeader + 46;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const uint8_t* fileData(const uint8_t* localHeader) {
|
||||||
|
return localHeader + LocalHeaderSize + localFileNameLength(localHeader) +
|
||||||
|
localExtraFieldLength(localHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const uint8_t* endOfEntry(const uint8_t* p) {
|
||||||
|
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) +
|
||||||
|
commentFieldLength(p);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
||||||
unsigned* length)
|
unsigned* length)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user