SpotBugs Report

Project Information

Project: jsoup Java HTML Parser

SpotBugs version: 4.8.3

Code analyzed:



Metrics

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)



Contents

Summary

Warning Type Number
Bad practice Warnings 18
Correctness Warnings 2
Malicious code vulnerability Warnings 14
Performance Warnings 3
Dodgy code Warnings 8
Total 45

Warnings

Click on a warning row to see full context information.

Bad practice Warnings

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

Correctness Warnings

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)

Malicious code vulnerability Warnings

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

Performance Warnings

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

Dodgy code Warnings

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

Details

CN_IDIOM_NO_SUPER_CALL: clone method does not call super.clone()

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.

CT_CONSTRUCTOR_THROW: Be wary of letting constructors throw exceptions.

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.

DB_DUPLICATE_BRANCHES: Method uses the same code for two branches

This method uses the same code to implement two branches of a conditional branch. Check to ensure that this isn't a coding mistake.

DLS_DEAD_LOCAL_STORE: Dead store to local variable

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.

DMI_RANDOM_USED_ONLY_ONCE: Random object created and used only once

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).

EI_EXPOSE_REP: May expose internal representation by returning reference to mutable object

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.

EI_EXPOSE_REP2: May expose internal representation by incorporating reference to mutable object

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.

ES_COMPARING_STRINGS_WITH_EQ: Comparison of String objects using == or !=

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.

HE_INHERITS_EQUALS_USE_HASHCODE: Class inherits equals() and uses Object.hashCode()

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.

HSC_HUGE_SHARED_STRING_CONSTANT: Huge string constants is duplicated across multiple class files

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.

NP_NULL_PARAM_DEREF: Method call passes null for non-null parameter

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.

NS_NON_SHORT_CIRCUIT: Questionable use of non-short-circuit logic

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.

NM_CLASS_NOT_EXCEPTION: Class is not derived from an Exception, even though it is named as such

This class is not derived from another exception, but ends with 'Exception'. This will be confusing to users of this class.

RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE: Nullcheck of value previously dereferenced

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.

REC_CATCH_EXCEPTION: Exception is caught when Exception is not thrown

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 ...
}

SR_NOT_CHECKED: Method ignores results of InputStream.skip()

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.

RV_RETURN_VALUE_IGNORED_INFERRED: Method ignores return value, is this OK?

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.

SF_SWITCH_FALLTHROUGH: Switch statement found where one case falls through to the next case

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.

SIC_INNER_SHOULD_BE_STATIC: Should be a static inner class

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.

SE_BAD_FIELD: Non-transient non-serializable instance field in serializable class

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.

WMI_WRONG_MAP_ITERATOR: Inefficient use of keySet iterator instead of entrySet iterator

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.