am 99189120: Merge "Revert "Revert "Add further handling for when a CONNECT incorrectly returns a body.""" into lollipop-mr1-cts-dev

* commit '99189120cb4444cc196251961234ed8642534644':
  Revert "Revert "Add further handling for when a CONNECT incorrectly returns a body.""
diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java
index 0961c3d..0fcc4bd 100644
--- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java
+++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java
@@ -2961,6 +2961,39 @@
   }
 
   /**
+   * Tolerate bad https proxy response when using HttpResponseCache. Android bug 6754912.
+   */
+  @Test
+  public void testConnectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() throws Exception {
+    initResponseCache();
+
+    server.useHttps(sslContext.getSocketFactory(), true);
+    // The inclusion of a body in the response to a CONNECT is key to reproducing b/6754912.
+    MockResponse
+        badProxyResponse = new MockResponse()
+        .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)
+        .clearHeaders()
+        .setBody("bogus proxy connect response content");
+
+    server.enqueue(badProxyResponse);
+    server.enqueue(new MockResponse().setBody("response"));
+
+    server.play();
+
+    URL url = new URL("https://android.com/foo");
+    client.setSslSocketFactory(sslContext.getSocketFactory());
+    client.setHostnameVerifier(new RecordingHostnameVerifier());
+
+    ProxyConfig proxyConfig = ProxyConfig.PROXY_SYSTEM_PROPERTY;
+    HttpsURLConnection connection = (HttpsURLConnection) proxyConfig.connect(server, client, url);
+    assertContent("response", connection);
+
+    RecordedRequest connect = server.takeRequest();
+    assertEquals("CONNECT android.com:443 HTTP/1.1", connect.getRequestLine());
+    assertContains(connect.getHeaders(), "Host: android.com");
+  }
+
+  /**
    * The RFC is unclear in this regard as it only specifies that this should
    * invalidate the cache entry (if any).
    */
diff --git a/okhttp/src/main/java/com/squareup/okhttp/Connection.java b/okhttp/src/main/java/com/squareup/okhttp/Connection.java
index 94527af..743c33b 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/Connection.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/Connection.java
@@ -17,10 +17,12 @@
 package com.squareup.okhttp;
 
 import com.squareup.okhttp.internal.Platform;
+import com.squareup.okhttp.internal.Util;
 import com.squareup.okhttp.internal.http.HttpAuthenticator;
 import com.squareup.okhttp.internal.http.HttpConnection;
 import com.squareup.okhttp.internal.http.HttpEngine;
 import com.squareup.okhttp.internal.http.HttpTransport;
+import com.squareup.okhttp.internal.http.OkHeaders;
 import com.squareup.okhttp.internal.http.SpdyTransport;
 import com.squareup.okhttp.internal.spdy.SpdyConnection;
 import java.io.Closeable;
@@ -29,6 +31,8 @@
 import java.net.Socket;
 import javax.net.ssl.SSLSocket;
 import okio.ByteString;
+import okio.OkBuffer;
+import okio.Source;
 
 import static java.net.HttpURLConnection.HTTP_OK;
 import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
@@ -353,12 +357,22 @@
       tunnelConnection.writeRequest(request.headers(), requestLine);
       tunnelConnection.flush();
       Response response = tunnelConnection.readResponse().request(request).build();
-      tunnelConnection.emptyResponseBody();
+      // The response body from a CONNECT should be empty, but if it is not then we should consume
+      // it before proceeding.
+      long contentLength = OkHeaders.contentLength(response);
+      if (contentLength != -1) {
+        Source body = tunnelConnection.newFixedLengthSource(null, contentLength);
+        Util.skipAll(body, Integer.MAX_VALUE);
+      } else {
+        tunnelConnection.emptyResponseBody();
+      }
 
       switch (response.code()) {
         case HTTP_OK:
           // Assume the server won't send a TLS ServerHello until we send a TLS ClientHello. If that
           // happens, then we will have buffered bytes that are needed by the SSLSocket!
+          // This check is imperfect: it doesn't tell us whether a handshake will succeed, just that
+          // it will almost certainly fail because the proxy has sent unexpected data.
           if (tunnelConnection.bufferSize() > 0) {
             throw new IOException("TLS tunnel buffered too many bytes!");
           }