Note: This is the artifact of a research project designed to help static analysis developers reason about and localize the unsoundness issues of their tool.
Description
Summary
Soot does not fully model the runtime resolution and allocation chain behind URL.openConnection(), specifically the creation of protocol-specific URLStreamHandler instances and their role in producing concrete URLConnection objects.
As a result, the receiver of HttpURLConnection.disconnect() may have an empty points-to set during call graph construction. This happens because the concrete URLConnection subtype is created indirectly through reflective class loading (Class.forName(...)) on a non-constant string and subsequent native-assisted handler initialization, which is not resolved by SPARK’s default reflection and native modeling.
Consequently, virtual dispatch on the returned connection object is not resolved, leading to missing call graph edges for disconnect().
Minimal Reproduction
A minimal Java application is provided that opens an HTTP connection using URL.openConnection() and then calls disconnect() on the resulting object.
How to reproduce
Run Soot/SPARK call graph construction on the provided project using the included analysis interface script.
soot version: 4.4.1
java version: 8
Unzip the artifact. The reproducing example is located in reproducing/, and the driver script is in interface/.
attachment.zip
python analysis_interface.py \
--framework Soot \
--algorithm SPARK \
--project reproducing \
--type static \
--reproducing_test_case_path ../reproducing \
--boundary_id 1
Observed Behavior
url.openConnection() is modeled, but the returned object lacks a precise concrete type
- The intermediate
URLStreamHandler resolution via Class.forName(...) with a concatenated string is not resolved by SPARK
- As a result, the allocation of
sun.net.www.protocol.http.HttpURLConnection is not propagated into the points-to set
- The receiver of
conn.disconnect() has an empty or incomplete points-to set
- The call graph does not include the edge:
sun.net.www.protocol.http.HttpURLConnection.disconnect()
- The failure occurs even though the
invokevirtual instruction is present in bytecode
Expected Behavior
For programs that use URL.openConnection():
- The analysis should model the full protocol handler resolution chain
- The
URLStreamHandler subtype should be resolved to its concrete implementation (e.g., HTTP handler)
- The resulting
URLConnection object should be assigned a concrete type (HttpURLConnection)
- Virtual dispatch on
disconnect() should be resolved
- The call graph should include:
{
"caller": "com.example.App.runConnection()V",
"callee": "sun.net.www.protocol.http.HttpURLConnection.disconnect()"
}
Notes on Implementation (inspected behavior)
From inspection of SPARK and Soot’s call graph construction:
- The receiver of
conn.disconnect() is computed from the return value of URL.openConnection()
URL.openConnection() delegates to URLStreamHandler.openConnection()
- The concrete handler class is instantiated via
Class.forName(...) inside URL.getURLStreamHandler()
- SPARK’s default reflection model only resolves
Class.forName() when the argument is a constant string
- In this case, the handler class name is constructed dynamically (concatenation), so no resolution occurs
- As a result, the concrete handler (
sun.net.www.protocol.http.Handler) is never added to the points-to set
- Consequently, the allocation of
HttpURLConnection inside the handler is not propagated
- The virtual call resolution for
disconnect() fails due to an empty receiver set
Relevant components:
OnFlyCallGraphBuilder.java
NativeMethodDriver.java
virtualedges.xml
- SPARK reflection handling for
Class.forName
The root issue is incomplete modeling of the JDK’s dynamic protocol handler mechanism, specifically the reflection-based loading of URLStreamHandler implementations and their influence on object allocation propagation.
Impact
If this limitation is unintended, it significantly affects precision of call graph construction in network-heavy Java applications.
The URL.openConnection() pattern is widely used in HTTP clients, SDKs, and enterprise systems. Missing its modeling leads to:
- Loss of virtual dispatch resolution for
URLConnection implementations
- Incomplete call graphs for networking libraries
- Under-approximation of API usage in security and dependency analysis
- Missing edges in widely used JDK-based communication flows
- Reduced accuracy of interprocedural analyses that depend on network behavior modeling
Overall, this results in systematic under-modeling of JDK protocol-based object creation and its downstream effects on call graph construction.
Note: This is the artifact of a research project designed to help static analysis developers reason about and localize the unsoundness issues of their tool.
Description
Summary
Soot does not fully model the runtime resolution and allocation chain behind
URL.openConnection(), specifically the creation of protocol-specificURLStreamHandlerinstances and their role in producing concreteURLConnectionobjects.As a result, the receiver of
HttpURLConnection.disconnect()may have an empty points-to set during call graph construction. This happens because the concreteURLConnectionsubtype is created indirectly through reflective class loading (Class.forName(...)) on a non-constant string and subsequent native-assisted handler initialization, which is not resolved by SPARK’s default reflection and native modeling.Consequently, virtual dispatch on the returned connection object is not resolved, leading to missing call graph edges for
disconnect().Minimal Reproduction
A minimal Java application is provided that opens an HTTP connection using
URL.openConnection()and then callsdisconnect()on the resulting object.How to reproduce
Run Soot/SPARK call graph construction on the provided project using the included analysis interface script.
soot version: 4.4.1
java version: 8
Unzip the artifact. The reproducing example is located in
reproducing/, and the driver script is ininterface/.attachment.zip
Observed Behavior
url.openConnection()is modeled, but the returned object lacks a precise concrete typeURLStreamHandlerresolution viaClass.forName(...)with a concatenated string is not resolved by SPARKsun.net.www.protocol.http.HttpURLConnectionis not propagated into the points-to setconn.disconnect()has an empty or incomplete points-to setinvokevirtualinstruction is present in bytecodeExpected Behavior
For programs that use
URL.openConnection():URLStreamHandlersubtype should be resolved to its concrete implementation (e.g., HTTP handler)URLConnectionobject should be assigned a concrete type (HttpURLConnection)disconnect()should be resolved{ "caller": "com.example.App.runConnection()V", "callee": "sun.net.www.protocol.http.HttpURLConnection.disconnect()" }Notes on Implementation (inspected behavior)
From inspection of SPARK and Soot’s call graph construction:
conn.disconnect()is computed from the return value ofURL.openConnection()URL.openConnection()delegates toURLStreamHandler.openConnection()Class.forName(...)insideURL.getURLStreamHandler()Class.forName()when the argument is a constant stringsun.net.www.protocol.http.Handler) is never added to the points-to setHttpURLConnectioninside the handler is not propagateddisconnect()fails due to an empty receiver setRelevant components:
OnFlyCallGraphBuilder.javaNativeMethodDriver.javavirtualedges.xmlClass.forNameThe root issue is incomplete modeling of the JDK’s dynamic protocol handler mechanism, specifically the reflection-based loading of
URLStreamHandlerimplementations and their influence on object allocation propagation.Impact
If this limitation is unintended, it significantly affects precision of call graph construction in network-heavy Java applications.
The
URL.openConnection()pattern is widely used in HTTP clients, SDKs, and enterprise systems. Missing its modeling leads to:URLConnectionimplementationsOverall, this results in systematic under-modeling of JDK protocol-based object creation and its downstream effects on call graph construction.