This is an automated email from the ASF dual-hosted git repository.
thomasrebele pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new a3969f1ef8 [CALCITE-7649] Add bytecode verification check using ASM in
the gradle build
a3969f1ef8 is described below
commit a3969f1ef8d267bf8b66a8b2601ffd41aebc7064
Author: Stamatis Zampetakis <[email protected]>
AuthorDate: Fri May 3 00:23:03 2024 +0200
[CALCITE-7649] Add bytecode verification check using ASM in the gradle build
---
build.gradle.kts | 11 +++++
buildSrc/gradle.properties | 3 ++
buildSrc/settings.gradle.kts | 1 +
.../subprojects/asmchecker/asmchecker.gradle.kts | 34 ++++++++++++++
.../buildtools/asmchecker/AsmCheckerPlugin.kt | 26 +++++++++++
.../buildtools/asmchecker/AsmCheckerTask.kt | 53 ++++++++++++++++++++++
gradle.properties | 1 +
7 files changed, 129 insertions(+)
diff --git a/build.gradle.kts b/build.gradle.kts
index 08cd2bd389..44e00c7fa3 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -26,6 +26,7 @@
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApisExtension
import net.ltgt.gradle.errorprone.errorprone
+import org.apache.calcite.buildtools.asmchecker.AsmCheckerTask
import org.apache.calcite.buildtools.buildext.dsl.ParenthesisBalancer
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
@@ -37,6 +38,7 @@
publishing
// Verification
checkstyle
+ id("calcite.asmchecker")
calcite.buildext
jacoco
id("jacoco-report-aggregation")
@@ -930,6 +932,15 @@ fun passProperty(name: String, default: String? = null) {
}
jvmArgs("-Xmx6g")
}
+ register<AsmCheckerTask>("bytecodeCheck") {
+ group = LifecycleBasePlugin.VERIFICATION_GROUP
+ description = "Checks the bytecode of every .class file in the
build directory using ASM."
+ dependsOn("classes")
+ }
+
+ check {
+ dependsOn("bytecodeCheck")
+ }
hepLargePlanModeTestIncludes[project.path]?.let { includes ->
val hepLargePlanModeTask =
register<Test>("testHepLargePlanMode") {
group = LifecycleBasePlugin.VERIFICATION_GROUP
diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties
index f308e6c245..a3ffbfb44a 100644
--- a/buildSrc/gradle.properties
+++ b/buildSrc/gradle.properties
@@ -20,3 +20,6 @@ kotlin.code.style=official
# Plugins
com.github.autostyle.version=3.2
com.github.vlsi.vlsi-release-plugins.version=1.52
+
+# Dependencies (keep in sync with root gradle.properties)
+asm.version=9.9.1
diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts
index e3b6a38b80..413ea0b7e5 100644
--- a/buildSrc/settings.gradle.kts
+++ b/buildSrc/settings.gradle.kts
@@ -24,6 +24,7 @@ fun PluginDependenciesSpec.idv(id: String, key: String = id)
= id(id) version ke
}
}
+include("asmchecker")
include("javacc")
include("fmpp")
include("buildext")
diff --git a/buildSrc/subprojects/asmchecker/asmchecker.gradle.kts
b/buildSrc/subprojects/asmchecker/asmchecker.gradle.kts
new file mode 100644
index 0000000000..03f796afd5
--- /dev/null
+++ b/buildSrc/subprojects/asmchecker/asmchecker.gradle.kts
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+dependencies {
+ val asmVersion = providers.gradleProperty("asm.version").get()
+ implementation("org.ow2.asm:asm:$asmVersion")
+ implementation("org.ow2.asm:asm-analysis:$asmVersion")
+ implementation("org.ow2.asm:asm-commons:$asmVersion")
+ implementation("org.ow2.asm:asm-tree:$asmVersion")
+ implementation("org.ow2.asm:asm-util:$asmVersion")
+}
+
+gradlePlugin {
+ plugins {
+ register("asmchecker") {
+ id = "calcite.asmchecker"
+ implementationClass =
"org.apache.calcite.buildtools.asmchecker.AsmCheckerPlugin"
+ }
+ }
+}
diff --git
a/buildSrc/subprojects/asmchecker/src/main/kotlin/org/apache/calcite/buildtools/asmchecker/AsmCheckerPlugin.kt
b/buildSrc/subprojects/asmchecker/src/main/kotlin/org/apache/calcite/buildtools/asmchecker/AsmCheckerPlugin.kt
new file mode 100644
index 0000000000..22463b41cd
--- /dev/null
+++
b/buildSrc/subprojects/asmchecker/src/main/kotlin/org/apache/calcite/buildtools/asmchecker/AsmCheckerPlugin.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.calcite.buildtools.asmchecker
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+open class AsmCheckerPlugin : Plugin<Project> {
+ override fun apply(target: Project) {
+ }
+}
diff --git
a/buildSrc/subprojects/asmchecker/src/main/kotlin/org/apache/calcite/buildtools/asmchecker/AsmCheckerTask.kt
b/buildSrc/subprojects/asmchecker/src/main/kotlin/org/apache/calcite/buildtools/asmchecker/AsmCheckerTask.kt
new file mode 100644
index 0000000000..f1dc97e657
--- /dev/null
+++
b/buildSrc/subprojects/asmchecker/src/main/kotlin/org/apache/calcite/buildtools/asmchecker/AsmCheckerTask.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.calcite.buildtools.asmchecker
+
+import java.nio.file.Files
+import java.nio.file.Paths
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.TaskAction
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.commons.ClassRemapper
+import org.objectweb.asm.commons.Remapper
+import org.objectweb.asm.util.CheckClassAdapter
+
+@CacheableTask
+open class AsmCheckerTask : DefaultTask() {
+
+ @TaskAction
+ fun run() {
+ project.layout.buildDirectory.get().asFile.walk()
+ .onEnter { dir ->
+ // the classes in spark/build/sparkServer/classes, generated by
SparkHandlerImpl,
+ // have invalid bytecode, so exclude them
+ "sparkServer${java.io.File.separator}classes" !in dir.path }
+ .filter { file -> file.getName().lowercase().endsWith(".class") }
+ .forEach {
+ val classReader =
ClassReader(Files.readAllBytes(Paths.get(it.getPath())))
+ val classVisitor =
CheckClassAdapter(ClassWriter(ClassWriter.COMPUTE_MAXS))
+ val classRemapper = ClassRemapper(classVisitor, object :
Remapper() {})
+ try {
+ classReader.accept(classRemapper,
ClassReader.EXPAND_FRAMES)
+ } catch (e: java.lang.RuntimeException) {
+ throw java.lang.RuntimeException("Invalid bytecode file:"
+ it, e)
+ }
+ }
+ }
+}
diff --git a/gradle.properties b/gradle.properties
index 14d29dfa35..0c5e83c503 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -82,6 +82,7 @@ jandex.version=3.5.3
aggdesigner-algorithm.version=6.1
apiguardian-api.version=1.1.2
arrow.version=16.0.0
+# must be kept in sync with buildSrc/gradle.properties
asm.version=9.9.1
byte-buddy.version=1.18.8
cassandra-all.version=4.1.6