mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Java: Add Guard Classes for checking OS
This commit is contained in:
14
java/ql/lib/semmle/code/java/StringCheck.qll
Normal file
14
java/ql/lib/semmle/code/java/StringCheck.qll
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about checking characterizations about strings.
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
* Holds if `ma` is a call to a method that checks a partial string match.
|
||||
*/
|
||||
predicate isStringPartialMatch(MethodAccess ma) {
|
||||
ma.getMethod().getDeclaringType() instanceof TypeString and
|
||||
ma.getMethod().getName() =
|
||||
["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
|
||||
}
|
||||
@@ -37,3 +37,12 @@ private class ApacheStrBuilderFluentMethod extends FluentMethod {
|
||||
this.getReturnType().(RefType).hasQualifiedName("org.apache.commons.lang3.text", "StrBuilder")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class ``org.apache.commons.lang.SystemUtils` or `org.apache.commons.lang3.SystemUtils`.
|
||||
*/
|
||||
class ApacheSystemUtilis extends Class {
|
||||
ApacheSystemUtilis() {
|
||||
this.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "SystemUtils")
|
||||
}
|
||||
}
|
||||
|
||||
93
java/ql/lib/semmle/code/java/os/OSCheck.qll
Normal file
93
java/ql/lib/semmle/code/java/os/OSCheck.qll
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Provides classes and predicates for guards that check for the current OS.
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.controlflow.Guards
|
||||
private import semmle.code.java.frameworks.apache.Lang
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.StringCheck
|
||||
|
||||
/**
|
||||
* A complimentatry guard that checks if the current platform is Windows.
|
||||
*/
|
||||
abstract class IsWindowsGuard extends Guard { }
|
||||
|
||||
/**
|
||||
* A complimentatry guard that checks if the current platform is unix or unix-like.
|
||||
*/
|
||||
abstract class IsUnixGuard extends Guard { }
|
||||
|
||||
/**
|
||||
* Holds when the MethodAccess is a call to check the current OS using either the upper case `osUpperCase` or lower case `osLowerCase` string constants.
|
||||
*/
|
||||
bindingset[osUpperCase, osLowerCase]
|
||||
private predicate isOsFromSystemProp(MethodAccess ma, string osUpperCase, string osLowerCase) {
|
||||
exists(MethodAccessSystemGetProperty sgpMa |
|
||||
sgpMa.hasCompileTimeConstantGetPropertyName("os.name")
|
||||
|
|
||||
DataFlow::localExprFlow(sgpMa, ma.getQualifier()) and // Call from System.getProperty to some partial match method
|
||||
ma.getAnArgument().(CompileTimeConstantExpr).getStringValue().matches(osUpperCase)
|
||||
or
|
||||
exists(MethodAccess toLowerCaseMa |
|
||||
toLowerCaseMa.getMethod() =
|
||||
any(Method m | m.getDeclaringType() instanceof TypeString and m.hasName("toLowerCase"))
|
||||
|
|
||||
DataFlow::localExprFlow(sgpMa, toLowerCaseMa.getQualifier()) and // Call from System.getProperty to toLowerCase
|
||||
DataFlow::localExprFlow(toLowerCaseMa, ma.getQualifier()) and // Call from toLowerCase to some partial match method
|
||||
ma.getAnArgument().(CompileTimeConstantExpr).getStringValue().matches(osLowerCase)
|
||||
)
|
||||
) and
|
||||
isStringPartialMatch(ma)
|
||||
}
|
||||
|
||||
private class IsWindowsFromSystemProp extends IsWindowsGuard instanceof MethodAccess {
|
||||
IsWindowsFromSystemProp() { isOsFromSystemProp(this, "Window%", "window%") }
|
||||
}
|
||||
|
||||
private class IsUnixFromSystemProp extends IsUnixGuard instanceof MethodAccess {
|
||||
IsUnixFromSystemProp() {
|
||||
isOsFromSystemProp(this, ["Mac%", "Linux%", "LINUX%"], ["mac%", "linux%"])
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isOsFromApacheCommons(FieldAccess fa, string fieldName) {
|
||||
exists(Field f | f = fa.getField() |
|
||||
f.getDeclaringType() instanceof ApacheSystemUtilis and
|
||||
f.hasName(fieldName)
|
||||
)
|
||||
}
|
||||
|
||||
private class IsWindowsFromApacheCommons extends IsWindowsGuard instanceof FieldAccess {
|
||||
IsWindowsFromApacheCommons() { isOsFromApacheCommons(this, "IS_OS_WINDOWS%") }
|
||||
}
|
||||
|
||||
private class IsUnixFromApacheCommons extends IsUnixGuard instanceof FieldAccess {
|
||||
IsUnixFromApacheCommons() { isOsFromApacheCommons(this, ["IS_OS_UNIX"]) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A guard that checks if the `java.nio.file.FileSystem` supports posix file permissions.
|
||||
* This is often used to infer if the OS is unix-based.
|
||||
* Looks for calls to `contains("poxix")` on the `supportedFileAttributeViews` method returned by `FileSystem`.
|
||||
*/
|
||||
private class IsUnixFromPosixFromFileSystem extends IsUnixGuard instanceof MethodAccess {
|
||||
IsUnixFromPosixFromFileSystem() {
|
||||
exists(Method m | m = this.getMethod() |
|
||||
m.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.getSourceDeclaration()
|
||||
.hasQualifiedName("java.util", "Set") and
|
||||
m.hasName("contains")
|
||||
) and
|
||||
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "posix" and
|
||||
exists(Method supportedFileAttribtueViewsMethod |
|
||||
supportedFileAttribtueViewsMethod.hasName("supportedFileAttributeViews") and
|
||||
supportedFileAttribtueViewsMethod.getDeclaringType() instanceof TypeFileSystem
|
||||
|
|
||||
DataFlow::localExprFlow(any(MethodAccess ma |
|
||||
ma.getMethod() = supportedFileAttribtueViewsMethod
|
||||
), super.getQualifier())
|
||||
)
|
||||
}
|
||||
}
|
||||
34
java/ql/test/library-tests/os/Test.java
Normal file
34
java/ql/test/library-tests/os/Test.java
Normal file
@@ -0,0 +1,34 @@
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class Test {
|
||||
void test() {
|
||||
if (System.getProperty("os.name").contains("Windows")) {
|
||||
|
||||
}
|
||||
|
||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||
|
||||
}
|
||||
|
||||
if (System.getProperty("os.name").contains("Linux")) {
|
||||
|
||||
}
|
||||
|
||||
if (System.getProperty("os.name").contains("Mac OS X")) {
|
||||
|
||||
}
|
||||
|
||||
if (System.getProperty("os.name").toLowerCase().contains("mac")) {
|
||||
|
||||
}
|
||||
|
||||
if (Path.of("whatever").getFileSystem().supportedFileAttributeViews().contains("posix")) {
|
||||
|
||||
}
|
||||
|
||||
if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
5
java/ql/test/library-tests/os/unix-test.expected
Normal file
5
java/ql/test/library-tests/os/unix-test.expected
Normal file
@@ -0,0 +1,5 @@
|
||||
| Test.java:14:13:14:59 | contains(...) |
|
||||
| Test.java:18:13:18:62 | contains(...) |
|
||||
| Test.java:22:13:22:71 | contains(...) |
|
||||
| Test.java:26:13:26:95 | contains(...) |
|
||||
| Test.java:30:13:30:84 | contains(...) |
|
||||
5
java/ql/test/library-tests/os/unix-test.ql
Normal file
5
java/ql/test/library-tests/os/unix-test.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import default
|
||||
import semmle.code.java.os.OSCheck
|
||||
|
||||
from IsUnixGuard isUnix
|
||||
select isUnix
|
||||
2
java/ql/test/library-tests/os/windows-test.expected
Normal file
2
java/ql/test/library-tests/os/windows-test.expected
Normal file
@@ -0,0 +1,2 @@
|
||||
| Test.java:6:13:6:61 | contains(...) |
|
||||
| Test.java:10:13:10:75 | contains(...) |
|
||||
5
java/ql/test/library-tests/os/windows-test.ql
Normal file
5
java/ql/test/library-tests/os/windows-test.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import default
|
||||
import semmle.code.java.os.OSCheck
|
||||
|
||||
from IsWindowsGuard isWindows
|
||||
select isWindows
|
||||
Reference in New Issue
Block a user