Project: jsoup Java HTML Parser
SpotBugs version: 4.8.3
Code analyzed:
9826 lines of code analyzed, in 253 classes, in 8 packages.
Metric | Total | Density* |
---|---|---|
High Priority Warnings | 2 | 0.20 |
Medium Priority Warnings | 43 | 4.38 |
Total Warnings | 45 | 4.58 |
(* Defects per Thousand lines of non-commenting source statements)
Warning Type | Number |
---|---|
Bad practice Warnings | 18 |
Correctness Warnings | 2 |
Malicious code vulnerability Warnings | 14 |
Performance Warnings | 3 |
Dodgy code Warnings | 8 |
Total | 45 |
Click on a warning row to see full context information.
Code | Warning |
---|---|
CN | org.jsoup.select.Elements.clone() does not call super.clone() |
CT | Exception thrown in class org.jsoup.helper.HttpConnection$Response at new org.jsoup.helper.HttpConnection$Response(HttpConnection$Response) will leave the constructor. The object under construction remains partially initialized and may be vulnerable to Finalizer attacks. |
DMI | Random object created and used only once in org.jsoup.helper.DataUtil.mimeBoundary() |
ES | Comparison of String objects using == or != in org.jsoup.nodes.Entities.appendEncoded(Appendable, Entities$EscapeMode, int) |
HE | org.jsoup.nodes.CDataNode inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.Comment inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.DataNode inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.Document inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.DocumentType inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.Element inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.FormElement inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.PseudoTextElement inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.TextNode inherits equals and uses Object.hashCode() |
HE | org.jsoup.nodes.XmlDeclaration inherits equals and uses Object.hashCode() |
Nm | Class org.jsoup.UncheckedIOException is not derived from an Exception, even though it is named as such |
RR | org.jsoup.helper.DataUtil.parseInputStream(InputStream, String, String, Parser) ignores result of java.io.InputStream.skip(long) |
RR | org.jsoup.parser.CharacterReader.bufferUp() ignores result of java.io.Reader.skip(long) |
Se | Class org.jsoup.nodes.Element$NodeList defines non-transient non-serializable instance field owner |
Code | Warning |
---|---|
NP | Null passed for non-null parameter of StringUtil.resolve(URL, String) in org.jsoup.helper.HttpConnection$Response.execute(Connection$Request, HttpConnection$Response) |
RCN | Nullcheck of Attribute.parent at line 87 of value previously dereferenced in org.jsoup.nodes.Attribute.setValue(String) |
Code | Warning |
---|---|
EI | org.jsoup.helper.HttpConnection$Request.data() may expose internal representation by returning HttpConnection$Request.data |
EI | org.jsoup.helper.HttpConnection$Request.parser() may expose internal representation by returning HttpConnection$Request.parser |
EI | org.jsoup.helper.HttpConnection$Request.proxy() may expose internal representation by returning HttpConnection$Request.proxy |
EI | org.jsoup.nodes.Element.attributes() may expose internal representation by returning Element.attributes |
EI | org.jsoup.nodes.Element.parent() may expose internal representation by returning Node.parentNode |
EI | org.jsoup.nodes.FormElement.elements() may expose internal representation by returning FormElement.elements |
EI | org.jsoup.nodes.Node.parent() may expose internal representation by returning Node.parentNode |
EI | org.jsoup.nodes.Node.parentNode() may expose internal representation by returning Node.parentNode |
EI | org.jsoup.parser.Parser.getErrors() may expose internal representation by returning Parser.errors |
EI2 | org.jsoup.helper.HttpConnection$Request.parser(Parser) may expose internal representation by storing an externally mutable object into HttpConnection$Request.parser |
EI2 | org.jsoup.helper.HttpConnection$Request.proxy(Proxy) may expose internal representation by storing an externally mutable object into HttpConnection$Request.proxy |
EI2 | new org.jsoup.helper.W3CDom$W3CBuilder(Document) may expose internal representation by storing an externally mutable object into W3CDom$W3CBuilder.doc |
EI2 | new org.jsoup.nodes.Attribute(String, String, Attributes) may expose internal representation by storing an externally mutable object into Attribute.parent |
EI2 | new org.jsoup.nodes.Element(Tag, String, Attributes) may expose internal representation by storing an externally mutable object into Element.attributes |
Code | Warning |
---|---|
HSC | org.jsoup.nodes.EntitiesData.fullPoints is initialized to a string constant 31800 characters long that is duplicated in 2 other class files |
SIC | Should org.jsoup.examples.HtmlToPlainText$FormattingVisitor be a _static_ inner class? |
WMI | org.jsoup.safety.Whitelist.removeAttributes(String, String[]) makes inefficient use of keySet iterator instead of entrySet iterator |
Code | Warning |
---|---|
DB | org.jsoup.parser.HtmlTreeBuilder.parseFragment(String, Element, String, ParseErrorList, ParseSettings) uses the same code for two branches |
DLS | Dead store to $L5 in org.jsoup.parser.HtmlTreeBuilderState$4.process(Token, HtmlTreeBuilder) |
NS | Questionable use of non-short-circuit logic in org.jsoup.helper.HttpConnection$Base.looksLikeUtf8(byte[]) |
REC | Exception is caught when Exception is not thrown in org.jsoup.helper.HttpConnection.encodeUrl(URL) |
RV | Return value of Element.appendElement(String) ignored, is this OK in org.jsoup.nodes.Document.createShell(String) |
RV | Return value of Element.appendElement(String) ignored, is this OK in org.jsoup.nodes.Document.normalise() |
RV | Return value of Element.prependElement(String) ignored, is this OK in org.jsoup.nodes.Document.normalise() |
SF | Switch statement found in org.jsoup.parser.TokeniserState$51.read(Tokeniser, CharacterReader) where one case falls through to the next case |
This non-final class defines a clone() method that does not call super.clone(). If this class ("A") is extended by a subclass ("B"), and the subclass B calls super.clone(), then it is likely that B's clone() method will return an object of type A, which violates the standard contract for clone().
If all clone() methods call super.clone(), then they are guaranteed to use Object.clone(), which always returns an object of the correct type.
Classes that throw exceptions in their constructors are vulnerable to Finalizer attacks
A finalizer attack can be prevented, by declaring the class final, using an empty finalizer declared as final, or by a clever use of a private constructor.
See SEI CERT Rule OBJ-11
for more information.
This method uses the same code to implement two branches of a conditional branch. Check to ensure that this isn't a coding mistake.
This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used.
Note that Sun's javac compiler often generates dead stores for final local variables. Because SpotBugs is a bytecode-based tool, there is no easy way to eliminate these false positives.
This code creates a java.util.Random object, uses it to generate one random number, and then discards the Random object. This produces mediocre quality random numbers and is inefficient. If possible, rewrite the code so that the Random object is created once and saved, and each time a new random number is required invoke a method on the existing Random object to obtain it.
If it is important that the generated Random numbers not be guessable, you must not create a new Random for each random number; the values are too easily guessable. You should strongly consider using a java.security.SecureRandom instead (and avoid allocating a new SecureRandom for each random number needed).
Returning a reference to a mutable object value stored in one of the object's fields exposes the internal representation of the object. If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Returning a new copy of the object is better approach in many situations.
This code stores a reference to an externally mutable object into the internal representation of the object. If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Storing a copy of the object is better approach in many situations.
This code compares java.lang.String
objects for reference
equality using the == or != operators.
Unless both strings are either constants in a source file, or have been
interned using the String.intern()
method, the same string
value may be represented by two different String objects. Consider
using the equals(Object)
method instead.
This class inherits equals(Object)
from an abstract
superclass, and hashCode()
from
java.lang.Object
(which returns
the identity hash code, an arbitrary value assigned to the object
by the VM). Therefore, the class is very likely to violate the
invariant that equal objects must have equal hashcodes.
If you don't want to define a hashCode method, and/or don't
believe the object will ever be put into a HashMap/Hashtable,
define the hashCode()
method
to throw UnsupportedOperationException
.
A large String constant is duplicated across multiple class files. This is likely because a final field is initialized to a String constant, and the Java language mandates that all references to a final field from other classes be inlined into that classfile. See JDK bug 6447475 for a description of an occurrence of this bug in the JDK and how resolving it reduced the size of the JDK by 1 megabyte.
This method call passes a null value for a non-null method parameter. Either the parameter is annotated as a parameter that should always be non-null, or analysis has shown that it will always be dereferenced.
This code seems to be using non-short-circuit logic (e.g., & or |) rather than short-circuit logic (&& or ||). Non-short-circuit logic causes both sides of the expression to be evaluated even when the result can be inferred from knowing the left-hand side. This can be less efficient and can result in errors if the left-hand side guards cases when evaluating the right-hand side can generate an error.
See the Java Language Specification for details.
This class is not derived from another exception, but ends with 'Exception'. This will be confusing to users of this class.
A value is checked here to see whether it is null, but this value cannot be null because it was previously dereferenced and if it were null a null pointer exception would have occurred at the earlier dereference. Essentially, this code and the previous dereference disagree as to whether this value is allowed to be null. Either the check is redundant or the previous dereference is erroneous.
This method uses a try-catch block that catches Exception objects, but Exception is not thrown within the try block, and RuntimeException is not explicitly caught. It is a common bug pattern to say try { ... } catch (Exception e) { something } as a shorthand for catching a number of types of exception each of whose catch blocks is identical, but this construct also accidentally catches RuntimeException as well, masking potential bugs.
A better approach is to either explicitly catch the specific exceptions that are thrown, or to explicitly catch RuntimeException exception, rethrow it, and then catch all non-Runtime Exceptions, as shown below:
try {
...
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
... deal with all non-runtime exceptions ...
}
This method ignores the return value of
java.io.InputStream.skip()
which can skip multiple bytes.
If the return value is not checked, the caller will not be able to correctly
handle the case where fewer bytes were skipped than the caller requested.
This is a particularly insidious kind of bug, because in many programs,
skips from input streams usually do skip the full amount of data requested,
causing the program to fail only sporadically. With Buffered streams, however,
skip() will only skip data in the buffer, and will routinely fail to skip the
requested number of bytes.
This code calls a method and ignores the return value. The return value
is the same type as the type the method is invoked on, and from our analysis it looks
like the return value might be important (e.g., like ignoring the
return value of String.toLowerCase()
).
We are guessing that ignoring the return value might be a bad idea just from a simple analysis of the body of the method. You can use a @CheckReturnValue annotation to instruct SpotBugs as to whether ignoring the return value of this method is important or acceptable.
Please investigate this closely to decide whether it is OK to ignore the return value.
This method contains a switch statement where one case branch will fall through to the next case. Usually you need to end this case with a break or return.
This class is an inner class, but does not use its embedded reference to the object which created it. This reference makes the instances of the class larger, and may keep the reference to the creator object alive longer than necessary. If possible, the class should be made static.
This Serializable class defines a non-primitive instance field which is neither transient,
Serializable, or java.lang.Object
, and does not appear to implement
the Externalizable
interface or the
readObject()
and writeObject()
methods.
Objects of this class will not be deserialized correctly if a non-Serializable
object is stored in this field.
This method accesses the value of a Map entry, using a key that was retrieved from a keySet iterator. It is more efficient to use an iterator on the entrySet of the map, to avoid the Map.get(key) lookup.