diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ddl/function/create/CreateFunctionOperation.java b/ql/src/java/org/apache/hadoop/hive/ql/ddl/function/create/CreateFunctionOperation.java index 9489675dfaa2..2a7ce1443d4d 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/ddl/function/create/CreateFunctionOperation.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/ddl/function/create/CreateFunctionOperation.java @@ -71,6 +71,10 @@ private int createTemporaryFunction() { FunctionUtils.addFunctionResources(resources); Class udfClass = getUdfClass(); + if (!validateIfBlockedUDF(udfClass)) { + return 1; + } + FunctionInfo registered = FunctionRegistry.registerTemporaryUDF(desc.getName(), udfClass, resources); if (registered != null) { return 0; @@ -79,8 +83,9 @@ private int createTemporaryFunction() { "FAILED: Class " + desc.getClassName() + " does not implement UDF, GenericUDF, or UDAF"); return 1; } - } catch (HiveException e) { - context.getConsole().printError("FAILED: " + e.toString()); + } + catch (HiveException e) { + context.getConsole().printError("FAILED: Create function: " + e.toString()); LOG.info("create function: ", e); return 1; } catch (ClassNotFoundException e) { @@ -90,6 +95,23 @@ private int createTemporaryFunction() { } } + /** + * Validates if the function being created is from blacklisted UDF. + * + * @return `true` if the UDF is valid and not blocked, `false` otherwise. + */ + private boolean validateIfBlockedUDF(Class udfClass) { + try { + // Function creation with blocked UDFs will fail with SemanticException here + FunctionRegistry.getFunctionInfo(FunctionUtils.getFuncNameFromClass(udfClass)); + return true; + } catch (SemanticException e) { + // Log and print error if the UDF is blocked + context.getConsole().printError("FAILED: Create function: " + e.toString()); + LOG.info("create function: ", e); + return false; + } + } private Class getUdfClass() throws ClassNotFoundException { // get the session specified class loader from SessionState ClassLoader classLoader = Utilities.getSessionSpecifiedClassLoader(); @@ -120,7 +142,6 @@ private int createPermanentFunction() throws HiveException, IOException { if (!addToMetastoreSuccess) { return 1; } - return 0; } @@ -172,8 +193,15 @@ private boolean registerFunction(String registeredName) throws SemanticException HiveConf oldConf = SessionState.get().getConf(); try { SessionState.get().setConf(context.getConf()); + if (!validateIfBlockedUDF(getUdfClass())) { + return false; + } registered = FunctionRegistry.registerPermanentFunction(registeredName, desc.getClassName(), true, FunctionUtils.toFunctionResource(desc.getResources())); + } catch (ClassNotFoundException e) { + context.getConsole().printError("FAILED: Class " + desc.getClassName() + " not found"); + LOG.info("create function: ", e); + return false; } catch (RuntimeException ex) { Throwable t = ex; while (t.getCause() != null) { diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java index 9a916397c9c9..7d419a5ccfb2 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java @@ -141,6 +141,22 @@ public static String[] getQualifiedFunctionNameParts(String name) throws HiveExc return new String[] { dbName, name }; } + /** + * Retrieves the display name of a UDF (User Defined Function) from its class + * by inspecting the `@Description` annotation. + * + * @param udfClass The class of the UDF to inspect. + * @return The name of the UDF as specified in the `name` field of the `@Description` annotation, + * or `null` if the annotation is not present. + */ + public static String getFuncNameFromClass(Class udfClass) { + if (udfClass.isAnnotationPresent(Description.class)) { + Description description = udfClass.getAnnotation(Description.class); + return description.name(); + } + return null; + } + /** * Function type, for permanent functions. * Currently just JAVA, though we could support Groovy later on.