Repository: cassandra Updated Branches: refs/heads/trunk a22ce89e8 -> 1774eb9a8
Bytecode inspection for Java-UDFs patch by Robert Stupp; reviewed by T Jake Luciani for CASSANDRA-9890 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1774eb9a Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1774eb9a Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1774eb9a Branch: refs/heads/trunk Commit: 1774eb9a8632fc68ec5e4ea0fd4ce237b74d0f51 Parents: a22ce89 Author: Robert Stupp <[email protected]> Authored: Fri Jul 31 20:36:23 2015 +0200 Committer: Robert Stupp <[email protected]> Committed: Fri Jul 31 20:36:23 2015 +0200 ---------------------------------------------------------------------- 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 + .../cassandra/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 +++ .../udfverify/UseOfSynchronizedWithNotify.java | 45 +++ .../UseOfSynchronizedWithNotifyAll.java | 45 +++ .../udfverify/UseOfSynchronizedWithWait.java | 52 ++++ .../udfverify/UseOfSynchronizedWithWaitL.java | 52 ++++ .../udfverify/UseOfSynchronizedWithWaitLI.java | 52 ++++ 25 files changed, 1356 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index c92a771..5f0a52f 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) http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/NOTICE.txt ---------------------------------------------------------------------- diff --git a/NOTICE.txt b/NOTICE.txt index 0ad792f..a20994f 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 http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/lib/asm-5.0.4.jar ---------------------------------------------------------------------- diff --git a/lib/asm-5.0.4.jar b/lib/asm-5.0.4.jar new file mode 100644 index 0000000..cdb283d Binary files /dev/null and b/lib/asm-5.0.4.jar differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/lib/licenses/asm-5.0.4.txt ---------------------------------------------------------------------- diff --git a/lib/licenses/asm-5.0.4.txt b/lib/licenses/asm-5.0.4.txt new file mode 100644 index 0000000..c5aba7b --- /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. http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java b/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java index d2827b4..e066581 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<String, String> 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<String> errors = udfByteCodeVerifier.verify(targetClassLoader.classData(targetClassName)); + String validDeclare = "not allowed method declared: " + executeInternalName + '('; + String validCall = "call to " + targetClassName.replace('.', '/') + '.' + executeInternalName + "()"; + for (Iterator<String> 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 http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/src/java/org/apache/cassandra/cql3/functions/UDFByteCodeVerifier.java ---------------------------------------------------------------------- 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 0000000..6e5978c --- /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<String, String> disallowedMethodCalls = HashMultimap.create(); + private final List<String> 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<String> verify(byte[] bytes) + { + Set<String> 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 ("<init>".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<ByteBuffer> params) + return new ExecuteImplVisitor(errors); + } + if ("<clinit>".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<String> errors; + + ExecuteImplVisitor(Set<String> errors) + { + super(Opcodes.ASM5); + this.errors = errors; + } + + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) + { + Collection<String> 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<String> errors; + + ConstructorVisitor(Set<String> 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) && "<init>".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); + } + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java index 9dab8df..58a8198 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", http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt ---------------------------------------------------------------------- diff --git a/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt b/src/resources/org/apache/cassandra/cql3/functions/JavaSourceUDF.txt index da2d10b..e72b9c8 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<ByteBuffer> params) + protected ByteBuffer executeImpl(int protocolVersion, List<ByteBuffer> 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# } http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/UFVerifierTest.java ---------------------------------------------------------------------- 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 0000000..69733d5 --- /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 + "$$"); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallClone.java ---------------------------------------------------------------------- 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 0000000..51481d8 --- /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<ByteBuffer> params) + { + try + { + clone(); + } + catch (CloneNotSupportedException e) + { + throw new RuntimeException(e); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallComDatastax.java ---------------------------------------------------------------------- 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 0000000..5c7e8b3 --- /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<ByteBuffer> params) + { + DataType.cint(); + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallFinalize.java ---------------------------------------------------------------------- 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 0000000..1b69a72 --- /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<ByteBuffer> params) + { + try + { + finalize(); + } + catch (Throwable e) + { + throw new RuntimeException(e); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/CallOrgApache.java ---------------------------------------------------------------------- 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 0000000..7a850e8 --- /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<ByteBuffer> params) + { + DatabaseDescriptor.getClusterName(); + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithField.java ---------------------------------------------------------------------- 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 0000000..f43588d --- /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<ByteBuffer> params) + { + return null; + } + + Object field; +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer.java ---------------------------------------------------------------------- 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 0000000..a6e10fb --- /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<ByteBuffer> params) + { + return null; + } + + final Object field; + + { + field = new Object(); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer2.java ---------------------------------------------------------------------- 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 0000000..d0c8e11 --- /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<ByteBuffer> params) + { + return null; + } + + final Object field = new Object(); + + { + Math.sin(1d); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithInitializer3.java ---------------------------------------------------------------------- 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 0000000..8672cd2 --- /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<ByteBuffer> params) + { + return null; + } + + { + Math.sin(1d); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/ClassWithStaticInitializer.java ---------------------------------------------------------------------- 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 0000000..459a6eb --- /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<ByteBuffer> params) + { + return null; + } + + static + { + Math.sin(1d); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/GoodClass.java ---------------------------------------------------------------------- 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 0000000..2666023 --- /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<ByteBuffer> params) + { + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronized.java ---------------------------------------------------------------------- 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 0000000..0059a0a --- /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<ByteBuffer> params) + { + synchronized (this) + { + Math.sin(1d); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotify.java ---------------------------------------------------------------------- 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 0000000..2da13b6 --- /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<ByteBuffer> params) + { + synchronized (this) + { + notify(); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithNotifyAll.java ---------------------------------------------------------------------- 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 0000000..1e4d33d --- /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<ByteBuffer> params) + { + synchronized (this) + { + notifyAll(); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWait.java ---------------------------------------------------------------------- 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 0000000..ccaf6ee --- /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<ByteBuffer> params) + { + synchronized (this) + { + try + { + wait(); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitL.java ---------------------------------------------------------------------- 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 0000000..56aa726 --- /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<ByteBuffer> params) + { + synchronized (this) + { + try + { + wait(1000L); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1774eb9a/test/unit/org/apache/cassandra/cql3/validation/entities/udfverify/UseOfSynchronizedWithWaitLI.java ---------------------------------------------------------------------- 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 0000000..403fb68 --- /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<ByteBuffer> params) + { + synchronized (this) + { + try + { + wait(1000L, 100); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + return null; + } +}
