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

Reply via email to