-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Java: Add modelling for Guava IO utilities #5310
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
Changes from all commits
d67de88
56e611f
c12f803
d30d1a2
e916e04
5278cc9
f5564b1
61dcf3a
470a2ca
3f3640f
ed228cb
bd4a414
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 |
---|---|---|
@@ -0,0 +1,2 @@ | ||
lgtm,codescanning | ||
* Increased coverage of the Guava framework by including classes in the `com.google.common.io` package. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ import java | |
import StringUtils | ||
import Collections | ||
import Preconditions | ||
import IO |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/** Definitions of taint steps in the IO package of the Guava framework */ | ||
|
||
import java | ||
private import semmle.code.java.dataflow.ExternalFlow | ||
|
||
private class GuavaIoCsv extends SummaryModelCsv { | ||
override predicate row(string row) { | ||
row = | ||
[ | ||
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", | ||
"com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;withSeparator;(String,int);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;upperCase;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;lowerCase;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;withPadChar;(char);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;omitPadding;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[-1];ReturnValue;taint", | ||
Comment on lines
+17
to
+25
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 add a comment why |
||
"com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteSource;true;concat;;;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;ByteSource;true;copyTo;(OutputStream);;Argument[-1];Argument[0];taint", | ||
"com.google.common.io;ByteSource;true;openStream;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteSource;true;read;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteSource;true;slice;(long,long);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteSource;true;wrap;(byte[]);;Argument[0];ReturnValue;taint", | ||
joefarebrother marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"com.google.common.io;ByteStreams;false;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", | ||
"com.google.common.io;ByteStreams;false;copy;(ReadablyByteChannel,WritableByteChannel);;Argument[0];Argument[1];taint", | ||
"com.google.common.io;ByteStreams;false;limit;(InputStream,long);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;ByteStreams;false;newDataInput;(ByteArrayInputStream);;Argument[0];ReturnValue;taint", | ||
joefarebrother marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"com.google.common.io;ByteStreams;false;newDataOutput;(ByteArrayOutputStream);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", | ||
"com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", | ||
"com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", | ||
"com.google.common.io;ByteStreams;false;toByteArray;(InputStream);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;asByteSource;(Charset);;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;concat;;;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;copyTo;(Appendable);;Argument[-1];Argument[0];taint", | ||
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. Should this also cover |
||
"com.google.common.io;CharSource;true;openStream;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;read;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;readFirstLine;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;readLines;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;lines;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;CharSource;true;wrap;(CharSequence);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;CharStreams;false;copy;(Readable,Appendable);;Argument[0];Argument[1];taint", | ||
"com.google.common.io;CharStreams;false;readLines;(Readable);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;CharStreams;false;toString;(Readable);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;Closer;true;register;;;Argument[0];ReturnValue;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. Should exception objects also be tracked for taint? E.g. when an exception message is created with a user-defined value and is then logged, it could allow log injection. Though in general any flow from user-defined data to an exception constructor is bad, so maybe it is not worth trying to check where the tainted exception flows afterwards? |
||
"com.google.common.io;Files;false;getFileExtension;(String);;Argument[0];ReturnValue;taint", | ||
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. Should all the methods which read or transfer the file content to in-memory structures (e.g. 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 is already a query for user controlled data flowing to a |
||
"com.google.common.io;Files;false;getNameWithoutExtension;(String);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;Files;false;simplifyPath;(String);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;MoreFiles;false;getFileExtension;(Path);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;MoreFiles;false;getNameWithoutExtension;(Path);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;LineReader;false;LineReader;(Readable);;Argument[0];ReturnValue;taint", | ||
"com.google.common.io;LineReader;true;readLine;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;toByteArray;();;Argument[-1];ReturnValue;taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;write;(byte[]);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;write;(int);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeByte;(int);;Argument[0];Argument[-1];taint", | ||
joefarebrother marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"com.google.common.io;ByteArrayDataOutput;true;writeBytes;(String);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeChar;(int);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeChars;(String);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeDouble;(double);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeFloat;(float);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeInt;(int);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeLong;(long);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeShort;(int);;Argument[0];Argument[-1];taint", | ||
"com.google.common.io;ByteArrayDataOutput;true;writeUTF;(String);;Argument[0];Argument[-1];taint" | ||
] | ||
} | ||
} | ||
|
||
private class GuavaIoSinkCsv extends SinkModelCsv { | ||
override predicate row(string row) { | ||
row = | ||
[ | ||
//"package;type;overrides;name;signature;ext;inputspec;kind", | ||
"com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream", | ||
"com.google.common.io;Resources;false;asCharSource;(URL,Charset);;Argument[0];url-open-stream", | ||
"com.google.common.io;Resources;false;copy;(URL,OutputStream);;Argument[0];url-open-stream", | ||
"com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream", | ||
"com.google.common.io;Resources;false;readLines;;;Argument[0];url-open-stream", | ||
"com.google.common.io;Resources;false;toByteArray;(URL);;Argument[0];url-open-stream", | ||
"com.google.common.io;Resources;false;toString;(URL,Charset);;Argument[0];url-open-stream" | ||
] | ||
} | ||
} |
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.
Can taint be modelled backwards?
In that case should this also match
encodingSink
andencodingStream
where the return value taints the argument?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.
There are a few special cases that model backwards taint steps, however there is no general mechanism for it, as it would likely lead to false positives from "time-travel flow", in cases like the following:
If the writes to
y
are propegated backwards tox
, then we get spurious flow to sink.So, the question of whether to include things like
encodingStream
(in general, wrappers around an output stream - of which there are several in the standard library that we don't model for simlar reasons) amounts to whether the additional effort to implement a special-case backwards flow step plus the potential for these kinds of FPs is worth the few additional results it could get; which I don't think it is.