You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sn...@apache.org on 2015/07/31 20:37:24 UTC
cassandra git commit: Bytecode inspection for Java-UDFs
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 <sn...@snazy.de>
Authored: Fri Jul 31 20:36:23 2015 +0200
Committer: Robert Stupp <sn...@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;
+ }
+}