Skip to content

Call chain analysis exception #19637

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

Open
fraudV opened this issue Jun 1, 2025 · 0 comments
Open

Call chain analysis exception #19637

fraudV opened this issue Jun 1, 2025 · 0 comments
Labels
question Further information is requested

Comments

@fraudV
Copy link

fraudV commented Jun 1, 2025

Hello, I'm not familiar with isAdditionalFlowStep, so there might be some issues with the rule I wrote. Could you please help me take a look?

public class HashMap<K,V> extends AbstractMap<K,V>
        // 4、key
        implements Map<K,V>, Cloneable, Serializable {
    static final int hash(Object key) {
        int h;
        // 5、key.hashCode()
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    //1、s
    private void readObject(java.io.ObjectInputStream s)
            throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        reinitialize();
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new InvalidObjectException("Illegal load factor: " +
                    loadFactor);
        s.readInt();           
        int mappings = s.readInt(); 
        if (mappings < 0)
            throw new InvalidObjectException("Illegal mappings count: " +
                    mappings);
        else if (mappings > 0) {
            float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
            float fc = (float)mappings / lf + 1.0f;
            int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
                    DEFAULT_INITIAL_CAPACITY :
                    (fc >= MAXIMUM_CAPACITY) ?
                            MAXIMUM_CAPACITY :
                            tableSizeFor((int)fc));
            float ft = (float)cap * lf;
            threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
                    (int)ft : Integer.MAX_VALUE);
            @SuppressWarnings({"rawtypes","unchecked"})
            Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
            table = tab;

            for (int i = 0; i < mappings; i++) {
                @SuppressWarnings("unchecked")
                // 2、keu
                K key = (K) s.readObject();
                @SuppressWarnings("unchecked")
                V value = (V) s.readObject();
                // 3、hash(key)
                putVal(hash(key), key, value, false, false);
            }
        }
    }
}


public final class URL implements java.io.Serializable {

    transient URLStreamHandler handler;

    // 6
    public synchronized int hashCode() {
        if (hashCode != -1)
            return hashCode;

        // 7、handler.hashCode(this)
        hashCode = handler.hashCode(this);
        return hashCode;
    }
}


public abstract class URLStreamHandler {

    // 8、u
    protected int hashCode(URL u) {
        int h = 0;

        String protocol = u.getProtocol();
        if (protocol != null)
            h += protocol.hashCode();

        // 9、getHostAddress(u);
        InetAddress addr = getHostAddress(u);
        if (addr != null) {
            h += addr.hashCode();
        } else {
            String host = u.getHost();
            if (host != null)
                h += host.toLowerCase().hashCode();
        }

        String file = u.getFile();
        if (file != null)
            h += file.hashCode();

        if (u.getPort() == -1)
            h += getDefaultPort();
        else
            h += u.getPort();

        String ref = u.getRef();
        if (ref != null)
            h += ref.hashCode();

        return h;
    }
}

The path query from HashMap.readObject to HashMap.hash->h = key.hashCode() has been successfully completed.

class ReadObjectSource extends DataFlow::Node {
  ReadObjectSource() {
    exists(Method m |
       m.getDeclaringType().getASupertype() instanceof TypeSerializable and
       m.hasName("readObject") and
       m.getDeclaringType().hasQualifiedName("java.util", "HashMap") and
       this.asParameter() = m.getParameter(0)
    )
  }
}

class GetHostAddressSource extends DataFlow::Node {
  GetHostAddressSource() {
  exists(MethodCall call |
      call.getMethod().hasName("hashCode") and
      call.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Object") and
      this.asExpr() = call.getQualifier()
    )
  }
}

module LiteralToURLConfig implements DataFlow::ConfigSig {
   predicate isSource(DataFlow::Node source) {
    source instanceof ReadObjectSource
  }

  predicate isSink(DataFlow::Node sink) {
    sink instanceof GetHostAddressSource
  }
}

However, the path from HashMap.readObject to HashMap.hash->h = key.hashCode() cannot be found as shown below, and it directly jumps to the hashCode method in other classes.

class ReadObjectSource extends DataFlow::Node {
  ReadObjectSource() {
    exists(Method m |
       m.getDeclaringType().getASupertype() instanceof TypeSerializable and
       m.hasName("readObject") and
       m.getDeclaringType().hasQualifiedName("java.util", "HashMap") and
       this.asParameter() = m.getParameter(0)
    )
  }
}

class GetHostAddressSource extends DataFlow::Node {
  GetHostAddressSource() {
  exists(MethodCall call |
      call.getMethod().hasName("getHostAddress") and
      this.asExpr() = call.getArgument(0)
    )
  }
}

module LiteralToURLConfig implements DataFlow::ConfigSig {
   predicate isSource(DataFlow::Node source) {
    source instanceof ReadObjectSource
  }

  predicate isSink(DataFlow::Node sink) {
    sink instanceof GetHostAddressSource
  }

   predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink){
    source instanceof ReadObjectSource and
    exists(
      MethodCall call,
      RefType rt
    |
      source instanceof ReadObjectSource and 
      sink.asExpr() = call.getQualifier() and 
      rt = sink.getType().(RefType)
    )
   }
}

@fraudV fraudV added the question Further information is requested label Jun 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant