From 1774eb9a8632fc68ec5e4ea0fd4ce237b74d0f51 Mon Sep 17 00:00:00 2001 From: Robert Stupp Date: Fri, 31 Jul 2015 20:36:23 +0200 Subject: [PATCH] Bytecode inspection for Java-UDFs patch by Robert Stupp; reviewed by T Jake Luciani for CASSANDRA-9890 --- CHANGES.txt | 2 +- NOTICE.txt | 4 + lib/asm-5.0.4.jar | Bin 0 -> 53297 bytes lib/licenses/asm-5.0.4.txt | 29 ++ .../cql3/functions/JavaBasedUDFunction.java | 53 ++- .../cql3/functions/UDFByteCodeVerifier.java | 215 ++++++++++++ .../cassandra/cql3/functions/UDFunction.java | 1 + .../cql3/functions/JavaSourceUDF.txt | 8 +- .../validation/entities/UFVerifierTest.java | 307 ++++++++++++++++++ .../entities/udfverify/CallClone.java | 49 +++ .../entities/udfverify/CallComDatastax.java | 43 +++ .../entities/udfverify/CallFinalize.java | 49 +++ .../entities/udfverify/CallOrgApache.java | 43 +++ .../entities/udfverify/ClassWithField.java | 43 +++ .../udfverify/ClassWithInitializer.java | 47 +++ .../udfverify/ClassWithInitializer2.java | 47 +++ .../udfverify/ClassWithInitializer3.java | 45 +++ .../udfverify/ClassWithStaticInitializer.java | 46 +++ .../entities/udfverify/GoodClass.java | 41 +++ .../entities/udfverify/UseOfSynchronized.java | 45 +++ .../UseOfSynchronizedWithNotify.java | 45 +++ .../UseOfSynchronizedWithNotifyAll.java | 45 +++ .../udfverify/UseOfSynchronizedWithWait.java | 52 +++ .../udfverify/UseOfSynchronizedWithWaitL.java | 52 +++ .../UseOfSynchronizedWithWaitLI.java | 52 +++ 25 files changed, 1356 insertions(+), 7 deletions(-) create mode 100644 lib/asm-5.0.4.jar create mode 100644 lib/licenses/asm-5.0.4.txt create mode 100644 src/java/org/apache/cassandra/cql3/functions/UDFByteCodeVerifier.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/UFVerifierTest.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallClone.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallComDatastax.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallFinalize.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallOrgApache.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithField.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer2.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer3.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithStaticInitializer.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/GoodClass.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronized.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotify.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotifyAll.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWait.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitL.java create mode 100644 test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitLI.java diff --git a/CHANGES.txt b/CHANGES.txt index c92a771ea7..5f0a52fa4e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,5 @@ 3.0 - * Implement proper sandboxing for UDFs (CASSANDRA-9402) + * Implement proper sandboxing for UDFs (CASSANDRA-9402, 9890) * Simplify (and unify) cleanup of compaction leftovers (CASSANDRA-7066) * Allow extra schema definitions in cassandra-stress yaml (CASSANDRA-9850) * Metrics should use up to date nomenclature (CASSANDRA-9448) diff --git a/NOTICE.txt b/NOTICE.txt index 0ad792ff1c..a20994f48b 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -79,3 +79,7 @@ Protocol buffers for varint encoding https://developers.google.com/protocol-buffers/ Copyright 2008 Google Inc. All rights reserved. BSD 3-clause + +ASM +(http://asm.ow2.org/) +Copyright (c) 2000-2011 INRIA, France Telecom diff --git a/lib/asm-5.0.4.jar b/lib/asm-5.0.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..cdb283dd7f6d7d420ba0fca8ec23e1f38fc3b7c1 GIT binary patch literal 53297 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 literal 0 HcmV?d00001 diff --git a/lib/licenses/asm-5.0.4.txt b/lib/licenses/asm-5.0.4.txt new file mode 100644 index 0000000000..c5aba7be47 --- /dev/null +++ b/lib/licenses/asm-5.0.4.txt @@ -0,0 +1,29 @@ +Copyright (c) 2000-2011 INRIA, France Telecom +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java b/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java index d2827b4906..e066581934 100644 --- a/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java +++ b/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java @@ -38,9 +38,11 @@ import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -90,6 +92,8 @@ final class JavaBasedUDFunction extends UDFunction private static final EcjTargetClassLoader targetClassLoader = new EcjTargetClassLoader(); + private static final UDFByteCodeVerifier udfByteCodeVerifier = new UDFByteCodeVerifier(); + private static final ProtectionDomain protectionDomain; private static final IErrorHandlingPolicy errorHandlingPolicy = DefaultErrorHandlingPolicies.proceedWithAllProblems(); @@ -105,6 +109,24 @@ final class JavaBasedUDFunction extends UDFunction static { + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/Class", "forName"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/Class", "getClassLoader"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/Class", "getResource"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/Class", "getResourceAsStream"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "clearAssertionStatus"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getResource"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getResourceAsStream"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getResources"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getSystemClassLoader"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getSystemResource"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getSystemResourceAsStream"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "getSystemResources"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "loadClass"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "setClassAssertionStatus"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "setDefaultAssertionStatus"); + udfByteCodeVerifier.addDisallowedMethodCall("java/lang/ClassLoader", "setPackageAssertionStatus"); + udfByteCodeVerifier.addDisallowedMethodCall("java/nio/ByteBuffer", "allocateDirect"); + Map settings = new HashMap<>(); settings.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE); @@ -172,6 +194,8 @@ final class JavaBasedUDFunction extends UDFunction String pkgName = BASE_PACKAGE + '.' + generateClassName(name, 'p'); String clsName = generateClassName(name, 'C'); + String executeInternalName = generateClassName(name, 'x'); + StringBuilder javaSourceBuilder = new StringBuilder(); int lineOffset = 1; for (int i = 0; i < javaSourceTemplate.length; i++) @@ -202,6 +226,9 @@ final class JavaBasedUDFunction extends UDFunction case "return_type": s = javaSourceName(javaReturnType); break; + case "execute_internal_name": + s = executeInternalName; + break; } } @@ -262,6 +289,23 @@ final class JavaBasedUDFunction extends UDFunction throw new InvalidRequestException("Java source compilation failed:\n" + problems); } + // Verify the UDF bytecode against use of probably dangerous code + Set errors = udfByteCodeVerifier.verify(targetClassLoader.classData(targetClassName)); + String validDeclare = "not allowed method declared: " + executeInternalName + '('; + String validCall = "call to " + targetClassName.replace('.', '/') + '.' + executeInternalName + "()"; + for (Iterator i = errors.iterator(); i.hasNext();) + { + String error = i.next(); + // we generate a random name of the private, internal execute method, which is detected by the byte-code verifier + if (error.startsWith(validDeclare) || error.equals(validCall)) + { + i.remove(); + } + } + if (!errors.isEmpty()) + throw new InvalidRequestException("Java UDF validation failed: " + errors); + + // Load the class and create a new instance of it Thread thread = Thread.currentThread(); ClassLoader orig = thread.getContextClassLoader(); try @@ -269,7 +313,7 @@ final class JavaBasedUDFunction extends UDFunction thread.setContextClassLoader(UDFunction.udfClassLoader); // Execute UDF intiialization from UDF class loader - Class cls = targetClassLoader.loadClass(targetClassName); + Class cls = Class.forName(targetClassName, false, targetClassLoader); if (cls.getDeclaredMethods().length != 2 || cls.getDeclaredConstructors().length != 1) throw new InvalidRequestException("Check your source to not define additional Java methods or constructors"); @@ -382,7 +426,7 @@ final class JavaBasedUDFunction extends UDFunction private static String composeMethod(Class type) { - return (type.isPrimitive()) ? ("compose_" + type.getName()) : "compose"; + return (type.isPrimitive()) ? ("super.compose_" + type.getName()) : "super.compose"; } // Java source UDFs are a very simple compilation task, which allows us to let one class implement @@ -578,6 +622,11 @@ final class JavaBasedUDFunction extends UDFunction classes.put(className, classData); } + byte[] classData(String className) + { + return classes.get(className); + } + protected Class findClass(String name) throws ClassNotFoundException { // remove the class binary - it's only used once - so it's wasting heap diff --git a/src/java/org/apache/cassandra/cql3/functions/UDFByteCodeVerifier.java b/src/java/org/apache/cassandra/cql3/functions/UDFByteCodeVerifier.java new file mode 100644 index 0000000000..6e5978cd5f --- /dev/null +++ b/src/java/org/apache/cassandra/cql3/functions/UDFByteCodeVerifier.java @@ -0,0 +1,215 @@ +/* + * 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.cassandra.cql3.functions; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Handle; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * Verifies Java UDF byte code. + * Checks for disallowed method calls (e.g. {@code Object.finalize()}), + * additional code in the constructor, + * use of {@code synchronized} blocks, + * too many methods. + */ +public final class UDFByteCodeVerifier +{ + + public static final String JAVA_UDF_NAME = JavaUDF.class.getName().replace('.', '/'); + public static final String OBJECT_NAME = Object.class.getName().replace('.', '/'); + public static final String CTOR_SIG = "(Lcom/datastax/driver/core/DataType;[Lcom/datastax/driver/core/DataType;)V"; + + private final Multimap disallowedMethodCalls = HashMultimap.create(); + private final List disallowedPackages = new ArrayList<>(); + + public UDFByteCodeVerifier() + { + addDisallowedMethodCall(OBJECT_NAME, "clone"); + addDisallowedMethodCall(OBJECT_NAME, "finalize"); + addDisallowedMethodCall(OBJECT_NAME, "notify"); + addDisallowedMethodCall(OBJECT_NAME, "notifyAll"); + addDisallowedMethodCall(OBJECT_NAME, "wait"); + } + + public UDFByteCodeVerifier addDisallowedMethodCall(String clazz, String method) + { + disallowedMethodCalls.put(clazz, method); + return this; + } + + public UDFByteCodeVerifier addDisallowedPackage(String pkg) + { + disallowedPackages.add(pkg); + return this; + } + + public Set verify(byte[] bytes) + { + Set errors = new TreeSet<>(); // it's a TreeSet for unit tests + ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5) + { + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) + { + errors.add("field declared: " + name); + return null; + } + + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) + { + if ("".equals(name) && CTOR_SIG.equals(desc)) + { + if (Opcodes.ACC_PUBLIC != access) + errors.add("constructor not public"); + // allowed constructor - JavaUDF(DataType returnDataType, DataType[] argDataTypes) + return new ConstructorVisitor(errors); + } + if ("executeImpl".equals(name) && "(ILjava/util/List;)Ljava/nio/ByteBuffer;".equals(desc)) + { + if (Opcodes.ACC_PROTECTED != access) + errors.add("executeImpl not protected"); + // the executeImpl method - ByteBuffer executeImpl(int protocolVersion, List params) + return new ExecuteImplVisitor(errors); + } + if ("".equals(name)) + { + errors.add("static initializer declared"); + } + else + { + errors.add("not allowed method declared: " + name + desc); + return new ExecuteImplVisitor(errors); + } + return null; + } + + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) + { + if (!JAVA_UDF_NAME.equals(superName)) + { + errors.add("class does not extend " + JavaUDF.class.getName()); + } + if (access != (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER)) + { + errors.add("class not public final"); + } + super.visit(version, access, name, signature, superName, interfaces); + } + + public void visitInnerClass(String name, String outerName, String innerName, int access) + { + errors.add("class declared as inner class"); + super.visitInnerClass(name, outerName, innerName, access); + } + }; + + ClassReader classReader = new ClassReader(bytes); + classReader.accept(classVisitor, ClassReader.SKIP_DEBUG); + + return errors; + } + + private class ExecuteImplVisitor extends MethodVisitor + { + private final Set errors; + + ExecuteImplVisitor(Set errors) + { + super(Opcodes.ASM5); + this.errors = errors; + } + + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) + { + Collection disallowed = disallowedMethodCalls.get(owner); + if (disallowed != null && disallowed.contains(name)) + { + errors.add("call to " + name + "()"); + } + if (!JAVA_UDF_NAME.equals(owner)) + { + for (String pkg : disallowedPackages) + { + if (owner.startsWith(pkg)) + errors.add("call to " + owner + '.' + name + "()"); + } + } + super.visitMethodInsn(opcode, owner, name, desc, itf); + } + + public void visitInsn(int opcode) + { + switch (opcode) + { + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + errors.add("use of synchronized"); + break; + } + super.visitInsn(opcode); + } + } + + private static class ConstructorVisitor extends MethodVisitor + { + private final Set errors; + + ConstructorVisitor(Set errors) + { + super(Opcodes.ASM5); + this.errors = errors; + } + + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) + { + errors.add("Use of invalid method instruction in constructor"); + super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) + { + if (!(Opcodes.INVOKESPECIAL == opcode && JAVA_UDF_NAME.equals(owner) && "".equals(name) && CTOR_SIG.equals(desc))) + { + errors.add("initializer declared"); + } + super.visitMethodInsn(opcode, owner, name, desc, itf); + } + + public void visitInsn(int opcode) + { + if (Opcodes.RETURN != opcode) + { + errors.add("initializer declared"); + } + super.visitInsn(opcode); + } + } +} diff --git a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java index 9dab8dfdab..58a8198240 100644 --- a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java +++ b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java @@ -113,6 +113,7 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct "com/datastax/driver/core/Statement.class", "com/datastax/driver/core/TimestampGenerator.class", // indirectly covers ServerSideTimestampGenerator + ThreadLocalMonotonicTimestampGenerator "java/lang/Compiler.class", + "java/lang/InheritableThreadLocal.class", "java/lang/Package.class", "java/lang/Process.class", "java/lang/ProcessBuilder.class", diff --git a/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt b/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt index da2d10b027..e72b9c8939 100644 --- a/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt +++ b/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt @@ -14,15 +14,15 @@ public final class #class_name# extends JavaUDF super(returnDataType, argDataTypes); } - public ByteBuffer executeImpl(int protocolVersion, List params) + protected ByteBuffer executeImpl(int protocolVersion, List params) { - #return_type# result = executeInternal( + #return_type# result = #execute_internal_name#( #arguments# ); - return decompose(protocolVersion, result); + return super.decompose(protocolVersion, result); } - private #return_type# executeInternal(#argument_list#) + private #return_type# #execute_internal_name#(#argument_list#) { #body# } diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFVerifierTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFVerifierTest.java new file mode 100644 index 0000000000..69733d57c8 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFVerifierTest.java @@ -0,0 +1,307 @@ +/* + * 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.cassandra.cql3.validation.entities; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; + +import org.junit.Test; + +import org.apache.cassandra.cql3.CQLTester; +import org.apache.cassandra.cql3.functions.UDFByteCodeVerifier; +import org.apache.cassandra.cql3.validation.entities.udfverify.CallClone; +import org.apache.cassandra.cql3.validation.entities.udfverify.CallComDatastax; +import org.apache.cassandra.cql3.validation.entities.udfverify.CallFinalize; +import org.apache.cassandra.cql3.validation.entities.udfverify.CallOrgApache; +import org.apache.cassandra.cql3.validation.entities.udfverify.ClassWithField; +import org.apache.cassandra.cql3.validation.entities.udfverify.ClassWithInitializer; +import org.apache.cassandra.cql3.validation.entities.udfverify.ClassWithInitializer2; +import org.apache.cassandra.cql3.validation.entities.udfverify.ClassWithInitializer3; +import org.apache.cassandra.cql3.validation.entities.udfverify.ClassWithStaticInitializer; +import org.apache.cassandra.cql3.validation.entities.udfverify.GoodClass; +import org.apache.cassandra.cql3.validation.entities.udfverify.UseOfSynchronized; +import org.apache.cassandra.cql3.validation.entities.udfverify.UseOfSynchronizedWithNotify; +import org.apache.cassandra.cql3.validation.entities.udfverify.UseOfSynchronizedWithNotifyAll; +import org.apache.cassandra.cql3.validation.entities.udfverify.UseOfSynchronizedWithWait; +import org.apache.cassandra.cql3.validation.entities.udfverify.UseOfSynchronizedWithWaitL; +import org.apache.cassandra.cql3.validation.entities.udfverify.UseOfSynchronizedWithWaitLI; + +import static org.junit.Assert.assertEquals; + +/** + * Test the Java UDF byte code verifier. + */ +public class UFVerifierTest extends CQLTester +{ + @Test + public void testByteCodeVerifier() + { + new UDFByteCodeVerifier().verify(readClass(GoodClass.class)); + } + + @Test + public void testClassWithField() + { + assertEquals(new HashSet<>(Collections.singletonList("field declared: field")), + new UDFByteCodeVerifier().verify(readClass(ClassWithField.class))); + } + + @Test + public void testClassWithInitializer() + { + assertEquals(new HashSet<>(Arrays.asList("field declared: field", + "initializer declared")), + new UDFByteCodeVerifier().verify(readClass(ClassWithInitializer.class))); + } + + @Test + public void testClassWithInitializer2() + { + assertEquals(new HashSet<>(Arrays.asList("field declared: field", + "initializer declared")), + new UDFByteCodeVerifier().verify(readClass(ClassWithInitializer2.class))); + } + + @Test + public void testClassWithInitializer3() + { + assertEquals(new HashSet<>(Collections.singletonList("initializer declared")), + new UDFByteCodeVerifier().verify(readClass(ClassWithInitializer3.class))); + } + + @Test + public void testClassWithStaticInitializer() + { + assertEquals(new HashSet<>(Collections.singletonList("static initializer declared")), + new UDFByteCodeVerifier().verify(readClass(ClassWithStaticInitializer.class))); + } + + @Test + public void testUseOfSynchronized() + { + assertEquals(new HashSet<>(Collections.singletonList("use of synchronized")), + new UDFByteCodeVerifier().verify(readClass(UseOfSynchronized.class))); + } + + @Test + public void testUseOfSynchronizedWithNotify() + { + assertEquals(new HashSet<>(Arrays.asList("use of synchronized", "call to notify()")), + new UDFByteCodeVerifier().verify(readClass(UseOfSynchronizedWithNotify.class))); + } + + @Test + public void testUseOfSynchronizedWithNotifyAll() + { + assertEquals(new HashSet<>(Arrays.asList("use of synchronized", "call to notifyAll()")), + new UDFByteCodeVerifier().verify(readClass(UseOfSynchronizedWithNotifyAll.class))); + } + + @Test + public void testUseOfSynchronizedWithWait() + { + assertEquals(new HashSet<>(Arrays.asList("use of synchronized", "call to wait()")), + new UDFByteCodeVerifier().verify(readClass(UseOfSynchronizedWithWait.class))); + } + + @Test + public void testUseOfSynchronizedWithWaitL() + { + assertEquals(new HashSet<>(Arrays.asList("use of synchronized", "call to wait()")), + new UDFByteCodeVerifier().verify(readClass(UseOfSynchronizedWithWaitL.class))); + } + + @Test + public void testUseOfSynchronizedWithWaitI() + { + assertEquals(new HashSet<>(Arrays.asList("use of synchronized", "call to wait()")), + new UDFByteCodeVerifier().verify(readClass(UseOfSynchronizedWithWaitLI.class))); + } + + @Test + public void testCallClone() + { + assertEquals(new HashSet<>(Collections.singletonList("call to clone()")), + new UDFByteCodeVerifier().verify(readClass(CallClone.class))); + } + + @Test + public void testCallFinalize() + { + assertEquals(new HashSet<>(Collections.singletonList("call to finalize()")), + new UDFByteCodeVerifier().verify(readClass(CallFinalize.class))); + } + + @Test + public void testCallComDatastax() + { + assertEquals(new HashSet<>(Collections.singletonList("call to com/datastax/driver/core/DataType.cint()")), + new UDFByteCodeVerifier().addDisallowedPackage("com/").verify(readClass(CallComDatastax.class))); + } + + @Test + public void testCallOrgApache() + { + assertEquals(new HashSet<>(Collections.singletonList("call to org/apache/cassandra/config/DatabaseDescriptor.getClusterName()")), + new UDFByteCodeVerifier().addDisallowedPackage("org/").verify(readClass(CallOrgApache.class))); + } + + @SuppressWarnings("resource") + private static byte[] readClass(Class clazz) + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + URL res = clazz.getClassLoader().getResource(clazz.getName().replace('.', '/') + ".class"); + assert res != null; + try (InputStream input = res.openConnection().getInputStream()) + { + int i; + while ((i = input.read()) != -1) + out.write(i); + return out.toByteArray(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + @Test + public void testInvalidByteCodeUDFs() throws Throwable + { + assertInvalidByteCode("try\n" + + "{\n" + + " clone();\n" + + "}\n" + + "catch (CloneNotSupportedException e)\n" + + "{\n" + + " throw new RuntimeException(e);\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to clone()]"); + assertInvalidByteCode("try\n" + + "{\n" + + " finalize();\n" + + "}\n" + + "catch (Throwable e)\n" + + "{\n" + + " throw new RuntimeException(e);\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to finalize()]"); + assertInvalidByteCode('\n' + + "return 0d;\n" + + " }\n" + + '\n' + + " Object field;\n" + + '\n' + + " {", "Java UDF validation failed: [field declared: field]"); + assertInvalidByteCode('\n' + + "return 0d;\n" + + " }\n" + + '\n' + + " final Object field;\n" + + '\n' + + " {\n" + + "field = new Object();", "Java UDF validation failed: [field declared: field, initializer declared]"); + assertInvalidByteCode('\n' + + "return 0d;\n" + + " }\n" + + '\n' + + " Object field = new Object();\n" + + '\n' + + " {\n" + + "Math.sin(1d);", "Java UDF validation failed: [field declared: field, initializer declared]"); + assertInvalidByteCode('\n' + + "return 0d;\n" + + " }\n" + + '\n' + + " {\n" + + "Math.sin(1d);", "Java UDF validation failed: [initializer declared]"); + assertInvalidByteCode('\n' + + "return 0d;\n" + + " }\n" + + '\n' + + " static\n" + + " {\n" + + "Math.sin(1d);", "Java UDF validation failed: [static initializer declared]"); + assertInvalidByteCode("synchronized (this)\n" + + "{\n" + + " Math.sin(1d);\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [use of synchronized]"); + assertInvalidByteCode("synchronized (this)\n" + + "{\n" + + " notify();\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to notify(), use of synchronized]"); + assertInvalidByteCode("synchronized (this)\n" + + "{\n" + + " notifyAll();\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to notifyAll(), use of synchronized]"); + assertInvalidByteCode("synchronized (this)\n" + + "{\n" + + " try\n" + + " {\n" + + " wait();\n" + + " }\n" + + " catch (InterruptedException e)\n" + + " {\n" + + " throw new RuntimeException(e);\n" + + " }\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to wait(), use of synchronized]"); + assertInvalidByteCode("synchronized (this)\n" + + "{\n" + + " try\n" + + " {\n" + + " wait(1000L);\n" + + " }\n" + + " catch (InterruptedException e)\n" + + " {\n" + + " throw new RuntimeException(e);\n" + + " }\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to wait(), use of synchronized]"); + assertInvalidByteCode("synchronized (this)\n" + + "{\n" + + " try\n" + + " {\n" + + " wait(1000L, 100);\n" + + " }\n" + + " catch (InterruptedException e)\n" + + " {\n" + + " throw new RuntimeException(e);\n" + + " }\n" + + "}\n" + + "return 0d;", "Java UDF validation failed: [call to wait(), use of synchronized]"); + } + + private void assertInvalidByteCode(String body, String error) throws Throwable + { + assertInvalidMessage(error, + "CREATE FUNCTION " + KEYSPACE + ".mustBeInvalid ( input double ) " + + "CALLED ON NULL INPUT " + + "RETURNS double " + + "LANGUAGE java AS $$" + body + "$$"); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallClone.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallClone.java new file mode 100644 index 0000000000..51481d884f --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallClone.java @@ -0,0 +1,49 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class CallClone extends JavaUDF +{ + public CallClone(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + try + { + clone(); + } + catch (CloneNotSupportedException e) + { + throw new RuntimeException(e); + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallComDatastax.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallComDatastax.java new file mode 100644 index 0000000000..5c7e8b3c1e --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallComDatastax.java @@ -0,0 +1,43 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class CallComDatastax extends JavaUDF +{ + public CallComDatastax(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + DataType.cint(); + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallFinalize.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallFinalize.java new file mode 100644 index 0000000000..1b69a72f7a --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallFinalize.java @@ -0,0 +1,49 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class CallFinalize extends JavaUDF +{ + public CallFinalize(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + try + { + finalize(); + } + catch (Throwable e) + { + throw new RuntimeException(e); + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallOrgApache.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallOrgApache.java new file mode 100644 index 0000000000..7a850e82bf --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallOrgApache.java @@ -0,0 +1,43 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class CallOrgApache extends JavaUDF +{ + public CallOrgApache(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + DatabaseDescriptor.getClusterName(); + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithField.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithField.java new file mode 100644 index 0000000000..f43588dc8b --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithField.java @@ -0,0 +1,43 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class ClassWithField extends JavaUDF +{ + public ClassWithField(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + return null; + } + + Object field; +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer.java new file mode 100644 index 0000000000..a6e10fb2a3 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer.java @@ -0,0 +1,47 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class ClassWithInitializer extends JavaUDF +{ + public ClassWithInitializer(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + return null; + } + + final Object field; + + { + field = new Object(); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer2.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer2.java new file mode 100644 index 0000000000..d0c8e112c6 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer2.java @@ -0,0 +1,47 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class ClassWithInitializer2 extends JavaUDF +{ + public ClassWithInitializer2(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + return null; + } + + final Object field = new Object(); + + { + Math.sin(1d); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer3.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer3.java new file mode 100644 index 0000000000..8672cd29d1 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer3.java @@ -0,0 +1,45 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class ClassWithInitializer3 extends JavaUDF +{ + public ClassWithInitializer3(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + return null; + } + + { + Math.sin(1d); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithStaticInitializer.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithStaticInitializer.java new file mode 100644 index 0000000000..459a6eb339 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithStaticInitializer.java @@ -0,0 +1,46 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class ClassWithStaticInitializer extends JavaUDF +{ + public ClassWithStaticInitializer(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + return null; + } + + static + { + Math.sin(1d); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/GoodClass.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/GoodClass.java new file mode 100644 index 0000000000..2666023685 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/GoodClass.java @@ -0,0 +1,41 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class GoodClass extends JavaUDF +{ + public GoodClass(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronized.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronized.java new file mode 100644 index 0000000000..0059a0a6ca --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronized.java @@ -0,0 +1,45 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class UseOfSynchronized extends JavaUDF +{ + public UseOfSynchronized(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + synchronized (this) + { + Math.sin(1d); + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotify.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotify.java new file mode 100644 index 0000000000..2da13b6f20 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotify.java @@ -0,0 +1,45 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class UseOfSynchronizedWithNotify extends JavaUDF +{ + public UseOfSynchronizedWithNotify(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + synchronized (this) + { + notify(); + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotifyAll.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotifyAll.java new file mode 100644 index 0000000000..1e4d33d6a0 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotifyAll.java @@ -0,0 +1,45 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class UseOfSynchronizedWithNotifyAll extends JavaUDF +{ + public UseOfSynchronizedWithNotifyAll(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + synchronized (this) + { + notifyAll(); + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWait.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWait.java new file mode 100644 index 0000000000..ccaf6ee258 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWait.java @@ -0,0 +1,52 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class UseOfSynchronizedWithWait extends JavaUDF +{ + public UseOfSynchronizedWithWait(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + synchronized (this) + { + try + { + wait(); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitL.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitL.java new file mode 100644 index 0000000000..56aa7266c3 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitL.java @@ -0,0 +1,52 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class UseOfSynchronizedWithWaitL extends JavaUDF +{ + public UseOfSynchronizedWithWaitL(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + synchronized (this) + { + try + { + wait(1000L); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + return null; + } +} diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitLI.java b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitLI.java new file mode 100644 index 0000000000..403fb68f70 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitLI.java @@ -0,0 +1,52 @@ +/* + * 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.cassandra.cql3.validation.entities.udfverify; + +import java.nio.ByteBuffer; +import java.util.List; + +import com.datastax.driver.core.DataType; +import org.apache.cassandra.cql3.functions.JavaUDF; + +/** + * Used by {@link org.apache.cassandra.cql3.validation.entities.UFVerifierTest}. + */ +public final class UseOfSynchronizedWithWaitLI extends JavaUDF +{ + public UseOfSynchronizedWithWaitLI(DataType returnDataType, DataType[] argDataTypes) + { + super(returnDataType, argDataTypes); + } + + protected ByteBuffer executeImpl(int protocolVersion, List params) + { + synchronized (this) + { + try + { + wait(1000L, 100); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + return null; + } +}