-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java: Add Guard Classes for checking OS & unify System Property Access #8032
Changes from 16 commits
cd073a2
39828fd
3cdfc00
4951344
9f5022e
fd63107
5913c9a
dad9a02
82d3cd8
3c53a05
a7adbb7
85de9f3
fea5006
103c770
31527a6
7ab193d
5243fe3
523ddb7
b282c7f
5b651f2
a21992a
2a6c4e9
ecb8911
1c98642
50ff2c2
451661d
09cc8ee
b11340c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
import Member | ||
import semmle.code.java.security.ExternalProcess | ||
private import semmle.code.java.dataflow.FlowSteps | ||
|
||
// --- Standard types --- | ||
/** The class `java.lang.Object`. */ | ||
|
@@ -37,6 +38,27 @@ class StringLengthMethod extends Method { | |
StringLengthMethod() { this.hasName("length") and this.getDeclaringType() instanceof TypeString } | ||
} | ||
|
||
/** | ||
* The methods on the class `java.lang.String` that are used to perform partial matches with a specified substring or char. | ||
*/ | ||
class StringPartialMatchMethod extends Method { | ||
StringPartialMatchMethod() { | ||
this.hasName([ | ||
"contains", "startsWith", "endsWith", "matches", "indexOf", "lastIndexOf", "regionMatches" | ||
]) and | ||
this.getDeclaringType() instanceof TypeString | ||
} | ||
|
||
/** | ||
* Gets the index of the parameter that is being matched against. | ||
*/ | ||
int getMatchParameterIndex() { | ||
if this.hasName("regionMatches") | ||
then this.getParameterType(result) instanceof TypeString | ||
else result = 0 | ||
} | ||
} | ||
|
||
/** The class `java.lang.StringBuffer`. */ | ||
class TypeStringBuffer extends Class { | ||
TypeStringBuffer() { this.hasQualifiedName("java.lang", "StringBuffer") } | ||
|
@@ -228,11 +250,13 @@ class MethodSystemGetenv extends Method { | |
/** | ||
* Any method named `getProperty` on class `java.lang.System`. | ||
*/ | ||
class MethodSystemGetProperty extends Method { | ||
class MethodSystemGetProperty extends ValuePreservingMethod { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't a value-preserving method. A value-preserving method is Do you mean to say you want There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
/**
* Searches for the property with the specified key in this property list.
* If the key is not found in this property list, the default property list,
* and its defaults, recursively, are then checked. The method returns the
* default value argument if the property is not found.
*
* @param key the hashtable key.
* @param defaultValue a default value.
*
* @return the value in this property list with the specified key value.
* @see #setProperty
* @see #defaults
*/
public String getProperty(String key, String defaultValue) {
String val = getProperty(key);
return (val == null) ? defaultValue : val;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doh right, I'd forgotten those overloads existed. |
||
MethodSystemGetProperty() { | ||
this.hasName("getProperty") and | ||
this.getDeclaringType() instanceof TypeSystem | ||
} | ||
|
||
override predicate returnsValue(int arg) { arg = 1 } | ||
} | ||
|
||
/** | ||
|
@@ -244,6 +268,9 @@ class MethodAccessSystemGetProperty extends MethodAccess { | |
/** | ||
* Holds if this call has a compile-time constant first argument with the value `propertyName`. | ||
* For example: `System.getProperty("user.dir")`. | ||
* | ||
* Note: Better to use `semmle.code.java.environment.SystemProperty#getSystemProperty` instead | ||
* as that predicate covers more libraries' and JDK API's ways of accessing the same information | ||
JLLeitschuh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
predicate hasCompileTimeConstantGetPropertyName(string propertyName) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @smowton wondering if I should deprecate this in favor of the new way of finding all expressions that access system properties There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't deprecate since we use it ourselves, but expand your comment a little to point out that the recommended predicate covers more libraries' ways of accessing the same information. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As of my changes, it's only ever now used in my code, it isn't used anywhere else in this repository. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, at your request, I've improved my comment |
||
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = propertyName | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
import java | ||
import dataflow.DefUse | ||
private import semmle.code.java.environment.SystemProperty | ||
|
||
/** | ||
* A library method that formats a number of its arguments according to a | ||
|
@@ -312,27 +313,7 @@ private predicate formatStringValue(Expr e, string fmtvalue) { | |
or | ||
formatStringValue(e.(ChooseExpr).getAResultExpr(), fmtvalue) | ||
or | ||
exists(Method getprop, MethodAccess ma, string prop | | ||
e = ma and | ||
ma.getMethod() = getprop and | ||
getprop.hasName("getProperty") and | ||
getprop.getDeclaringType().hasQualifiedName("java.lang", "System") and | ||
getprop.getNumberOfParameters() = 1 and | ||
ma.getAnArgument().(StringLiteral).getValue() = prop and | ||
(prop = "line.separator" or prop = "file.separator" or prop = "path.separator") and | ||
fmtvalue = "x" // dummy value | ||
) | ||
or | ||
exists(Field f | | ||
e = f.getAnAccess() and | ||
f.getDeclaringType() instanceof TypeFile and | ||
fmtvalue = "x" // dummy value | ||
| | ||
f.hasName("pathSeparator") or | ||
f.hasName("pathSeparatorChar") or | ||
f.hasName("separator") or | ||
f.hasName("separatorChar") | ||
) | ||
e = getSystemProperty(["line.separator", "file.separator", "path.separator"]) and fmtvalue = "x" // dummy value | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simpler, and more comprehensive! 😄 |
||
) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import java | |
import semmle.code.java.dataflow.DataFlow | ||
import semmle.code.java.dataflow.TaintTracking | ||
import semmle.code.java.dataflow.DefUse | ||
import semmle.code.java.environment.SystemProperty | ||
import semmle.code.java.frameworks.Jdbc | ||
import semmle.code.java.frameworks.Networking | ||
import semmle.code.java.frameworks.Properties | ||
|
@@ -182,6 +183,8 @@ class EnvInput extends LocalUserInput { | |
// Results from various specific methods. | ||
this.asExpr().(MethodAccess).getMethod() instanceof EnvReadMethod | ||
or | ||
this.asExpr() = getSystemProperty(_) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Recommend removing from this PR, because this will cause FPs due to mistaking System.getProperty("line.separator") for something the user can control, and we'd want to assess the frequency of those FPs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /**
* System Property initialization for internal use only
* Retrieves the platform, JVM, and command line properties,
* applies initial defaults and returns the Properties instance
* that becomes the System.getProperties instance.
*/
public final class SystemProps {
// no instances
private SystemProps() {}
/**
* Create and initialize the system properties from the native properties
* and command line properties.
* Note: Build-defined properties such as versions and vendor information
* are initialized by VersionProps.java-template.
*
* @return a Properties instance initialized with all of the properties
*/
public static Map<String, String> initProperties() {
// Initially, cmdProperties only includes -D and props from the VM
Raw raw = new Raw();
HashMap<String, String> props = raw.cmdProperties();
String javaHome = props.get("java.home");
assert javaHome != null : "java.home not set";
putIfAbsent(props, "user.home", raw.propDefault(Raw._user_home_NDX));
putIfAbsent(props, "user.dir", raw.propDefault(Raw._user_dir_NDX));
putIfAbsent(props, "user.name", raw.propDefault(Raw._user_name_NDX));
// Platform defined encoding cannot be overridden on the command line
put(props, "sun.jnu.encoding", raw.propDefault(Raw._sun_jnu_encoding_NDX));
var nativeEncoding = ((raw.propDefault(Raw._file_encoding_NDX) == null)
? raw.propDefault(Raw._sun_jnu_encoding_NDX)
: raw.propDefault(Raw._file_encoding_NDX));
put(props, "native.encoding", nativeEncoding);
// Add properties that have not been overridden on the cmdline
putIfAbsent(props, "file.encoding", nativeEncoding);
// Use platform values if not overridden by a commandline -Dkey=value
// In no particular order
putIfAbsent(props, "os.name", raw.propDefault(Raw._os_name_NDX));
putIfAbsent(props, "os.arch", raw.propDefault(Raw._os_arch_NDX));
putIfAbsent(props, "os.version", raw.propDefault(Raw._os_version_NDX));
putIfAbsent(props, "line.separator", raw.propDefault(Raw._line_separator_NDX));
putIfAbsent(props, "file.separator", raw.propDefault(Raw._file_separator_NDX));
putIfAbsent(props, "path.separator", raw.propDefault(Raw._path_separator_NDX));
putIfAbsent(props, "java.io.tmpdir", raw.propDefault(Raw._java_io_tmpdir_NDX));
putIfAbsent(props, "http.proxyHost", raw.propDefault(Raw._http_proxyHost_NDX));
putIfAbsent(props, "http.proxyPort", raw.propDefault(Raw._http_proxyPort_NDX));
putIfAbsent(props, "https.proxyHost", raw.propDefault(Raw._https_proxyHost_NDX));
putIfAbsent(props, "https.proxyPort", raw.propDefault(Raw._https_proxyPort_NDX));
putIfAbsent(props, "ftp.proxyHost", raw.propDefault(Raw._ftp_proxyHost_NDX));
putIfAbsent(props, "ftp.proxyPort", raw.propDefault(Raw._ftp_proxyPort_NDX));
putIfAbsent(props, "socksProxyHost", raw.propDefault(Raw._socksProxyHost_NDX));
putIfAbsent(props, "socksProxyPort", raw.propDefault(Raw._socksProxyPort_NDX));
putIfAbsent(props, "http.nonProxyHosts", raw.propDefault(Raw._http_nonProxyHosts_NDX));
putIfAbsent(props, "ftp.nonProxyHosts", raw.propDefault(Raw._ftp_nonProxyHosts_NDX));
putIfAbsent(props, "socksNonProxyHosts", raw.propDefault(Raw._socksNonProxyHosts_NDX));
putIfAbsent(props, "sun.arch.abi", raw.propDefault(Raw._sun_arch_abi_NDX));
putIfAbsent(props, "sun.arch.data.model", raw.propDefault(Raw._sun_arch_data_model_NDX));
putIfAbsent(props, "sun.os.patch.level", raw.propDefault(Raw._sun_os_patch_level_NDX));
putIfAbsent(props, "sun.stdout.encoding", raw.propDefault(Raw._sun_stdout_encoding_NDX));
putIfAbsent(props, "sun.stderr.encoding", raw.propDefault(Raw._sun_stderr_encoding_NDX));
putIfAbsent(props, "sun.io.unicode.encoding", raw.propDefault(Raw._sun_io_unicode_encoding_NDX));
putIfAbsent(props, "sun.cpu.isalist", raw.propDefault(Raw._sun_cpu_isalist_NDX));
putIfAbsent(props, "sun.cpu.endian", raw.propDefault(Raw._sun_cpu_endian_NDX));
/* Construct i18n related options */
fillI18nProps(props,"user.language", raw.propDefault(Raw._display_language_NDX),
raw.propDefault(Raw._format_language_NDX));
fillI18nProps(props,"user.script", raw.propDefault(Raw._display_script_NDX),
raw.propDefault(Raw._format_script_NDX));
fillI18nProps(props,"user.country", raw.propDefault(Raw._display_country_NDX),
raw.propDefault(Raw._format_country_NDX));
fillI18nProps(props,"user.variant", raw.propDefault(Raw._display_variant_NDX),
raw.propDefault(Raw._format_variant_NDX));
return props;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's hard to say without experimenting at length, but it looks like props that come from Raw might not let the user override them? In that function at least At the very least this is surely a different PR. The scope of this one has already ballooned, let's please stop adding new tangentially related features to the same one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can do |
||
or | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Found another really good place to put my new predicate! 😄 |
||
// Access to `System.in`. | ||
exists(Field f | this.asExpr() = f.getAnAccess() | f instanceof SystemIn) | ||
or | ||
|
@@ -203,6 +206,7 @@ class EnvReadMethod extends Method { | |
EnvReadMethod() { | ||
this instanceof MethodSystemGetenv or | ||
this instanceof PropertiesGetPropertyMethod or | ||
this instanceof PropertiesGetMethod or | ||
this instanceof MethodSystemGetProperty | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
import java | ||
private import semmle.code.java.dataflow.DataFlow | ||
private import semmle.code.java.frameworks.Properties | ||
private import semmle.code.java.frameworks.apache.Lang | ||
|
||
/** | ||
* Gets an expression that retrieves the value of `propertyName` from `System.getProperty()`. | ||
*/ | ||
Expr getSystemProperty(string propertyName) { | ||
result = getSystemPropertyFromSystem(propertyName) or | ||
result = getSystemPropertyFromSystemGetProperties(propertyName) or | ||
result = getSystemPropertyFromFile(propertyName) or | ||
result = getSystemPropertyFromApacheSystemUtils(propertyName) or | ||
result = getSystemPropertyFromApacheFileUtils(propertyName) or | ||
result = getSystemPropertyFromGuava(propertyName) or | ||
result = getSystemPropertyFromOperatingSystemMXBean(propertyName) or | ||
result = getSystemPropertyFromSpringProperties(propertyName) | ||
} | ||
|
||
private MethodAccess getSystemPropertyFromSystem(string propertyName) { | ||
result.(MethodAccessSystemGetProperty).hasCompileTimeConstantGetPropertyName(propertyName) | ||
or | ||
exists(Method m | result.getMethod() = m | m.hasName("lineSeparator")) and | ||
JLLeitschuh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
propertyName = "line.separator" | ||
} | ||
|
||
/** | ||
* A method access that retrieves the value of `propertyName` from the following methods: | ||
* - `System.getProperties().getProperty(...)` | ||
* - `System.getProperties().get(...)` | ||
*/ | ||
private MethodAccess getSystemPropertyFromSystemGetProperties(string propertyName) { | ||
exists(Method getMethod | | ||
getMethod instanceof PropertiesGetMethod | ||
or | ||
getMethod instanceof PropertiesGetPropertyMethod and | ||
result.getMethod() = getMethod | ||
) and | ||
result.getArgument(0).(CompileTimeConstantExpr).getStringValue() = propertyName and | ||
DataFlow::localExprFlow(any(MethodAccess m | | ||
m.getMethod().getDeclaringType() instanceof TypeSystem and | ||
m.getMethod().hasName("getProperties") | ||
), result.getQualifier()) | ||
} | ||
|
||
private FieldAccess getSystemPropertyFromFile(string propertyName) { | ||
result.getField() instanceof FieldFileSeparator and propertyName = "file.separator" | ||
or | ||
result.getField() instanceof FieldFilePathSeparator and propertyName = "path.separator" | ||
} | ||
|
||
/** The field `java.io.File.separator` or `java.io.File.separatorChar` */ | ||
private class FieldFileSeparator extends Field { | ||
FieldFileSeparator() { | ||
this.getDeclaringType() instanceof TypeFile and this.hasName(["separator", "separatorChar"]) | ||
} | ||
} | ||
|
||
/* The field `java.io.File.pathSeparator` or `java.io.File.pathSeparatorChar` */ | ||
private class FieldFilePathSeparator extends Field { | ||
FieldFilePathSeparator() { | ||
this.getDeclaringType() instanceof TypeFile and | ||
this.hasName(["pathSeparator", "pathSeparatorChar"]) | ||
} | ||
} | ||
|
||
/** | ||
* A field access to the system property. | ||
* See: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/SystemUtils.html | ||
*/ | ||
private FieldAccess getSystemPropertyFromApacheSystemUtils(string propertyName) { | ||
exists(Field f | f = result.getField() and f.getDeclaringType() instanceof ApacheSystemUtils | | ||
f.hasName("AWT_TOOLKIT") and propertyName = "awt.toolkit" | ||
or | ||
f.hasName("FILE_ENCODING") and propertyName = "file.encoding" | ||
or | ||
f.hasName("FILE_SEPARATOR") and propertyName = "file.separator" | ||
or | ||
f.hasName("JAVA_AWT_FONTS") and propertyName = "java.awt.fonts" | ||
or | ||
f.hasName("JAVA_AWT_GRAPHICSENV") and propertyName = "java.awt.graphicsenv" | ||
or | ||
f.hasName("JAVA_AWT_HEADLESS") and propertyName = "java.awt.headless" | ||
or | ||
f.hasName("JAVA_AWT_PRINTERJOB") and propertyName = "java.awt.printerjob" | ||
or | ||
f.hasName("JAVA_CLASS_PATH") and propertyName = "java.class.path" | ||
or | ||
f.hasName("JAVA_CLASS_VERSION") and propertyName = "java.class.version" | ||
or | ||
f.hasName("JAVA_COMPILER") and propertyName = "java.compiler" | ||
or | ||
f.hasName("JAVA_EXT_DIRS") and propertyName = "java.ext.dirs" | ||
or | ||
f.hasName("JAVA_HOME") and propertyName = "java.home" | ||
or | ||
f.hasName("JAVA_IO_TMPDIR") and propertyName = "java.io.tmpdir" | ||
or | ||
f.hasName("JAVA_LIBRARY_PATH") and propertyName = "java.library.path" | ||
or | ||
f.hasName("JAVA_RUNTIME_NAME") and propertyName = "java.runtime.name" | ||
or | ||
f.hasName("JAVA_RUNTIME_VERSION") and propertyName = "java.runtime.version" | ||
or | ||
f.hasName("JAVA_SPECIFICATION_NAME") and propertyName = "java.specification.name" | ||
or | ||
f.hasName("JAVA_SPECIFICATION_VENDOR") and propertyName = "java.specification.vendor" | ||
or | ||
f.hasName("JAVA_UTIL_PREFS_PREFERENCES_FACTORY") and | ||
propertyName = "java.util.prefs.PreferencesFactory" // This really does break the lowercase convention obeyed everywhere else | ||
or | ||
f.hasName("JAVA_VENDOR") and propertyName = "java.vendor" | ||
or | ||
f.hasName("JAVA_VENDOR_URL") and propertyName = "java.vendor.url" | ||
or | ||
f.hasName("JAVA_VERSION") and propertyName = "java.version" | ||
or | ||
f.hasName("JAVA_VM_INFO") and propertyName = "java.vm.info" | ||
or | ||
f.hasName("JAVA_VM_NAME") and propertyName = "java.vm.name" | ||
or | ||
f.hasName("JAVA_VM_SPECIFICATION_NAME") and propertyName = "java.vm.specification.name" | ||
or | ||
f.hasName("JAVA_VM_SPECIFICATION_VENDOR") and propertyName = "java.vm.specification.vendor" | ||
or | ||
f.hasName("JAVA_VM_VENDOR") and propertyName = "java.vm.vendor" | ||
or | ||
f.hasName("JAVA_VM_VERSION") and propertyName = "java.vm.version" | ||
or | ||
f.hasName("LINE_SEPARATOR") and propertyName = "line.separator" | ||
or | ||
f.hasName("OS_ARCH") and propertyName = "os.arch" | ||
or | ||
f.hasName("OS_NAME") and propertyName = "os.name" | ||
or | ||
f.hasName("OS_VERSION") and propertyName = "os.version" | ||
or | ||
f.hasName("PATH_SEPARATOR") and propertyName = "path.separator" | ||
or | ||
f.hasName("USER_COUNTRY") and propertyName = "user.country" | ||
or | ||
f.hasName("USER_DIR") and propertyName = "user.dir" | ||
or | ||
f.hasName("USER_HOME") and propertyName = "user.home" | ||
or | ||
f.hasName("USER_LANGUAGE") and propertyName = "user.language" | ||
or | ||
f.hasName("USER_NAME") and propertyName = "user.name" | ||
or | ||
f.hasName("USER_TIMEZONE") and propertyName = "user.timezone" | ||
) | ||
} | ||
|
||
private MethodAccess getSystemPropertyFromApacheFileUtils(string propertyName) { | ||
exists(Method m | | ||
result.getMethod() = m and | ||
m.getDeclaringType().hasQualifiedName("org.apache.commons.io", "FileUtils") | ||
| | ||
m.hasName(["getTempDirectory", "getTempDirectoryPath"]) and propertyName = "java.io.tmpdir" | ||
or | ||
m.hasName(["getUserDirectory", "getUserDirectoryPath"]) and propertyName = "user.home" | ||
) | ||
} | ||
Comment on lines
+159
to
+168
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both
I figure that this is still fine as it's essentially equivalent to the string variant, but wrapped in a different type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it should be documented for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
private MethodAccess getSystemPropertyFromGuava(string propertyName) { | ||
exists(EnumConstant ec | | ||
ec.getDeclaringType().hasQualifiedName("com.google.common.base", "StandardSystemProperty") and | ||
result.getQualifier() = ec.getAnAccess() and | ||
result.getMethod().hasName("value") | ||
| | ||
ec.hasName("JAVA_VERSION") and propertyName = "java.version" | ||
or | ||
ec.hasName("JAVA_VENDOR") and propertyName = "java.vendor" | ||
or | ||
ec.hasName("JAVA_VENDOR_URL") and propertyName = "java.vendor.url" | ||
or | ||
ec.hasName("JAVA_HOME") and propertyName = "java.home" | ||
or | ||
ec.hasName("JAVA_VM_SPECIFICATION_VERSION") and propertyName = "java.vm.specification.version" | ||
or | ||
ec.hasName("JAVA_VM_SPECIFICATION_VENDOR") and propertyName = "java.vm.specification.vendor" | ||
or | ||
ec.hasName("JAVA_VM_SPECIFICATION_NAME") and propertyName = "java.vm.specification.name" | ||
or | ||
ec.hasName("JAVA_VM_VERSION") and propertyName = "java.vm.version" | ||
or | ||
ec.hasName("JAVA_VM_VENDOR") and propertyName = "java.vm.vendor" | ||
or | ||
ec.hasName("JAVA_VM_NAME") and propertyName = "java.vm.name" | ||
or | ||
ec.hasName("JAVA_SPECIFICATION_VERSION") and propertyName = "java.specification.version" | ||
or | ||
ec.hasName("JAVA_SPECIFICATION_VENDOR") and propertyName = "java.specification.vendor" | ||
or | ||
ec.hasName("JAVA_SPECIFICATION_NAME") and propertyName = "java.specification.name" | ||
or | ||
ec.hasName("JAVA_CLASS_VERSION") and propertyName = "java.class.version" | ||
or | ||
ec.hasName("JAVA_CLASS_PATH") and propertyName = "java.class.path" | ||
or | ||
ec.hasName("JAVA_LIBRARY_PATH") and propertyName = "java.library.path" | ||
or | ||
ec.hasName("JAVA_IO_TMPDIR") and propertyName = "java.io.tmpdir" | ||
or | ||
ec.hasName("JAVA_COMPILER") and propertyName = "java.compiler" | ||
or | ||
ec.hasName("JAVA_EXT_DIRS") and propertyName = "java.ext.dirs" | ||
or | ||
ec.hasName("OS_NAME") and propertyName = "os.name" | ||
or | ||
ec.hasName("OS_ARCH") and propertyName = "os.arch" | ||
or | ||
ec.hasName("OS_VERSION") and propertyName = "os.version" | ||
or | ||
ec.hasName("FILE_SEPARATOR") and propertyName = "file.separator" | ||
or | ||
ec.hasName("PATH_SEPARATOR") and propertyName = "path.separator" | ||
or | ||
ec.hasName("LINE_SEPARATOR") and propertyName = "line.separator" | ||
or | ||
ec.hasName("USER_NAME") and propertyName = "user.name" | ||
or | ||
ec.hasName("USER_HOME") and propertyName = "user.home" | ||
or | ||
ec.hasName("USER_DIR") and propertyName = "user.dir" | ||
) | ||
} | ||
|
||
private MethodAccess getSystemPropertyFromOperatingSystemMXBean(string propertyName) { | ||
exists(Method m | | ||
m = result.getMethod() and | ||
m.getDeclaringType().hasQualifiedName("java.lang.management", "OperatingSystemMXBean") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be good to consider subtypes as well, because there is at least There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah you are right; |
||
| | ||
m.getName() = "getName" and propertyName = "os.name" | ||
or | ||
m.getName() = "getArch" and propertyName = "os.arch" | ||
or | ||
m.getName() = "getVersion" and propertyName = "os.version" | ||
) | ||
} | ||
|
||
private MethodAccess getSystemPropertyFromSpringProperties(string propertyName) { | ||
exists(Method m | | ||
m = result.getMethod() and | ||
m.getDeclaringType().hasQualifiedName("org.springframework.core", "SpringProperties") and | ||
m.hasName("getProperty") | ||
) and | ||
result.getArgument(0).(CompileTimeConstantExpr).getStringValue() = propertyName | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume this is a pretty large import, I hope it's fine and won't break anything. Should I do this differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ok -- note that in FlowSteps.qll's
Frameworks
module you should private-import this file back. This is to ensure all queries using FlowSteps see the same set of standard value-preserving methods etc, and so the related QL can be evaluated once for the whole query suite, not re-evaluated per query as it would need to be if each one defined extra flow steps.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Thanks!