cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sn...@apache.org
Subject cassandra git commit: Bytecode inspection for Java-UDFs
Date Fri, 31 Jul 2015 18:37:24 GMT
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 <snazy@snazy.de>
Authored: Fri Jul 31 20:36:23 2015 +0200
Committer: Robert Stupp <snazy@snazy.de>
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;
+    }
+}


Mime
View raw message