mirror of
https://github.com/apache/openjpa.git
synced 2025-03-06 08:29:08 +00:00
OPENJPA-2917 fix off-by-1 issue on java stack
long parameters take up 2 byte on the call stack
This commit is contained in:
parent
33372a718e
commit
815ef2349f
@ -64,8 +64,7 @@ import org.apache.xbean.asm9.tree.VarInsnNode;
|
|||||||
*/
|
*/
|
||||||
public class PCDataGenerator extends DynamicStorageGenerator {
|
public class PCDataGenerator extends DynamicStorageGenerator {
|
||||||
|
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage(PCDataGenerator.class);
|
||||||
(PCDataGenerator.class);
|
|
||||||
|
|
||||||
protected static final String POSTFIX = "$openjpapcdata";
|
protected static final String POSTFIX = "$openjpapcdata";
|
||||||
|
|
||||||
@ -89,8 +88,10 @@ public class PCDataGenerator extends DynamicStorageGenerator {
|
|||||||
* Return a {@link PCData} instance for the given oid and metadata.
|
* Return a {@link PCData} instance for the given oid and metadata.
|
||||||
*/
|
*/
|
||||||
public PCData generatePCData(Object oid, ClassMetaData meta) {
|
public PCData generatePCData(Object oid, ClassMetaData meta) {
|
||||||
if (meta == null)
|
if (meta == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> type = meta.getDescribedType();
|
Class<?> type = meta.getDescribedType();
|
||||||
DynamicStorage storage = _generated.get(type);
|
DynamicStorage storage = _generated.get(type);
|
||||||
if (storage == null) {
|
if (storage == null) {
|
||||||
@ -110,13 +111,15 @@ public class PCDataGenerator extends DynamicStorageGenerator {
|
|||||||
* Actually generate the factory instance.
|
* Actually generate the factory instance.
|
||||||
*/
|
*/
|
||||||
private DynamicStorage generateStorage(ClassMetaData meta) {
|
private DynamicStorage generateStorage(ClassMetaData meta) {
|
||||||
if (_log.isTraceEnabled())
|
if (_log.isTraceEnabled()) {
|
||||||
_log.trace(_loc.get("pcdata-generate", meta));
|
_log.trace(_loc.get("pcdata-generate", meta));
|
||||||
|
}
|
||||||
|
|
||||||
FieldMetaData[] fields = meta.getFields();
|
FieldMetaData[] fields = meta.getFields();
|
||||||
int[] types = new int[fields.length];
|
int[] types = new int[fields.length];
|
||||||
for (int i = 0; i < types.length; i++)
|
for (int i = 0; i < types.length; i++) {
|
||||||
types[i] = replaceType(fields[i]);
|
types[i] = replaceType(fields[i]);
|
||||||
|
}
|
||||||
return generateStorage(types, meta);
|
return generateStorage(types, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +131,10 @@ public class PCDataGenerator extends DynamicStorageGenerator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getCreateFieldMethods(int typeCode) {
|
protected int getCreateFieldMethods(int typeCode) {
|
||||||
if (typeCode >= JavaTypes.OBJECT)
|
if (typeCode >= JavaTypes.OBJECT) {
|
||||||
return POLICY_SILENT;
|
return POLICY_SILENT;
|
||||||
|
}
|
||||||
|
|
||||||
// don't bother creating set/get<Primitive> methods
|
// don't bother creating set/get<Primitive> methods
|
||||||
return POLICY_EMPTY;
|
return POLICY_EMPTY;
|
||||||
}
|
}
|
||||||
|
@ -1215,6 +1215,7 @@ public class PCEnhancer {
|
|||||||
addGetManagedValueCode(classNode, insns, fmd, true);
|
addGetManagedValueCode(classNode, insns, fmd, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// the method parameter
|
||||||
insns.add(new VarInsnNode(AsmHelper.getLoadInsn(type), param + 1));
|
insns.add(new VarInsnNode(AsmHelper.getLoadInsn(type), param + 1));
|
||||||
}
|
}
|
||||||
insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
|
insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
|
||||||
@ -4195,7 +4196,7 @@ public class PCEnhancer {
|
|||||||
null, null);
|
null, null);
|
||||||
classNode.methods.add(newMethod);
|
classNode.methods.add(newMethod);
|
||||||
final InsnList instructions = newMethod.instructions;
|
final InsnList instructions = newMethod.instructions;
|
||||||
int nextFreeVarPos = 2;
|
int nextFreeVarPos = 1 + Type.getType(propType).getSize();
|
||||||
|
|
||||||
setVisibilityToSuperMethod(newMethod);
|
setVisibilityToSuperMethod(newMethod);
|
||||||
|
|
||||||
|
@ -26,12 +26,14 @@ import java.util.List;
|
|||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||||
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
|
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
|
||||||
import org.apache.openjpa.lib.conf.Configurations;
|
import org.apache.openjpa.lib.conf.Configurations;
|
||||||
|
import org.apache.openjpa.util.asm.AsmHelper;
|
||||||
import org.apache.openjpa.util.asm.BytecodeWriter;
|
import org.apache.openjpa.util.asm.BytecodeWriter;
|
||||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||||
import org.apache.openjpa.lib.util.Options;
|
import org.apache.openjpa.lib.util.Options;
|
||||||
import org.apache.openjpa.meta.MetaDataRepository;
|
import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
import org.apache.openjpa.persistence.test.AbstractCachedEMFTestCase;
|
import org.apache.openjpa.persistence.test.AbstractCachedEMFTestCase;
|
||||||
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementClassLoader;
|
||||||
import org.apache.openjpa.util.asm.EnhancementProject;
|
import org.apache.openjpa.util.asm.EnhancementProject;
|
||||||
import org.apache.xbean.asm9.Type;
|
import org.apache.xbean.asm9.Type;
|
||||||
|
|
||||||
@ -52,10 +54,23 @@ public class TestEnhancementWithMultiplePUs
|
|||||||
ClassNodeTracker bc = assertNotPC(loader, project, className);
|
ClassNodeTracker bc = assertNotPC(loader, project, className);
|
||||||
|
|
||||||
PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
|
PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
|
||||||
|
enhancer.setCreateSubclass(true);
|
||||||
|
|
||||||
assertEquals(PCEnhancer.ENHANCE_PC, enhancer.run());
|
assertEquals(PCEnhancer.ENHANCE_PC, enhancer.run());
|
||||||
|
|
||||||
assertTrue(enhancer.getPCBytecode().getClassNode().interfaces.contains(Type.getInternalName(PersistenceCapable.class)));
|
assertTrue(enhancer.getPCBytecode().getClassNode().interfaces.contains(Type.getInternalName(PersistenceCapable.class)));
|
||||||
|
|
||||||
|
// load the Class<?> for real.
|
||||||
|
EnhancementProject finalProject = new EnhancementProject();
|
||||||
|
EnhancementClassLoader finalLoader = new EnhancementClassLoader(finalProject, this.getClass().getClassLoader());
|
||||||
|
final byte[] classBytes2 = AsmHelper.toByteArray(enhancer.getPCBytecode());
|
||||||
|
|
||||||
|
// this is just to make the ClassLoader aware of the bytecode for the enhanced class
|
||||||
|
finalProject.loadClass(classBytes2, finalLoader);
|
||||||
|
|
||||||
|
String pcClassName = enhancer.getPCBytecode().getClassNode().name.replace("/", ".");
|
||||||
|
final Class<?> implClass = Class.forName(pcClassName, true, finalLoader);
|
||||||
|
assertNotNull(implClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassNodeTracker assertNotPC(ClassLoader loader, EnhancementProject project, String className) {
|
private ClassNodeTracker assertNotPC(ClassLoader loader, EnhancementProject project, String className) {
|
||||||
|
@ -20,9 +20,48 @@ package org.apache.openjpa.enhance;
|
|||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.IdClass;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
@IdClass(UnenhancedBootstrapInstanceId.class)
|
||||||
public class UnenhancedBootstrapInstance {
|
public class UnenhancedBootstrapInstance {
|
||||||
|
private long billNumber;
|
||||||
|
private long billVersion;
|
||||||
|
private long billRevision;
|
||||||
|
private String billDescription;
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
private int id;
|
public long getBillNumber() {
|
||||||
|
return billNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillNumber(final long number) {
|
||||||
|
billNumber = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public long getBillVersion() {
|
||||||
|
return billVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillVersion(final long version) {
|
||||||
|
billVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public long getBillRevision() {
|
||||||
|
return billRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillRevision(final long revision) {
|
||||||
|
billRevision = revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBillDescription() {
|
||||||
|
return billDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillDescription(final String description) {
|
||||||
|
billDescription = description;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.openjpa.enhance;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UnenhancedBootstrapInstanceId implements Serializable {
|
||||||
|
private long billNumber;
|
||||||
|
private long billVersion;
|
||||||
|
private long billRevision;
|
||||||
|
|
||||||
|
public UnenhancedBootstrapInstanceId() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnenhancedBootstrapInstanceId(final long number, final long version, final long revision) {
|
||||||
|
this.billNumber = number;
|
||||||
|
this.billVersion = version;
|
||||||
|
this.billRevision = revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getBillNumber() {
|
||||||
|
return this.billNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillNumber(final long number) {
|
||||||
|
this.billNumber = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getBillVersion() {
|
||||||
|
return this.billVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillVersion(final long version) {
|
||||||
|
this.billVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getBillRevision() {
|
||||||
|
return this.billRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBillRevision(final long revision) {
|
||||||
|
this.billRevision = revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == this)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!(obj instanceof UnenhancedBootstrapInstanceId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
final UnenhancedBootstrapInstanceId pk = (UnenhancedBootstrapInstanceId) obj;
|
||||||
|
|
||||||
|
if (billNumber != pk.billNumber)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (billVersion != pk.billVersion)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (billRevision != pk.billRevision)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return (billNumber + "." + billVersion + "." + billRevision).hashCode();
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,8 @@ public class UnenhancedFieldAccess
|
|||||||
@Version public int version;
|
@Version public int version;
|
||||||
protected String stringField = "foo";
|
protected String stringField = "foo";
|
||||||
|
|
||||||
|
private long longVal;
|
||||||
|
|
||||||
@Basic(fetch = FetchType.LAZY)
|
@Basic(fetch = FetchType.LAZY)
|
||||||
private String lazyField = "lazy";
|
private String lazyField = "lazy";
|
||||||
|
|
||||||
@ -65,6 +67,15 @@ public class UnenhancedFieldAccess
|
|||||||
return lazyField;
|
return lazyField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getLongVal() {
|
||||||
|
return longVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongVal(long longVal) {
|
||||||
|
this.longVal = longVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (o == this)
|
if (o == this)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user