-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 36348957 - [36345154->24.03] Change our usage of ASM to bypass th…
…e class version check (merge main -> ce/main @ 107180) [git-p4: depot-paths = "//dev/coherence-ce/main/": change = 107185]
- Loading branch information
Showing
8 changed files
with
348 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
prj/coherence-core/src/main/java/com/tangosol/internal/asm/ClassReaderInternal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright (c) 2024, Oracle and/or its affiliates. | ||
* | ||
* Licensed under the Universal Permissive License v 1.0 as shown at | ||
* https://oss.oracle.com/licenses/upl. | ||
*/ | ||
package com.tangosol.internal.asm; | ||
|
||
import com.tangosol.util.asm.BaseClassReaderInternal; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
||
import org.objectweb.asm.ClassReader; | ||
import org.objectweb.asm.ClassVisitor; | ||
|
||
/** | ||
* This class wraps ASM's ClassReader allowing Coherence to bypass the class | ||
* version checks performed by ASM when reading a class. | ||
* | ||
* @since 15.1.1.0 | ||
*/ | ||
/* | ||
* Internal NOTE: This class is also duplicated in coherence-json and | ||
* coherence-rest. This is done because each module shades | ||
* ASM within a unique package into the produced JAR and | ||
* thus having to create copes to deal with those package | ||
* differences. | ||
*/ | ||
public class ClassReaderInternal | ||
extends BaseClassReaderInternal<ClassReader, ClassVisitor> | ||
{ | ||
// ----- constructors --------------------------------------------------- | ||
|
||
/** | ||
* @see BaseClassReaderInternal#BaseClassReaderInternal(InputStream) | ||
*/ | ||
public ClassReaderInternal(InputStream streamIn) throws IOException | ||
{ | ||
super(streamIn); | ||
} | ||
|
||
/** | ||
* @see BaseClassReaderInternal#BaseClassReaderInternal(byte[]) | ||
*/ | ||
public ClassReaderInternal(byte[] abBytes) | ||
{ | ||
super(abBytes); | ||
} | ||
|
||
// ----- BaseClassReaderInternal methods -------------------------------- | ||
|
||
@Override | ||
protected ClassReader createReader(byte[] abBytes) | ||
{ | ||
return new ClassReader(abBytes); | ||
} | ||
|
||
@Override | ||
protected void accept(ClassReader classReader, ClassVisitor classVisitor, int nParsingOptions) | ||
{ | ||
classReader.accept(classVisitor, nParsingOptions); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
prj/coherence-core/src/main/java/com/tangosol/util/asm/BaseClassReaderInternal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* | ||
* Copyright (c) 2024, Oracle and/or its affiliates. | ||
* | ||
* Licensed under the Universal Permissive License v 1.0 as shown at | ||
* https://oss.oracle.com/licenses/upl. | ||
*/ | ||
package com.tangosol.util.asm; | ||
|
||
import com.oracle.coherence.common.base.Logger; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
||
/** | ||
* Base class for internal wrappers of ASM's ClassReader. | ||
* | ||
* @param <RT> the ClassReader type | ||
* @param <CVT> the ClassVisitor type | ||
* | ||
* @since 15.1.1.0 | ||
*/ | ||
public abstract class BaseClassReaderInternal<RT, CVT> | ||
{ | ||
// ----- constructors --------------------------------------------------- | ||
|
||
/** | ||
* @see org.objectweb.asm.ClassReader#ClassReader(InputStream) | ||
*/ | ||
public BaseClassReaderInternal(InputStream streamIn) | ||
throws IOException | ||
{ | ||
this(streamIn.readAllBytes()); | ||
} | ||
|
||
/** | ||
* @see org.objectweb.asm.ClassReader#ClassReader(byte[]) | ||
*/ | ||
public BaseClassReaderInternal(byte[] abBytes) | ||
{ | ||
m_abBytes = abBytes; | ||
} | ||
|
||
// ----- abstract methods ----------------------------------------------- | ||
|
||
/** | ||
* Create the module-specific ClassReader. | ||
* | ||
* @param abBytes the class bytes | ||
* | ||
* @return the module-specific ClassReader | ||
*/ | ||
protected abstract RT createReader(byte[] abBytes); | ||
|
||
/** | ||
* Perform the accept operation on the module-specific ClassReader | ||
* | ||
* @param classReader the module-specific ClassReader | ||
* @param classVisitor the module-specific ClassVisitor | ||
* @param nParsingOptions the parsing options | ||
*/ | ||
protected abstract void accept(RT classReader, CVT classVisitor, int nParsingOptions); | ||
|
||
// ----- api methods ---------------------------------------------------- | ||
|
||
/** | ||
* Makes the given visitor visit the Java Virtual Machine's class file | ||
* structure passed to the constructor of this {@code ClassReader}. | ||
* | ||
* @param classVisitor the visitor that must visit this class | ||
* @param nParsingOptions the options to use to parse this class | ||
* | ||
* @see org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, int) | ||
*/ | ||
@SuppressWarnings("DuplicatedCode") | ||
public void accept(CVT classVisitor, int nParsingOptions) | ||
{ | ||
byte[] abBytes = m_abBytes; | ||
int nOriginalVersion = getMajorVersion(abBytes); | ||
boolean fRevertVersion = false; | ||
|
||
if (nOriginalVersion > MAX_MAJOR_VERSION) | ||
{ | ||
// temporarily downgrade version to bypass check in ASM | ||
setMajorVersion(MAX_MAJOR_VERSION, abBytes); | ||
|
||
fRevertVersion = true; | ||
|
||
Logger.warn(() -> String.format("Unsupported class file major version " + nOriginalVersion)); | ||
} | ||
|
||
RT classReader = createReader(abBytes); | ||
|
||
if (fRevertVersion) | ||
{ | ||
// set version back | ||
setMajorVersion(nOriginalVersion, abBytes); | ||
} | ||
|
||
accept(classReader, classVisitor, nParsingOptions); | ||
} | ||
|
||
// ----- helper methods ------------------------------------------------- | ||
|
||
/** | ||
* Sets the major version number in given class bytes. | ||
* | ||
* @param nMajorVersion major version of bytecode to set | ||
* @param abBytes class bytes | ||
* | ||
* @see #getMajorVersion(byte[]) | ||
*/ | ||
protected static void setMajorVersion(final int nMajorVersion, final byte[] abBytes) | ||
{ | ||
abBytes[6] = (byte) (nMajorVersion >>> 8); | ||
abBytes[7] = (byte) nMajorVersion; | ||
} | ||
|
||
/** | ||
* Gets major version number from the given class bytes. | ||
* | ||
* @param abBytes class bytes | ||
* | ||
* @return the major version of bytecode | ||
*/ | ||
protected static int getMajorVersion(final byte[] abBytes) | ||
{ | ||
return ((abBytes[6] & 0xFF) << 8) | (abBytes[7] & 0xFF); | ||
} | ||
|
||
// ----- constants ------------------------------------------------------ | ||
|
||
/** | ||
* The max major version supported by the shaded ASM. | ||
*/ | ||
/* | ||
* Implementation Note: This doesn't reference the constant to avoid | ||
* strange issues with moditect | ||
*/ | ||
private static final int MAX_MAJOR_VERSION = 66; // Opcodes.V22 | ||
|
||
// ----- data members --------------------------------------------------- | ||
|
||
/** | ||
* The class bytes. | ||
*/ | ||
protected byte[] m_abBytes; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.