summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-03-24 03:32:36 +0100
committerSven Gothel <[email protected]>2019-03-24 03:32:36 +0100
commit4375d2824ac6ff656df184ea0c19ab781e3524e8 (patch)
tree4aba947abba2e7081a361019fbc9bd9c59b28f91
parent8409512c12e88cfad06704cf0c6d3f196dd24163 (diff)
Bug 1219, Bug 1231: Avoid deflating test-exe on Windows using java.nio.file.Files.isExecutable(Path)
Attempt to resolved virus scanner false positive detection on Windows while deflating the native code test-exe file in the temporary folder. As Julien Gouesse suggested, using Java 1.7's java.nio.file.Files.isExecutable(Path) _may_ resolve the issue, this has to be thorougly tested. This patch favors the nio's isExecutable file's ACL test over the more intrusive execution itself using a simple shell script file w/ set executable flag. Mind that previous tests allowed the shell script's execution, even if the temp folder did not allow execution of native code. We have to see how our testing results will be on this attempt.
-rwxr-xr-xmake/scripts/runtest.sh8
-rw-r--r--src/java/com/jogamp/common/util/IOUtil.java158
2 files changed, 111 insertions, 55 deletions
diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh
index 924ee93..bd8e8ae 100755
--- a/make/scripts/runtest.sh
+++ b/make/scripts/runtest.sh
@@ -61,9 +61,9 @@ X_ARGS="-Drootrel.build=$ROOTREL_BUILD -Dgluegen.root=$GLUEGEN_ROOT"
#D_ARGS="-Djogamp.debug.Lock -Djogamp.debug.Lock.TraceLock"
#D_ARGS="-Djogamp.debug.Lock.TraceLock"
#D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.IOUtil.Exe -Djogamp.debug.IOUtil.Exe.NoStream"
-#D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.IOUtil.Exe"
+D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.IOUtil.Exe"
#D_ARGS="-Djogamp.debug.ByteBufferInputStream"
-D_ARGS="-Djogamp.debug.Buffers"
+#D_ARGS="-Djogamp.debug.Buffers"
#D_ARGS="-Djogamp.debug.Bitstream"
#D_ARGS="-Djogamp.debug=all"
#D_ARGS="-Djogamp.debug.Logging"
@@ -91,7 +91,7 @@ function onetest() {
#
#onetest com.jogamp.common.GlueGenVersion 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestSystemPropsAndEnvs 2>&1 | tee -a $LOG
-#onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
+onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionNumber 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionSemantics 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestIteratorIndexCORE 2>&1 | tee -a $LOG
@@ -134,7 +134,7 @@ function onetest() {
#onetest com.jogamp.common.nio.TestBuffersFloatDoubleConversion 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestPointerBufferEndian 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestStructAccessorEndian 2>&1 | tee -a $LOG
-onetest com.jogamp.common.nio.TestByteBufferInputStream 2>&1 | tee -a $LOG
+#onetest com.jogamp.common.nio.TestByteBufferInputStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestByteBufferOutputStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestByteBufferCopyStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.os.TestElfReader01 $* 2>&1 | tee -a $LOG
diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java
index 342c557..9f95582 100644
--- a/src/java/com/jogamp/common/util/IOUtil.java
+++ b/src/java/com/jogamp/common/util/IOUtil.java
@@ -43,10 +43,13 @@ import java.io.Reader;
import java.io.SyncFailedException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.regex.Pattern;
import jogamp.common.Debug;
@@ -54,6 +57,7 @@ import jogamp.common.os.AndroidUtils;
import jogamp.common.os.PlatformPropsImpl;
import com.jogamp.common.ExceptionUtils;
+import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.net.AssetURLContext;
import com.jogamp.common.net.Uri;
import com.jogamp.common.nio.Buffers;
@@ -65,14 +69,55 @@ public class IOUtil {
private static final boolean DEBUG_EXE;
private static final boolean DEBUG_EXE_NOSTREAM;
private static final boolean DEBUG_EXE_EXISTING_FILE;
+ private static final boolean testTempDirExec;
+ private static final Method fileToPathGetter;
+ private static final Method isExecutableQuery;
+ private static final boolean useNioExecTest;
static {
- Debug.initSingleton();
- DEBUG = Debug.debug("IOUtil");
- DEBUG_EXE = PropertyAccess.isPropertyDefined("jogamp.debug.IOUtil.Exe", true);
- DEBUG_EXE_NOSTREAM = PropertyAccess.isPropertyDefined("jogamp.debug.IOUtil.Exe.NoStream", true);
- // For security reasons, we have to hardcode this, i.e. disable this manual debug feature!
- DEBUG_EXE_EXISTING_FILE = false; // PropertyAccess.isPropertyDefined("jogamp.debug.IOUtil.Exe.ExistingFile", true);
+ final boolean _props[] = { false, false, false, false, false };
+ final Method[] res = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+ @Override
+ public Method[] run() {
+ final Method[] res = new Method[] { null, null };
+ try {
+ int i=0;
+ _props[i++] = Debug.debug("IOUtil");
+ _props[i++] = PropertyAccess.isPropertyDefined("jogamp.debug.IOUtil.Exe", true);
+ _props[i++] = PropertyAccess.isPropertyDefined("jogamp.debug.IOUtil.Exe.NoStream", true);
+ // For security reasons, we have to hardcode this, i.e. disable this manual debug feature!
+ _props[i++] = false; // PropertyAccess.isPropertyDefined("jogamp.debug.IOUtil.Exe.ExistingFile", true);
+ _props[i++] = PropertyAccess.getBooleanProperty("jogamp.gluegen.TestTempDirExec", true, true);
+
+ // Java 1.7
+ i=0;
+ res[i] = File.class.getDeclaredMethod("toPath");
+ res[i++].setAccessible(true);
+ final Class<?> nioPathClz = ReflectionUtil.getClass("java.nio.file.Path", false, IOUtil.class.getClassLoader());
+ final Class<?> nioFilesClz = ReflectionUtil.getClass("java.nio.file.Files", false, IOUtil.class.getClassLoader());
+ res[i] = nioFilesClz.getDeclaredMethod("isExecutable", nioPathClz);
+ res[i++].setAccessible(true);
+ } catch (final Throwable t) {
+ if(_props[0]) {
+ ExceptionUtils.dumpThrowable("ioutil-init", t);
+ }
+ }
+ return res;
+ }
+ });
+ {
+ int i=0;
+ DEBUG = _props[i++];
+ DEBUG_EXE = _props[i++];
+ DEBUG_EXE_NOSTREAM = _props[i++];
+ DEBUG_EXE_EXISTING_FILE = _props[i++];
+ testTempDirExec = _props[i++];
+
+ i=0;
+ fileToPathGetter = res[i++];
+ isExecutableQuery = res[i++];
+ useNioExecTest = null != fileToPathGetter && null != isExecutableQuery;
+ }
}
/** Std. temporary directory property key <code>java.io.tmpdir</code>. */
@@ -83,12 +128,6 @@ public class IOUtil {
/** Subdirectory within platform's temporary root directory where all JogAmp related temp files are being stored: {@code jogamp} */
public static final String tmpSubDir = "jogamp";
- private static final String _TestTempDirExec = "jogamp.gluegen.TestTempDirExec";
- private static final boolean testTempDirExec;
- static {
- testTempDirExec = PropertyAccess.getBooleanProperty(_TestTempDirExec, true, true);
- }
-
private IOUtil() {}
/**
@@ -714,7 +753,7 @@ public class IOUtil {
private static String getExeTestFileSuffix() {
switch(PlatformPropsImpl.OS_TYPE) {
case WINDOWS:
- if( Platform.CPUFamily.X86 == PlatformPropsImpl.CPU_ARCH.family ) {
+ if( !useNioExecTest && Platform.CPUFamily.X86 == PlatformPropsImpl.CPU_ARCH.family ) {
return ".exe";
} else {
return ".bat";
@@ -728,7 +767,7 @@ public class IOUtil {
case WINDOWS:
return "echo off"+PlatformPropsImpl.NEWLINE;
default:
- return null;
+ return "#!/bin/true"+PlatformPropsImpl.NEWLINE;
}
}
private static String[] getExeTestCommandArgs(final String scriptFile) {
@@ -755,7 +794,8 @@ public class IOUtil {
private static WeakReference<byte[]> exeTestCodeRef = null;
private static void fillExeTestFile(final File exefile) throws IOException {
- if( Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE &&
+ if( !useNioExecTest &&
+ Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE &&
Platform.CPUFamily.X86 == PlatformPropsImpl.CPU_ARCH.family
) {
final byte[] exeTestCode;
@@ -912,6 +952,18 @@ public class IOUtil {
}
}
+ private static final Boolean isNioExecutableFile(final File file) {
+ if( useNioExecTest ) {
+ try {
+ return (Boolean) isExecutableQuery.invoke(null, fileToPathGetter.invoke(file));
+ } catch (final Throwable t) {
+ throw new JogampRuntimeException("error invoking Files.isExecutable(file.toPath())", t);
+ }
+ } else {
+ return null;
+ }
+ }
+
/**
* Returns true if the given {@code dir}
* <ol>
@@ -931,7 +983,7 @@ public class IOUtil {
if( !testTempDirExec ) {
if(DEBUG) {
- System.err.println("IOUtil.testDirExec: <"+dir.getAbsolutePath()+">: Disabled "+_TestTempDirExec);
+ System.err.println("IOUtil.testDirExec: <"+dir.getAbsolutePath()+">: Disabled TestTempDirExec");
}
return false;
}
@@ -959,6 +1011,7 @@ public class IOUtil {
} else {
exeTestFile = File.createTempFile("jogamp_exe_tst", getExeTestFileSuffix(), dir);
existingExe = false;
+ fillExeTestFile(exeTestFile);
}
} catch (final SecurityException se) {
throw se; // fwd Security exception
@@ -972,41 +1025,44 @@ public class IOUtil {
long t2;
int res = -1;
int exitValue = -1;
+ Boolean isNioExec = null;
if( existingExe || exeTestFile.setExecutable(true /* exec */, true /* ownerOnly */) ) {
- Process pr = null;
- try {
- if( !existingExe ) {
- fillExeTestFile(exeTestFile);
- }
- t2 = debug ? System.currentTimeMillis() : 0;
- // Using 'Process.exec(String[])' avoids StringTokenizer of 'Process.exec(String)'
- // and hence splitting up command by spaces!
- // Note: All no-exec cases throw an IOExceptions at ProcessBuilder.start(), i.e. below exec() call!
- pr = Runtime.getRuntime().exec( getExeTestCommandArgs( exeTestFile.getCanonicalPath() ), null, null );
- if( DEBUG_EXE && !DEBUG_EXE_NOSTREAM ) {
- new StreamMonitor(new InputStream[] { pr.getInputStream(), pr.getErrorStream() }, System.err, "Exe-Tst: ");
- }
- pr.waitFor();
- exitValue = pr.exitValue(); // Note: Bug 1219 Comment 50: On reporter's machine exit value 1 is being returned
- res = 0; // file has been executed
- } catch (final SecurityException se) {
- throw se; // fwd Security exception
- } catch (final Throwable t) {
- t2 = debug ? System.currentTimeMillis() : 0;
- res = -2;
- if( debug ) {
- System.err.println("IOUtil.testDirExec: <"+exeTestFile.getAbsolutePath()+">: Caught "+t.getClass().getSimpleName()+": "+t.getMessage());
- t.printStackTrace();
- }
- } finally {
- if( null != pr ) {
- // Bug 1219 Comment 58: Ensure that the launched process gets terminated!
- // This is Process implementation specific and varies on different platforms,
- // hence it may be required.
- try {
- pr.destroy();
- } catch (final Throwable t) {
- ExceptionUtils.dumpThrowable("", t);
+ t2 = debug ? System.currentTimeMillis() : 0;
+ isNioExec = isNioExecutableFile(exeTestFile);
+ if( null != isNioExec ) {
+ res = isNioExec.booleanValue() ? 0 : -1;
+ } else {
+ Process pr = null;
+ try {
+ // Using 'Process.exec(String[])' avoids StringTokenizer of 'Process.exec(String)'
+ // and hence splitting up command by spaces!
+ // Note: All no-exec cases throw an IOExceptions at ProcessBuilder.start(), i.e. below exec() call!
+ pr = Runtime.getRuntime().exec( getExeTestCommandArgs( exeTestFile.getCanonicalPath() ), null, null );
+ if( DEBUG_EXE && !DEBUG_EXE_NOSTREAM ) {
+ new StreamMonitor(new InputStream[] { pr.getInputStream(), pr.getErrorStream() }, System.err, "Exe-Tst: ");
+ }
+ pr.waitFor();
+ exitValue = pr.exitValue(); // Note: Bug 1219 Comment 50: On reporter's machine exit value 1 is being returned
+ res = 0; // file has been executed
+ } catch (final SecurityException se) {
+ throw se; // fwd Security exception
+ } catch (final Throwable t) {
+ t2 = debug ? System.currentTimeMillis() : 0;
+ res = -2;
+ if( debug ) {
+ System.err.println("IOUtil.testDirExec: <"+exeTestFile.getAbsolutePath()+">: Caught "+t.getClass().getSimpleName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ } finally {
+ if( null != pr ) {
+ // Bug 1219 Comment 58: Ensure that the launched process gets terminated!
+ // This is Process implementation specific and varies on different platforms,
+ // hence it may be required.
+ try {
+ pr.destroy();
+ } catch (final Throwable t) {
+ ExceptionUtils.dumpThrowable("", t);
+ }
}
}
}
@@ -1020,7 +1076,7 @@ public class IOUtil {
}
if( debug ) {
final long t3 = System.currentTimeMillis();
- System.err.println("IOUtil.testDirExec(): test-exe <"+exeTestFile.getAbsolutePath()+">, existingFile "+existingExe+", returned "+exitValue);
+ System.err.println("IOUtil.testDirExec(): test-exe <"+exeTestFile.getAbsolutePath()+">, existingFile "+existingExe+", isNioExec "+isNioExec+", returned "+exitValue);
System.err.println("IOUtil.testDirExec(): abs-path <"+dir.getAbsolutePath()+">: res "+res+" -> "+ok);
System.err.println("IOUtil.testDirExec(): total "+(t3-t0)+"ms, create "+(t1-t0)+"ms, fill "+(t2-t1)+"ms, execute "+(t3-t2)+"ms");
}