mirror of
https://github.com/corda/corda.git
synced 2025-01-19 03:06:36 +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
|
||||
classpath-jar-dep = $(openjdk-jar-dep)
|
||||
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)
|
||||
javahome-files += lib/tzmappings
|
||||
endif
|
||||
@ -905,5 +907,6 @@ $(openjdk-jar-dep):
|
||||
$(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/jce.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/ext/sunjce_provider.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/resources.jar")")
|
||||
@touch $(@)
|
||||
|
@ -224,6 +224,9 @@ class MyClasspath : public Classpath {
|
||||
sb.append("/lib/jce.jar");
|
||||
sb.append(s->pathSeparator());
|
||||
sb.append(javaHome);
|
||||
sb.append("/lib/ext/sunjce_provider.jar");
|
||||
sb.append(s->pathSeparator());
|
||||
sb.append(javaHome);
|
||||
sb.append("/lib/resources.jar");
|
||||
sb.append('\0');
|
||||
|
||||
@ -400,6 +403,13 @@ class MyClasspath : public Classpath {
|
||||
unsigned filePathField;
|
||||
unsigned fileDescriptorFdField;
|
||||
unsigned fileInputStreamFdField;
|
||||
unsigned zipFileJzfileField;
|
||||
unsigned zipEntryNameField;
|
||||
unsigned zipEntryTimeField;
|
||||
unsigned zipEntryCrcField;
|
||||
unsigned zipEntrySizeField;
|
||||
unsigned zipEntryCsizeField;
|
||||
unsigned zipEntryMethodField;
|
||||
bool ranNetOnLoad;
|
||||
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
|
||||
getBootstrapResource(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
@ -1092,6 +1534,102 @@ interceptFileOperations(Thread* t)
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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 Thread;
|
||||
|
||||
|
@ -41,16 +41,6 @@ copy(Allocator* allocator, const char* a)
|
||||
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 {
|
||||
public:
|
||||
class Iterator {
|
||||
@ -233,9 +223,6 @@ class DataRegion: public System::Region {
|
||||
|
||||
class JarIndex {
|
||||
public:
|
||||
static const unsigned LocalHeaderSize = 30;
|
||||
static const unsigned HeaderSize = 46;
|
||||
|
||||
enum CompressionMethod {
|
||||
Stored = 0,
|
||||
Deflated = 8
|
||||
@ -262,78 +249,6 @@ class JarIndex {
|
||||
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) {
|
||||
return new
|
||||
(allocator->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
||||
@ -347,14 +262,14 @@ class JarIndex {
|
||||
|
||||
const uint8_t* start = region->start();
|
||||
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
|
||||
while (p > start) {
|
||||
if (signature(p) == 0x06054b50) {
|
||||
if (signature(p) == CentralDirectorySignature) {
|
||||
p = region->start() + centralDirectoryOffset(p);
|
||||
|
||||
while (p < end) {
|
||||
if (signature(p) == 0x02014b50) {
|
||||
if (signature(p) == EntrySignature) {
|
||||
index = index->add(hash(fileName(p), fileNameLength(p)), p);
|
||||
|
||||
p = endOfEntry(p);
|
||||
@ -495,8 +410,8 @@ class JarElement: public Element {
|
||||
virtual const char* next(unsigned* size) {
|
||||
if (position < index->position) {
|
||||
JarIndex::Node* n = index->nodes + (position++);
|
||||
*size = JarIndex::fileNameLength(n->entry);
|
||||
return reinterpret_cast<const char*>(JarIndex::fileName(n->entry));
|
||||
*size = fileNameLength(n->entry);
|
||||
return reinterpret_cast<const char*>(fileName(n->entry));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
88
src/finder.h
88
src/finder.h
@ -17,6 +17,94 @@
|
||||
|
||||
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
|
||||
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
||||
unsigned* length)
|
||||
|
Loading…
Reference in New Issue
Block a user