OOZIE-3390 [Shell action] STDERR contains a bogus error message (kmarton, andras.piros)
diff --git a/core/src/test/java/org/apache/oozie/action/hadoop/TestShellContentWriter.java b/core/src/test/java/org/apache/oozie/action/hadoop/TestShellContentWriter.java
index 75a98cb..de2141a 100644
--- a/core/src/test/java/org/apache/oozie/action/hadoop/TestShellContentWriter.java
+++ b/core/src/test/java/org/apache/oozie/action/hadoop/TestShellContentWriter.java
@@ -65,6 +65,25 @@
}
@Test
+ public void testPrintShellValidShellCommand() {
+ callPrint(1, "echo");
+
+ Assert.assertTrue(String.format("output stream must be empty but is [%s]", outputStream.toString()),
+ outputStream.toString().isEmpty());
+ Assert.assertTrue(String.format("error stream must be empty but is [%s]", errorStream.toString()),
+ errorStream.toString().isEmpty());
+ }
+
+ @Test
+ public void testPrintShellInvalidShellCommand() {
+ callPrint(1, "invalid command");
+
+ Assert.assertTrue(String.format("output stream must be empty but is [%s]", outputStream.toString()),
+ outputStream.toString().isEmpty());
+ Assert.assertTrue(String.format("invalid error stream message [%s]", errorStream.toString()),
+ errorStream.toString().contains("doesn't appear to exist"));
+ }
+ @Test
public void testPrintControlCharacter() throws Exception {
writeScript("echo Hello World\011");
@@ -107,7 +126,8 @@
writeScript("");
Assert.assertTrue(outputStream.toString().isEmpty());
- Assert.assertTrue(errorStream.toString().contains("doesn't appear to exist"));
+ Assert.assertTrue(String.format("invalid error stream message [%s]", errorStream.toString()),
+ errorStream.toString().contains("doesn't appear to exist"));
}
private void writeScript(String content) throws IOException {
@@ -120,11 +140,15 @@
Files.write(scriptFile.toPath(), content.getBytes());
}
+ callPrint(maxLen, scriptFile.getAbsolutePath());
+ }
+
+ private void callPrint(final int maxLen, final String filename) {
ShellContentWriter writer = new ShellContentWriter(
maxLen,
outputStream,
errorStream,
- scriptFile.getAbsolutePath()
+ filename
);
writer.print();
diff --git a/release-log.txt b/release-log.txt
index 7d0dfe7..d9ba02c 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -1,5 +1,6 @@
-- Oozie 5.1.0 release
+OOZIE-3390 [Shell action] STDERR contains a bogus error message (kmarton, andras.piros)
OOZIE-3389 Getting input dependency list on the UI throws NPE (andras.piros via asalamon74, kmarton)
OOZIE-3386 Misleading error message when workflow application does not exist (kmarton)
OOZIE-3377 [docs] Remaining 5.1.0 documentation changes (andras.piros)
diff --git a/sharelib/oozie/pom.xml b/sharelib/oozie/pom.xml
index 70f488b..6856d70 100644
--- a/sharelib/oozie/pom.xml
+++ b/sharelib/oozie/pom.xml
@@ -72,6 +72,11 @@
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>annotations</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/sharelib/oozie/src/main/java/org/apache/oozie/action/hadoop/ShellContentWriter.java b/sharelib/oozie/src/main/java/org/apache/oozie/action/hadoop/ShellContentWriter.java
index fe833ac..0cef202 100644
--- a/sharelib/oozie/src/main/java/org/apache/oozie/action/hadoop/ShellContentWriter.java
+++ b/sharelib/oozie/src/main/java/org/apache/oozie/action/hadoop/ShellContentWriter.java
@@ -18,6 +18,7 @@
package org.apache.oozie.action.hadoop;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.io.Charsets;
import java.io.BufferedInputStream;
@@ -29,6 +30,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.concurrent.TimeUnit;
/**
* Dump the content of a shell script to output stream.
@@ -67,7 +69,7 @@
Path path = Paths.get(filename);
try {
- if (Files.exists(path)) {
+ if (isValidScript(path)) {
BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
long len = attributes.size();
if (len < maxLen) {
@@ -88,11 +90,37 @@
writeLine(errorStream, message);
}
} else {
- writeLine(errorStream, "Path " + filename + " doesn't appear to exist");
+ writeLine(errorStream, "Path " + filename + " doesn't appear to exist, not printing its content.");
}
} catch (IOException ignored) { }
}
+ @SuppressFBWarnings(value = {"COMMAND_INJECTION", "PATH_TRAVERSAL_OUT"},
+ justification = "pathToScript is specified in the WF action. It will surely be executed later on, no need to filter")
+ private boolean isValidScript(final Path pathToScript) {
+ if (Files.exists(pathToScript)) {
+ return true;
+ }
+
+ try {
+ // command -v is not present on every tested platform, using which instead
+ final Process presentOnPathProcess = new ProcessBuilder()
+ .command("which", pathToScript.toString())
+ .start();
+
+ final boolean hasFinished = presentOnPathProcess.waitFor(1, TimeUnit.SECONDS);
+ if (!hasFinished) {
+ return false;
+ }
+
+ final int exitValue = presentOnPathProcess.exitValue();
+
+ return exitValue == 0;
+ } catch (final IOException | InterruptedException | IllegalThreadStateException e) {
+ return false;
+ }
+ }
+
// Read the file into the given buffer.
// Return true if the file appears to be printable, false otherwise.
private boolean readFile(Path path, byte[] buffer) throws IOException {