Skip to content

Commit

Permalink
Bug 36348957 - [36345154->24.03] Change our usage of ASM to bypass th…
Browse files Browse the repository at this point in the history
…e class version check (merge main -> ce/main @ 107180)

[git-p4: depot-paths = "//dev/coherence-ce/main/": change = 107185]
  • Loading branch information
rlubke committed Feb 28, 2024
1 parent 035f8c2 commit a213482
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* Copyright (c) 2020 Oracle and/or its affiliates.
* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
* https://oss.oracle.com/licenses/upl.
*/

package com.oracle.coherence.common.schema;
Expand All @@ -13,6 +13,8 @@
import com.oracle.coherence.common.schema.util.NameTransformer;
import com.oracle.coherence.common.schema.util.NameTransformerChain;

import com.tangosol.internal.asm.ClassReaderInternal;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
Expand All @@ -29,7 +31,6 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
Expand Down Expand Up @@ -458,8 +459,8 @@ else if (isPass(1))
protected void populateSchema(Schema schema, InputStream in)
throws IOException
{
ClassReader reader = new ClassReader(in);
ClassNode source = new ClassNode();
ClassReaderInternal reader = new ClassReaderInternal(in);
ClassNode source = new ClassNode();
reader.accept(source, 0);

if (m_typeFilter.test(source))
Expand Down
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);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
* https://oss.oracle.com/licenses/upl.
*/
package com.tangosol.internal.util.invoke;

import com.tangosol.dev.assembler.Field;

import com.tangosol.internal.asm.ClassReaderInternal;

import java.lang.invoke.MethodHandleInfo;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
Expand Down Expand Up @@ -55,7 +56,7 @@ public static byte[] createRemoteClass(String sClassNameOld, String sClassNameNe
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassRemapper remapper = new ClassRemapper(writer, new SimpleRemapper(sClassNameOld, sClassNameNew));

new ClassReader(abClass).accept(remapper, ClassReader.EXPAND_FRAMES);
new ClassReaderInternal(abClass).accept(remapper, org.objectweb.asm.ClassReader.EXPAND_FRAMES);

return writer.toByteArray();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
* https://oss.oracle.com/licenses/upl.
*/
package com.tangosol.internal.util.invoke.lambda;

import com.tangosol.internal.asm.ClassReaderInternal;

import com.tangosol.internal.util.invoke.ClassIdentity;

import com.tangosol.internal.util.invoke.Lambdas;
import com.tangosol.internal.util.invoke.RemotableClassGenerator;

import com.tangosol.internal.util.invoke.Remotable;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
Expand Down Expand Up @@ -319,8 +321,8 @@ private static String copyLambdaMethod(ClassWriter cw, SerializedLambda lambdaMe

try (InputStream is = loader.getResourceAsStream(sImplClassName + ".class"))
{
ClassReader reader = new ClassReader(is);
ClassNode implClass = new ClassNode();
ClassReaderInternal reader = new ClassReaderInternal(is);
ClassNode implClass = new ClassNode();

reader.accept(implClass, 0);

Expand Down
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;
}
9 changes: 9 additions & 0 deletions prj/coherence-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,16 @@

<!-- library dependency versions -->
<asciidoctor.diagram.version>2.0.2</asciidoctor.diagram.version>

<!--
When changing asm.version, also change the value of the constant
defined in com.tangosol.util.asm.BaseClassReaderInternal#MAX_MAJOR_VERSION
to have the same value as the latest class opcode defined in
org.objectweb.asm.Opcodes. As of ASM 9.6, this is Opcodes.V22 whose
value is 66.
-->
<asm.version>9.6</asm.version>

<bdb.version>6.2.31</bdb.version>
<bnd.version>6.4.0</bnd.version>
<caffeine.version>3.1.1</caffeine.version>
Expand Down
Loading

0 comments on commit a213482

Please sign in to comment.