Avoid crashing when downloading MitM'd PAC that is too big am: 7d2198b586 am: 9c1cb7a273 am: 6634e90ad7
am: 66ee2296a9

Change-Id: Ib0023b44e521b936ab2f9450ad367b1feda64492
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index fa6bac8..58c76ec 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -27,6 +27,7 @@
 import android.net.ProxyInfo;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -39,10 +40,10 @@
 import com.android.net.IProxyCallback;
 import com.android.net.IProxyPortListener;
 import com.android.net.IProxyService;
-import com.android.server.IoThread;
 
 import libcore.io.Streams;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.URL;
 import java.net.URLConnection;
@@ -66,6 +67,7 @@
     private static final int DELAY_1 = 0;
     private static final int DELAY_4 = 3;
     private static final int DELAY_LONG = 4;
+    private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
 
     /** Keep these values up-to-date with ProxyService.java */
     public static final String KEY_PROXY = "keyProxy";
@@ -123,15 +125,21 @@
         }
     };
 
+    private final HandlerThread mNetThread = new HandlerThread("android.pacmanager",
+            android.os.Process.THREAD_PRIORITY_DEFAULT);
+    private final Handler mNetThreadHandler;
+
     class PacRefreshIntentReceiver extends BroadcastReceiver {
         public void onReceive(Context context, Intent intent) {
-            IoThread.getHandler().post(mPacDownloader);
+            mNetThreadHandler.post(mPacDownloader);
         }
     }
 
     public PacManager(Context context, Handler handler, int proxyMessage) {
         mContext = context;
         mLastPort = -1;
+        mNetThread.start();
+        mNetThreadHandler = new Handler(mNetThread.getLooper());
 
         mPacRefreshIntent = PendingIntent.getBroadcast(
                 context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -199,7 +207,25 @@
     private static String get(Uri pacUri) throws IOException {
         URL url = new URL(pacUri.toString());
         URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
-        return new String(Streams.readFully(urlConnection.getInputStream()));
+        long contentLength = -1;
+        try {
+            contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length"));
+        } catch (NumberFormatException e) {
+            // Ignore
+        }
+        if (contentLength > MAX_PAC_SIZE) {
+            throw new IOException("PAC too big: " + contentLength + " bytes");
+        }
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int count;
+        while ((count = urlConnection.getInputStream().read(buffer)) != -1) {
+            bytes.write(buffer, 0, count);
+            if (bytes.size() > MAX_PAC_SIZE) {
+                throw new IOException("PAC too big");
+            }
+        }
+        return bytes.toString();
     }
 
     private int getNextDelay(int currentDelay) {
@@ -297,7 +323,7 @@
                         } catch (RemoteException e) {
                             Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
                         }
-                        IoThread.getHandler().post(mPacDownloader);
+                        mNetThreadHandler.post(mPacDownloader);
                     }
                 }
             }