From 6ed3b0c826826d80c66545c642b4272622f35ff196e5fcd20acd8433038ed694 Mon Sep 17 00:00:00 2001 From: David Anes Date: Thu, 10 Nov 2022 13:54:45 +0000 Subject: [PATCH] Accepting request 1035053 from home:pmonrealgonzalez:branches:Java:packages - Security fix: [bsc#1205125, CVE-2022-42920] * Apache Commons BCEL prior to 6.6.0 allows producing arbitrary bytecode via out-of-bounds writing * Add bcel-CVE-2022-42920.patch OBS-URL: https://build.opensuse.org/request/show/1035053 OBS-URL: https://build.opensuse.org/package/show/Java:packages/bcel?expand=0&rev=42 --- bcel-CVE-2022-42920.patch | 166 ++++++++++++++++++++++++++++++++++++++ bcel.changes | 8 ++ bcel.spec | 13 ++- 3 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 bcel-CVE-2022-42920.patch diff --git a/bcel-CVE-2022-42920.patch b/bcel-CVE-2022-42920.patch new file mode 100644 index 0000000..02bb0a4 --- /dev/null +++ b/bcel-CVE-2022-42920.patch @@ -0,0 +1,166 @@ +From f3267cbcc900f80851d561bdd16b239d936947f5 Mon Sep 17 00:00:00 2001 +From: Richard Atkins +Date: Wed, 21 Sep 2022 23:18:58 +1000 +Subject: [PATCH] BCEL-363 Enforce MAX_CP_ENTRIES in ConstantPoolGen and + ConstantPool.dump (#147) + +* BCEL-363 Enforce MAX_CP_ENTRIES in ConstantPoolGen and ConstantPool.dump + +* BCEL-363 Add test coverage for enforced size limit + +* BCEL-363 Throw IllegalStateException instead of RuntimeException + +* BCEL-363 Use final +--- + .../org/apache/bcel/classfile/ConstantPool.java | 11 +++++++++-- + .../org/apache/bcel/generic/ConstantPoolGen.java | 11 ++++++++++- + .../bcel/classfile/ConstantPoolTestCase.java | 15 +++++++++++++++ + 3 files changed, 34 insertions(+), 3 deletions(-) + +Index: bcel/src/java/org/apache/bcel/classfile/ConstantPool.java +=================================================================== +--- bcel.orig/src/java/org/apache/bcel/classfile/ConstantPool.java ++++ bcel/src/java/org/apache/bcel/classfile/ConstantPool.java +@@ -198,10 +198,17 @@ public class ConstantPool implements Clo + * @throws IOException + */ + public void dump( DataOutputStream file ) throws IOException { +- file.writeShort(constant_pool_count); +- for (int i = 1; i < constant_pool_count; i++) { +- if (constant_pool[i] != null) { +- constant_pool[i].dump(file); ++ /* ++ * Constants over the size of the constant pool shall not be written out. ++ * This is a redundant measure as the ConstantPoolGen should have already ++ * reported an error back in the situation. ++ */ ++ final int size = Math.min(constant_pool.length, Constants.MAX_CP_ENTRIES); ++ ++ file.writeShort(size); ++ for (int i = 1; i < size; i++) { ++ if (constant_pool[i] != null) { ++ constant_pool[i].dump(file); + } + } + } +Index: bcel/src/java/org/apache/bcel/generic/ConstantPoolGen.java +=================================================================== +--- bcel.orig/src/java/org/apache/bcel/generic/ConstantPoolGen.java ++++ bcel/src/java/org/apache/bcel/generic/ConstantPoolGen.java +@@ -50,14 +50,16 @@ import org.apache.bcel.classfile.Constan + */ + public class ConstantPoolGen implements java.io.Serializable { + +- protected int size = 1024; // Inital size, sufficient in most cases +- protected Constant[] constants = new Constant[size]; +- protected int index = 1; // First entry (0) used by JVM ++ private static final int DEFAULT_BUFFER_SIZE = 256; + private static final String METHODREF_DELIM = ":"; + private static final String IMETHODREF_DELIM = "#"; + private static final String FIELDREF_DELIM = "&"; + private static final String NAT_DELIM = "%"; + ++ protected int size = DEFAULT_BUFFER_SIZE; ++ protected Constant[] constants = new Constant[size]; ++ protected int index = 1; // First entry (0) used by JVM ++ + private static class Index implements java.io.Serializable { + + int index; +@@ -75,6 +76,8 @@ public class ConstantPoolGen implements + * @param cs array of given constants, new ones will be appended + */ + public ConstantPoolGen(Constant[] cs) { ++ ++ size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), Constants.MAX_CP_ENTRIES + 1); + if (cs.length > size) { + size = cs.length; + constants = new Constant[size]; +@@ -156,9 +159,18 @@ public class ConstantPoolGen implements + /** Resize internal array of constants. + */ + protected void adjustSize() { ++ // 3 extra spaces are needed as some entries may take 3 slots ++ if (index + 3 >= Constants.MAX_CP_ENTRIES + 1) { ++ throw new IllegalStateException("The number of constants " + (index + 3) ++ + " is over the size of the constant pool: " ++ + Constants.MAX_CP_ENTRIES); ++ } ++ + if (index + 3 >= size) { + Constant[] cs = constants; + size *= 2; ++ // the constant array shall not exceed the size of the constant pool ++ size = Math.min(size, Constants.MAX_CP_ENTRIES + 1); + constants = new Constant[size]; + System.arraycopy(cs, 0, constants, 0, index); + } +Index: bcel/src/test/java/org/apache/bcel/ConstantPoolTestCase.java +=================================================================== +--- /dev/null ++++ bcel/src/test/java/org/apache/bcel/ConstantPoolTestCase.java +@@ -0,0 +1,64 @@ ++/* ++ * 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.bcel.classfile; ++ ++import static org.junit.jupiter.api.Assertions.assertNotNull; ++import static org.junit.jupiter.api.Assertions.assertThrows; ++ ++import org.apache.bcel.AbstractTestCase; ++import org.apache.bcel.Const; ++import org.apache.bcel.generic.ConstantPoolGen; ++import org.apache.bcel.generic.InstructionHandle; ++import org.apache.bcel.generic.InstructionList; ++import org.apache.bcel.generic.MethodGen; ++import org.junit.jupiter.api.Test; ++public class ConstantPoolTestCase extends AbstractTestCase { ++ private InstructionHandle[] getInstructionHandles(final JavaClass clazz, final ConstantPoolGen cp, final Method method) { ++ final MethodGen methodGen = new MethodGen(method, clazz.getClassName(), cp); ++ final InstructionList instructionList = methodGen.getInstructionList(); ++ return instructionList.getInstructionHandles(); ++ } ++ @Test ++ public void testConstantToString() throws ClassNotFoundException { ++ final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME + ".data.SimpleClassWithDefaultConstructor"); ++ final ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool()); ++ final Method[] methods = clazz.getMethods(); ++ for (final Method method : methods) { ++ if (method.getName().equals("")) { ++ for (final InstructionHandle instructionHandle : getInstructionHandles(clazz, cp, method)) { ++ final String string = instructionHandle.getInstruction().toString(cp.getConstantPool()); ++ assertNotNull(string); ++ // TODO Need real assertions. ++ // System.out.println(string); ++ } ++ } ++ } ++ } ++ ++ @Test ++ public void testTooManyConstants() throws ClassNotFoundException { ++ final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME + ".data.SimpleClassWithDefaultConstructor"); ++ final ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool()); ++ ++ int i = cp.getSize(); ++ while (i < Constants.MAX_CP_ENTRIES - 1) { ++ cp.addLong(i); ++ i = cp.getSize(); // i += 2 ++ } ++ assertThrows(IllegalStateException.class, () -> cp.addLong(0)); ++ } ++} diff --git a/bcel.changes b/bcel.changes index fed0a3c..5014c83 100644 --- a/bcel.changes +++ b/bcel.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Thu Nov 10 11:02:08 UTC 2022 - Pedro Monreal + +- Security fix: [bsc#1205125, CVE-2022-42920] + * Apache Commons BCEL prior to 6.6.0 allows producing + arbitrary bytecode via out-of-bounds writing + * Add bcel-CVE-2022-42920.patch + ------------------------------------------------------------------- Fri Feb 1 14:10:42 UTC 2019 - Fridrich Strba diff --git a/bcel.spec b/bcel.spec index 2e89ab7..4387703 100644 --- a/bcel.spec +++ b/bcel.spec @@ -1,7 +1,7 @@ # # spec file for package bcel # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -28,6 +28,8 @@ Source1: http://archive.apache.org/dist/commons/bcel/source/%{name}-%{ver Source2: http://repo.maven.apache.org/maven2/org/apache/%{name}/%{name}/%{version}/%{name}-%{version}.pom Source3: bcel.keyring Patch0: bcel-5.2-encoding.patch +#PATCH-FIX-UPSTREAM bsc#1205125 CVE-2022-42920 Out-of-bounds writing issue +Patch1: bcel-CVE-2022-42920.patch BuildRequires: ant BuildRequires: java-devel >= 1.8 BuildRequires: javapackages-local @@ -59,8 +61,7 @@ much better information about what is wrong with your code than the standard JVM message. %prep -%setup -q -%patch0 -p1 +%autosetup -p1 # remove all binary libs find . -name "*.jar" -exec rm -f {} \; # very broken build @@ -73,11 +74,7 @@ export OPT_JAR_LIST="ant/ant-nodeps" ant \ -Dant.build.javac.target=8 -Dant.build.javac.source=8 \ -Dbuild.dest=./build -Dbuild.dir=./build -Dname=%{name} \ - compile -ant \ - -Dant.build.javac.target=8 -Dant.build.javac.source=8 \ - -Dbuild.dest=./build -Dbuild.dir=./build -Dname=%{name} \ - jar + compile jar %install # jars