github-advanced-security[bot] commented on code in PR #4420:
URL: https://github.com/apache/streampark/pull/4420#discussion_r3540561391


##########
streampark-common/src/main/java/org/apache/streampark/common/util/FileUtils.java:
##########
@@ -0,0 +1,325 @@
+/*
+ * 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.streampark.common.util;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.Serializable;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Scanner;
+import java.util.stream.Collectors;
+
+public final class FileUtils {
+
+    private FileUtils() {}
+
+    public static File toCanonicalFile(String path) throws IOException {
+        Path normalized = Paths.get(path).normalize();
+        if (normalized.toString().contains("..")) {
+            throw new IOException("Invalid path: " + path);
+        }
+        return normalized.toFile().getCanonicalFile();
+    }
+
+    public static File resolveChildFile(File baseDir, String... childSegments) 
throws IOException {
+        Path base = baseDir.getCanonicalFile().toPath();
+        Path current = base;
+        for (String segment : childSegments) {
+            if (segment == null || segment.isEmpty() || 
segment.contains("..")) {
+                throw new IOException("Invalid path segment: " + segment);
+            }
+            current = current.resolve(segment);
+        }
+        Path resolved = current.normalize().toAbsolutePath();
+        if (!resolved.startsWith(base)) {
+            throw new IOException("Resolved path escapes base directory: " + 
resolved);
+        }
+        return resolved.toFile();
+    }
+
+    private static String bytesToHexString(byte[] src) {
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        StringBuilder stringBuilder = new StringBuilder();
+        for (byte b : src) {
+            int v = b & 0xFF;
+            String hv = Integer.toHexString(v).toUpperCase();
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    public static boolean isJarFileType(InputStream input) {
+        if (input == null) {
+            throw new RuntimeException("The inputStream can not be null");
+        }
+        return AutoCloseUtils.using(
+                        input,
+                        in -> {
+                            byte[] b = new byte[4];
+                            try {
+                                in.read(b, 0, b.length);
+                            } catch (IOException e) {
+                                throw new RuntimeException(e);
+                            }
+                            return bytesToHexString(b);
+                        })
+                .equals("504B0304");
+    }
+
+    public static boolean isJarFileType(File file) throws IOException {
+        if (!file.exists() || !file.isFile()) {
+            throw new RuntimeException("The file does not exist or the path is 
a directory");
+        }
+        return isJarFileType(new FileInputStream(file));
+    }
+
+    public static File createTempDir() {
+        final int TEMP_DIR_ATTEMPTS = 10000;
+        File baseDir = new File(System.getProperty("java.io.tmpdir"));
+        String baseName = System.currentTimeMillis() + "-";
+        for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
+            File tempDir = new File(baseDir, baseName + counter);
+            if (tempDir.mkdir()) {
+                return tempDir;
+            }
+        }
+        throw new IllegalStateException(
+                "[StreamPark] Failed to create directory within "
+                        + TEMP_DIR_ATTEMPTS
+                        + "  attempts (tried "
+                        + baseName
+                        + " 0 to "
+                        + baseName
+                        + (TEMP_DIR_ATTEMPTS - 1)
+                        + ")");
+    }
+
+    public static void mkdir(File dir) throws IOException {
+        if (dir.exists() && !dir.isDirectory()) {
+            throw new IOException("File " + dir + " exists and is not a 
directory. Unable to create directory.");
+        } else if (!dir.mkdirs() && !dir.isDirectory()) {
+            throw new IOException("Unable to create directory " + dir);
+        }
+    }
+
+    public static String getPathFromEnv(String env) {
+        String path = System.getenv(env);
+        if (path == null) {
+            path = System.getProperty(env);
+        }
+        AssertUtils.notNull(path, "[StreamPark] FileUtils.getPathFromEnv: " + 
env + " is not set on system env");
+        File file = new File(path);
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] 
FileUtils.getPathFromEnv: " + env + " is not exist!");
+        }
+        return file.getAbsolutePath();
+    }
+
+    public static String resolvePath(String parent, String child) {
+        File file = new File(parent, child);
+        if (!file.exists()) {
+            throw new IllegalArgumentException(
+                    "[StreamPark] FileUtils.resolvePath: " + 
file.getAbsolutePath() + " is not exist!");
+        }
+        return file.getAbsolutePath();
+    }
+
+    public static String getSuffix(String filename) {
+        AssertUtils.notNull(filename);
+        return filename.substring(filename.lastIndexOf("."));
+    }
+
+    public static List<URL> listFileAsURL(String dirPath) {
+        File dir = new File(dirPath);
+        if (dir.exists() && dir.isDirectory()) {
+            File[] files = dir.listFiles();
+            if (files != null && files.length > 0) {
+                List<URL> urls = new ArrayList<>();
+                for (File f : files) {
+                    try {
+                        urls.add(f.toURI().toURL());
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                return urls;
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    public static boolean exists(Serializable file) {
+        if (file == null) {
+            return false;
+        }
+        if (file instanceof File) {
+            return ((File) file).exists();
+        }
+        return new File(file.toString()).exists();
+    }
+
+    public static boolean directoryNotBlank(Serializable file) {
+        if (file == null) {
+            return false;
+        }
+        File f = file instanceof File ? (File) file : new 
File(file.toString());
+        String[] list = f.list();
+        return f.isDirectory() && list != null && list.length > 0;
+    }
+
+    public static boolean equals(File file1, File file2) throws IOException {
+        if (file1 == null || file2 == null) {
+            return false;
+        }
+        if (!file1.exists() || !file2.exists()) {
+            return false;
+        }
+        if (file1.getAbsolutePath().equals(file2.getAbsolutePath())) {
+            return true;
+        }
+        BufferedInputStream first = new BufferedInputStream(new 
FileInputStream(file1));
+        BufferedInputStream second = new BufferedInputStream(new 
FileInputStream(file2));
+        if (first.available() != second.available()) {
+            Utils.close(first, second);
+            return false;
+        }
+        while (true) {
+            int firRead = first.read();
+            int secRead = second.read();
+            if (firRead != secRead) {
+                Utils.close(first, second);
+                return false;
+            }
+            if (firRead == -1) {
+                Utils.close(first, second);
+                return true;
+            }
+        }
+    }
+
+    public static void readInputStream(InputStream in, byte[] array) throws 
IOException {
+        try (InputStream input = in) {
+            int toRead = array.length;
+            int off = 0;
+            while (toRead > 0) {
+                int ret = input.read(array, off, toRead);
+                if (ret < 0) {
+                    throw new IOException("Bad inputStream, premature EOF");
+                }
+                toRead -= ret;
+                off += ret;
+            }
+        }
+    }
+
+    public static String readFile(File file) throws IOException {
+        Path canonicalPath = file.getCanonicalFile().toPath();
+        if (Files.size(canonicalPath) >= Integer.MAX_VALUE) {

Review Comment:
   ## SonarCloud / Accessing files should not lead to filesystem oracle attacks
   
   <!--SONAR_ISSUE_KEY:AZ8_OJ0YOVToqvy4RHQu-->Change this code to not construct 
the path from user-controlled data. <p>See more on <a 
href="https://sonarcloud.io/project/issues?id=apache_incubator-streampark&issues=AZ8_OJ0YOVToqvy4RHQu&open=AZ8_OJ0YOVToqvy4RHQu&pullRequest=4420";>SonarQube
 Cloud</a></p>
   
   [Show more 
details](https://github.com/apache/streampark/security/code-scanning/236)



##########
streampark-common/src/main/java/org/apache/streampark/common/util/PropertiesUtils.java:
##########
@@ -0,0 +1,292 @@
+/*
+ * 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.streampark.common.util;
+
+import com.typesafe.config.ConfigFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.streampark.shaded.org.slf4j.Logger;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+
+public final class PropertiesUtils {
+
+    private static final Logger LOG =
+            
StreamParkLoggerFactory.loggerFactory().getLogger(PropertiesUtils.class.getName());
+
+    private PropertiesUtils() {}
+
+    public static String readFile(String filename) {
+        Path path = toConfigPath(filename, "readFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " is not a normal file");
+        }
+        try (Scanner scanner = new Scanner(file)) {
+            StringBuilder buffer = new StringBuilder();
+            while (scanner.hasNextLine()) {
+                buffer.append(scanner.nextLine()).append("\r\n");
+            }
+            return buffer.toString();
+        } catch (java.io.FileNotFoundException e) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " does not exist", e);
+        }
+    }
+
+    public static Map<String, String> fromYamlText(String text) {
+        try {
+            Map<String, Object> map = new Yaml().load(text);
+            return flatten(map);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Failed when loading conf 
error:", e);
+        }
+    }
+
+    public static Map<String, String> fromHoconText(String conf) {
+        if (conf == null) {
+            throw new IllegalArgumentException("[StreamPark] fromHoconText: 
Hocon content must not be null");
+        }
+        try {
+            return parseHoconByReader(new StringReader(conf));
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading Hocon ", 
e);
+        }
+    }
+
+    public static Map<String, String> fromPropertiesText(String conf) {
+        try {
+            Properties properties = new Properties();
+            properties.load(new StringReader(conf));
+            Map<String, String> result = new HashMap<>();
+            for (String k : properties.stringPropertyNames()) {
+                result.put(k, properties.getProperty(k).trim());
+            }
+            return result;
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading properties 
", e);
+        }
+    }
+
+    public static Map<String, String> fromYamlFile(String filename) {
+        Path path = toConfigPath(filename, "fromYamlFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] fromYamlFile: 
Yaml file " + file + " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("[StreamPark] fromYamlFile: 
Yaml file " + file + " is not a normal file");
+        }
+        try (InputStream inputStream = Files.newInputStream(path)) {
+            return fromYamlFile(inputStream);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading yaml from 
file", e);
+        }
+    }
+
+    public static Map<String, String> fromHoconFile(String filename) {
+        Path path = toConfigPath(filename, "fromHoconFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] fromHoconFile: 
file " + file + " does not exist");
+        }
+        try (InputStream inputStream = Files.newInputStream(path)) {

Review Comment:
   ## SonarCloud / I/O function calls should not be vulnerable to path 
injection attacks
   
   <!--SONAR_ISSUE_KEY:AZ8_MSRL5bWB2tWCYapG-->Change this code to not construct 
the path from user-controlled data. <p>See more on <a 
href="https://sonarcloud.io/project/issues?id=apache_incubator-streampark&issues=AZ8_MSRL5bWB2tWCYapG&open=AZ8_MSRL5bWB2tWCYapG&pullRequest=4420";>SonarQube
 Cloud</a></p>
   
   [Show more 
details](https://github.com/apache/streampark/security/code-scanning/232)



##########
streampark-common/src/main/java/org/apache/streampark/common/util/PropertiesUtils.java:
##########
@@ -0,0 +1,292 @@
+/*
+ * 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.streampark.common.util;
+
+import com.typesafe.config.ConfigFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.streampark.shaded.org.slf4j.Logger;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+
+public final class PropertiesUtils {
+
+    private static final Logger LOG =
+            
StreamParkLoggerFactory.loggerFactory().getLogger(PropertiesUtils.class.getName());
+
+    private PropertiesUtils() {}
+
+    public static String readFile(String filename) {
+        Path path = toConfigPath(filename, "readFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " is not a normal file");
+        }
+        try (Scanner scanner = new Scanner(file)) {
+            StringBuilder buffer = new StringBuilder();
+            while (scanner.hasNextLine()) {
+                buffer.append(scanner.nextLine()).append("\r\n");
+            }
+            return buffer.toString();
+        } catch (java.io.FileNotFoundException e) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " does not exist", e);
+        }
+    }
+
+    public static Map<String, String> fromYamlText(String text) {
+        try {
+            Map<String, Object> map = new Yaml().load(text);
+            return flatten(map);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Failed when loading conf 
error:", e);
+        }
+    }
+
+    public static Map<String, String> fromHoconText(String conf) {
+        if (conf == null) {
+            throw new IllegalArgumentException("[StreamPark] fromHoconText: 
Hocon content must not be null");
+        }
+        try {
+            return parseHoconByReader(new StringReader(conf));
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading Hocon ", 
e);
+        }
+    }
+
+    public static Map<String, String> fromPropertiesText(String conf) {
+        try {
+            Properties properties = new Properties();
+            properties.load(new StringReader(conf));
+            Map<String, String> result = new HashMap<>();
+            for (String k : properties.stringPropertyNames()) {
+                result.put(k, properties.getProperty(k).trim());
+            }
+            return result;
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading properties 
", e);
+        }
+    }
+
+    public static Map<String, String> fromYamlFile(String filename) {
+        Path path = toConfigPath(filename, "fromYamlFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] fromYamlFile: 
Yaml file " + file + " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("[StreamPark] fromYamlFile: 
Yaml file " + file + " is not a normal file");
+        }
+        try (InputStream inputStream = Files.newInputStream(path)) {
+            return fromYamlFile(inputStream);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading yaml from 
file", e);
+        }
+    }
+
+    public static Map<String, String> fromHoconFile(String filename) {
+        Path path = toConfigPath(filename, "fromHoconFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] fromHoconFile: 
file " + file + " does not exist");
+        }
+        try (InputStream inputStream = Files.newInputStream(path)) {
+            return fromHoconFile(inputStream);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading Hocon ", 
e);
+        }
+    }
+
+    public static Map<String, String> fromPropertiesFile(String filename) {
+        Path path = toConfigPath(filename, "fromPropertiesFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException(
+                    "[StreamPark] fromPropertiesFile: Properties file " + file 
+ " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException(
+                    "[StreamPark] fromPropertiesFile: Properties file " + file 
+ " is not a normal file");
+        }
+        try (InputStream inputStream = Files.newInputStream(path)) {

Review Comment:
   ## SonarCloud / I/O function calls should not be vulnerable to path 
injection attacks
   
   <!--SONAR_ISSUE_KEY:AZ8_PEvYE9D-RjRrxYQc-->Change this code to not construct 
the path from user-controlled data. <p>See more on <a 
href="https://sonarcloud.io/project/issues?id=apache_incubator-streampark&issues=AZ8_PEvYE9D-RjRrxYQc&open=AZ8_PEvYE9D-RjRrxYQc&pullRequest=4420";>SonarQube
 Cloud</a></p>
   
   [Show more 
details](https://github.com/apache/streampark/security/code-scanning/235)



##########
streampark-common/src/main/java/org/apache/streampark/common/util/PropertiesUtils.java:
##########
@@ -0,0 +1,292 @@
+/*
+ * 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.streampark.common.util;
+
+import com.typesafe.config.ConfigFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.streampark.shaded.org.slf4j.Logger;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+
+public final class PropertiesUtils {
+
+    private static final Logger LOG =
+            
StreamParkLoggerFactory.loggerFactory().getLogger(PropertiesUtils.class.getName());
+
+    private PropertiesUtils() {}
+
+    public static String readFile(String filename) {
+        Path path = toConfigPath(filename, "readFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " is not a normal file");
+        }
+        try (Scanner scanner = new Scanner(file)) {
+            StringBuilder buffer = new StringBuilder();
+            while (scanner.hasNextLine()) {
+                buffer.append(scanner.nextLine()).append("\r\n");
+            }
+            return buffer.toString();
+        } catch (java.io.FileNotFoundException e) {
+            throw new IllegalArgumentException("[StreamPark] readFile: file " 
+ file + " does not exist", e);
+        }
+    }
+
+    public static Map<String, String> fromYamlText(String text) {
+        try {
+            Map<String, Object> map = new Yaml().load(text);
+            return flatten(map);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Failed when loading conf 
error:", e);
+        }
+    }
+
+    public static Map<String, String> fromHoconText(String conf) {
+        if (conf == null) {
+            throw new IllegalArgumentException("[StreamPark] fromHoconText: 
Hocon content must not be null");
+        }
+        try {
+            return parseHoconByReader(new StringReader(conf));
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading Hocon ", 
e);
+        }
+    }
+
+    public static Map<String, String> fromPropertiesText(String conf) {
+        try {
+            Properties properties = new Properties();
+            properties.load(new StringReader(conf));
+            Map<String, String> result = new HashMap<>();
+            for (String k : properties.stringPropertyNames()) {
+                result.put(k, properties.getProperty(k).trim());
+            }
+            return result;
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed when loading properties 
", e);
+        }
+    }
+
+    public static Map<String, String> fromYamlFile(String filename) {
+        Path path = toConfigPath(filename, "fromYamlFile");
+        File file = path.toFile();
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] fromYamlFile: 
Yaml file " + file + " does not exist");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("[StreamPark] fromYamlFile: 
Yaml file " + file + " is not a normal file");
+        }
+        try (InputStream inputStream = Files.newInputStream(path)) {

Review Comment:
   ## SonarCloud / I/O function calls should not be vulnerable to path 
injection attacks
   
   <!--SONAR_ISSUE_KEY:AZ8_PEvYE9D-RjRrxYQb-->Change this code to not construct 
the path from user-controlled data. <p>See more on <a 
href="https://sonarcloud.io/project/issues?id=apache_incubator-streampark&issues=AZ8_PEvYE9D-RjRrxYQb&open=AZ8_PEvYE9D-RjRrxYQb&pullRequest=4420";>SonarQube
 Cloud</a></p>
   
   [Show more 
details](https://github.com/apache/streampark/security/code-scanning/234)



##########
streampark-common/src/main/java/org/apache/streampark/common/util/FileUtils.java:
##########
@@ -0,0 +1,325 @@
+/*
+ * 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.streampark.common.util;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.Serializable;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Scanner;
+import java.util.stream.Collectors;
+
+public final class FileUtils {
+
+    private FileUtils() {}
+
+    public static File toCanonicalFile(String path) throws IOException {
+        Path normalized = Paths.get(path).normalize();
+        if (normalized.toString().contains("..")) {
+            throw new IOException("Invalid path: " + path);
+        }
+        return normalized.toFile().getCanonicalFile();
+    }
+
+    public static File resolveChildFile(File baseDir, String... childSegments) 
throws IOException {
+        Path base = baseDir.getCanonicalFile().toPath();
+        Path current = base;
+        for (String segment : childSegments) {
+            if (segment == null || segment.isEmpty() || 
segment.contains("..")) {
+                throw new IOException("Invalid path segment: " + segment);
+            }
+            current = current.resolve(segment);
+        }
+        Path resolved = current.normalize().toAbsolutePath();
+        if (!resolved.startsWith(base)) {
+            throw new IOException("Resolved path escapes base directory: " + 
resolved);
+        }
+        return resolved.toFile();
+    }
+
+    private static String bytesToHexString(byte[] src) {
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        StringBuilder stringBuilder = new StringBuilder();
+        for (byte b : src) {
+            int v = b & 0xFF;
+            String hv = Integer.toHexString(v).toUpperCase();
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    public static boolean isJarFileType(InputStream input) {
+        if (input == null) {
+            throw new RuntimeException("The inputStream can not be null");
+        }
+        return AutoCloseUtils.using(
+                        input,
+                        in -> {
+                            byte[] b = new byte[4];
+                            try {
+                                in.read(b, 0, b.length);
+                            } catch (IOException e) {
+                                throw new RuntimeException(e);
+                            }
+                            return bytesToHexString(b);
+                        })
+                .equals("504B0304");
+    }
+
+    public static boolean isJarFileType(File file) throws IOException {
+        if (!file.exists() || !file.isFile()) {
+            throw new RuntimeException("The file does not exist or the path is 
a directory");
+        }
+        return isJarFileType(new FileInputStream(file));
+    }
+
+    public static File createTempDir() {
+        final int TEMP_DIR_ATTEMPTS = 10000;
+        File baseDir = new File(System.getProperty("java.io.tmpdir"));
+        String baseName = System.currentTimeMillis() + "-";
+        for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
+            File tempDir = new File(baseDir, baseName + counter);
+            if (tempDir.mkdir()) {
+                return tempDir;
+            }
+        }
+        throw new IllegalStateException(
+                "[StreamPark] Failed to create directory within "
+                        + TEMP_DIR_ATTEMPTS
+                        + "  attempts (tried "
+                        + baseName
+                        + " 0 to "
+                        + baseName
+                        + (TEMP_DIR_ATTEMPTS - 1)
+                        + ")");
+    }
+
+    public static void mkdir(File dir) throws IOException {
+        if (dir.exists() && !dir.isDirectory()) {
+            throw new IOException("File " + dir + " exists and is not a 
directory. Unable to create directory.");
+        } else if (!dir.mkdirs() && !dir.isDirectory()) {
+            throw new IOException("Unable to create directory " + dir);
+        }
+    }
+
+    public static String getPathFromEnv(String env) {
+        String path = System.getenv(env);
+        if (path == null) {
+            path = System.getProperty(env);
+        }
+        AssertUtils.notNull(path, "[StreamPark] FileUtils.getPathFromEnv: " + 
env + " is not set on system env");
+        File file = new File(path);
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] 
FileUtils.getPathFromEnv: " + env + " is not exist!");
+        }
+        return file.getAbsolutePath();
+    }
+
+    public static String resolvePath(String parent, String child) {
+        File file = new File(parent, child);
+        if (!file.exists()) {
+            throw new IllegalArgumentException(
+                    "[StreamPark] FileUtils.resolvePath: " + 
file.getAbsolutePath() + " is not exist!");
+        }
+        return file.getAbsolutePath();
+    }
+
+    public static String getSuffix(String filename) {
+        AssertUtils.notNull(filename);
+        return filename.substring(filename.lastIndexOf("."));
+    }
+
+    public static List<URL> listFileAsURL(String dirPath) {
+        File dir = new File(dirPath);
+        if (dir.exists() && dir.isDirectory()) {
+            File[] files = dir.listFiles();
+            if (files != null && files.length > 0) {
+                List<URL> urls = new ArrayList<>();
+                for (File f : files) {
+                    try {
+                        urls.add(f.toURI().toURL());
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                return urls;
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    public static boolean exists(Serializable file) {
+        if (file == null) {
+            return false;
+        }
+        if (file instanceof File) {
+            return ((File) file).exists();
+        }
+        return new File(file.toString()).exists();
+    }
+
+    public static boolean directoryNotBlank(Serializable file) {
+        if (file == null) {
+            return false;
+        }
+        File f = file instanceof File ? (File) file : new 
File(file.toString());
+        String[] list = f.list();
+        return f.isDirectory() && list != null && list.length > 0;
+    }
+
+    public static boolean equals(File file1, File file2) throws IOException {
+        if (file1 == null || file2 == null) {
+            return false;
+        }
+        if (!file1.exists() || !file2.exists()) {
+            return false;
+        }
+        if (file1.getAbsolutePath().equals(file2.getAbsolutePath())) {
+            return true;
+        }
+        BufferedInputStream first = new BufferedInputStream(new 
FileInputStream(file1));
+        BufferedInputStream second = new BufferedInputStream(new 
FileInputStream(file2));
+        if (first.available() != second.available()) {
+            Utils.close(first, second);
+            return false;
+        }
+        while (true) {
+            int firRead = first.read();
+            int secRead = second.read();
+            if (firRead != secRead) {
+                Utils.close(first, second);
+                return false;
+            }
+            if (firRead == -1) {
+                Utils.close(first, second);
+                return true;
+            }
+        }
+    }
+
+    public static void readInputStream(InputStream in, byte[] array) throws 
IOException {
+        try (InputStream input = in) {
+            int toRead = array.length;
+            int off = 0;
+            while (toRead > 0) {
+                int ret = input.read(array, off, toRead);
+                if (ret < 0) {
+                    throw new IOException("Bad inputStream, premature EOF");
+                }
+                toRead -= ret;
+                off += ret;
+            }
+        }
+    }
+
+    public static String readFile(File file) throws IOException {
+        Path canonicalPath = file.getCanonicalFile().toPath();
+        if (Files.size(canonicalPath) >= Integer.MAX_VALUE) {
+            throw new IOException("Too large file, unexpected!");
+        }
+        byte[] array = new byte[(int) Files.size(canonicalPath)];
+        try (InputStream is = Files.newInputStream(canonicalPath)) {

Review Comment:
   ## SonarCloud / I/O function calls should not be vulnerable to path 
injection attacks
   
   <!--SONAR_ISSUE_KEY:AZ8_PEunE9D-RjRrxYQZ-->Change this code to not construct 
the path from user-controlled data. <p>See more on <a 
href="https://sonarcloud.io/project/issues?id=apache_incubator-streampark&issues=AZ8_PEunE9D-RjRrxYQZ&open=AZ8_PEunE9D-RjRrxYQZ&pullRequest=4420";>SonarQube
 Cloud</a></p>
   
   [Show more 
details](https://github.com/apache/streampark/security/code-scanning/233)



##########
streampark-common/src/main/java/org/apache/streampark/common/util/FileUtils.java:
##########
@@ -0,0 +1,325 @@
+/*
+ * 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.streampark.common.util;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.Serializable;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Scanner;
+import java.util.stream.Collectors;
+
+public final class FileUtils {
+
+    private FileUtils() {}
+
+    public static File toCanonicalFile(String path) throws IOException {
+        Path normalized = Paths.get(path).normalize();
+        if (normalized.toString().contains("..")) {
+            throw new IOException("Invalid path: " + path);
+        }
+        return normalized.toFile().getCanonicalFile();
+    }
+
+    public static File resolveChildFile(File baseDir, String... childSegments) 
throws IOException {
+        Path base = baseDir.getCanonicalFile().toPath();
+        Path current = base;
+        for (String segment : childSegments) {
+            if (segment == null || segment.isEmpty() || 
segment.contains("..")) {
+                throw new IOException("Invalid path segment: " + segment);
+            }
+            current = current.resolve(segment);
+        }
+        Path resolved = current.normalize().toAbsolutePath();
+        if (!resolved.startsWith(base)) {
+            throw new IOException("Resolved path escapes base directory: " + 
resolved);
+        }
+        return resolved.toFile();
+    }
+
+    private static String bytesToHexString(byte[] src) {
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        StringBuilder stringBuilder = new StringBuilder();
+        for (byte b : src) {
+            int v = b & 0xFF;
+            String hv = Integer.toHexString(v).toUpperCase();
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    public static boolean isJarFileType(InputStream input) {
+        if (input == null) {
+            throw new RuntimeException("The inputStream can not be null");
+        }
+        return AutoCloseUtils.using(
+                        input,
+                        in -> {
+                            byte[] b = new byte[4];
+                            try {
+                                in.read(b, 0, b.length);
+                            } catch (IOException e) {
+                                throw new RuntimeException(e);
+                            }
+                            return bytesToHexString(b);
+                        })
+                .equals("504B0304");
+    }
+
+    public static boolean isJarFileType(File file) throws IOException {
+        if (!file.exists() || !file.isFile()) {
+            throw new RuntimeException("The file does not exist or the path is 
a directory");
+        }
+        return isJarFileType(new FileInputStream(file));
+    }
+
+    public static File createTempDir() {
+        final int TEMP_DIR_ATTEMPTS = 10000;
+        File baseDir = new File(System.getProperty("java.io.tmpdir"));
+        String baseName = System.currentTimeMillis() + "-";
+        for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
+            File tempDir = new File(baseDir, baseName + counter);
+            if (tempDir.mkdir()) {
+                return tempDir;
+            }
+        }
+        throw new IllegalStateException(
+                "[StreamPark] Failed to create directory within "
+                        + TEMP_DIR_ATTEMPTS
+                        + "  attempts (tried "
+                        + baseName
+                        + " 0 to "
+                        + baseName
+                        + (TEMP_DIR_ATTEMPTS - 1)
+                        + ")");
+    }
+
+    public static void mkdir(File dir) throws IOException {
+        if (dir.exists() && !dir.isDirectory()) {
+            throw new IOException("File " + dir + " exists and is not a 
directory. Unable to create directory.");
+        } else if (!dir.mkdirs() && !dir.isDirectory()) {
+            throw new IOException("Unable to create directory " + dir);
+        }
+    }
+
+    public static String getPathFromEnv(String env) {
+        String path = System.getenv(env);
+        if (path == null) {
+            path = System.getProperty(env);
+        }
+        AssertUtils.notNull(path, "[StreamPark] FileUtils.getPathFromEnv: " + 
env + " is not set on system env");
+        File file = new File(path);
+        if (!file.exists()) {
+            throw new IllegalArgumentException("[StreamPark] 
FileUtils.getPathFromEnv: " + env + " is not exist!");
+        }
+        return file.getAbsolutePath();
+    }
+
+    public static String resolvePath(String parent, String child) {
+        File file = new File(parent, child);
+        if (!file.exists()) {
+            throw new IllegalArgumentException(
+                    "[StreamPark] FileUtils.resolvePath: " + 
file.getAbsolutePath() + " is not exist!");
+        }
+        return file.getAbsolutePath();
+    }
+
+    public static String getSuffix(String filename) {
+        AssertUtils.notNull(filename);
+        return filename.substring(filename.lastIndexOf("."));
+    }
+
+    public static List<URL> listFileAsURL(String dirPath) {
+        File dir = new File(dirPath);
+        if (dir.exists() && dir.isDirectory()) {
+            File[] files = dir.listFiles();
+            if (files != null && files.length > 0) {
+                List<URL> urls = new ArrayList<>();
+                for (File f : files) {
+                    try {
+                        urls.add(f.toURI().toURL());
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                return urls;
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    public static boolean exists(Serializable file) {
+        if (file == null) {
+            return false;
+        }
+        if (file instanceof File) {
+            return ((File) file).exists();
+        }
+        return new File(file.toString()).exists();
+    }
+
+    public static boolean directoryNotBlank(Serializable file) {
+        if (file == null) {
+            return false;
+        }
+        File f = file instanceof File ? (File) file : new 
File(file.toString());
+        String[] list = f.list();
+        return f.isDirectory() && list != null && list.length > 0;
+    }
+
+    public static boolean equals(File file1, File file2) throws IOException {
+        if (file1 == null || file2 == null) {
+            return false;
+        }
+        if (!file1.exists() || !file2.exists()) {
+            return false;
+        }
+        if (file1.getAbsolutePath().equals(file2.getAbsolutePath())) {
+            return true;
+        }
+        BufferedInputStream first = new BufferedInputStream(new 
FileInputStream(file1));
+        BufferedInputStream second = new BufferedInputStream(new 
FileInputStream(file2));
+        if (first.available() != second.available()) {
+            Utils.close(first, second);
+            return false;
+        }
+        while (true) {
+            int firRead = first.read();
+            int secRead = second.read();
+            if (firRead != secRead) {
+                Utils.close(first, second);
+                return false;
+            }
+            if (firRead == -1) {
+                Utils.close(first, second);
+                return true;
+            }
+        }
+    }
+
+    public static void readInputStream(InputStream in, byte[] array) throws 
IOException {
+        try (InputStream input = in) {
+            int toRead = array.length;
+            int off = 0;
+            while (toRead > 0) {
+                int ret = input.read(array, off, toRead);
+                if (ret < 0) {
+                    throw new IOException("Bad inputStream, premature EOF");
+                }
+                toRead -= ret;
+                off += ret;
+            }
+        }
+    }
+
+    public static String readFile(File file) throws IOException {
+        Path canonicalPath = file.getCanonicalFile().toPath();
+        if (Files.size(canonicalPath) >= Integer.MAX_VALUE) {
+            throw new IOException("Too large file, unexpected!");
+        }
+        byte[] array = new byte[(int) Files.size(canonicalPath)];

Review Comment:
   ## SonarCloud / Accessing files should not lead to filesystem oracle attacks
   
   <!--SONAR_ISSUE_KEY:AZ8_PEunE9D-RjRrxYQa-->Change this code to not construct 
the path from user-controlled data. <p>See more on <a 
href="https://sonarcloud.io/project/issues?id=apache_incubator-streampark&issues=AZ8_PEunE9D-RjRrxYQa&open=AZ8_PEunE9D-RjRrxYQa&pullRequest=4420";>SonarQube
 Cloud</a></p>
   
   [Show more 
details](https://github.com/apache/streampark/security/code-scanning/237)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to