Version 1.7.0-dev.4.3

svn merge -c 40811 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@40917 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 6261cf8..f11355a 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -1135,7 +1135,7 @@
     int bytesRead = 0;
     // Loop over zero, one, or two linear data ranges.
     while (bytesRead < bytes) {
-      int toRead = min(bytes, linearLength);
+      int toRead = min(bytes - bytesRead, linearLength);
       result.setRange(bytesRead,
                       bytesRead + toRead,
                       data,
diff --git a/tests/standalone/io/regress_21160_test.dart b/tests/standalone/io/regress_21160_test.dart
new file mode 100644
index 0000000..98c9b68
--- /dev/null
+++ b/tests/standalone/io/regress_21160_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "package:async_helper/async_helper.dart";
+
+import "dart:async";
+import "dart:io";
+import "dart:typed_data";
+
+// 1 MB of i%256 data.
+Uint8List DATA = new Uint8List.fromList(
+    new List.generate(1024 * 1024, (i) => i % 256));
+
+Future<SecureServerSocket> startServer() {
+  return SecureServerSocket.bind("localhost",
+                                 0,
+                                 'localhost_cert').then((server) {
+    server.listen((SecureSocket request) {
+      request.drain().then((_) {
+        request
+            ..add(DATA)
+            ..close();
+      });
+    });
+    return server;
+  });
+}
+
+void InitializeSSL() {
+  var testPkcertDatabase = Platform.script.resolve('pkcert').toFilePath();
+  SecureSocket.initialize(database: testPkcertDatabase,
+                          password: 'dartdart');
+}
+
+void main() {
+  InitializeSSL();
+
+  asyncStart();
+  startServer().then((SecureServerSocket server) {
+    RawSecureSocket.connect("localhost", server.port).then((socket) {
+      List<int> body = <int>[];
+
+      // Close our end, since we're not sending data.
+      socket.shutdown(SocketDirection.SEND);
+
+      socket.listen((RawSocketEvent event) {
+            switch (event) {
+              case RawSocketEvent.READ:
+                // NOTE: We have a very low prime number here. The internal
+                // ring buffers will not have a size of 3. This means that
+                // we'll reach the point where we would like to read 1/2 bytes
+                // at the end and then wrap around and read the next 2/1 bytes.
+                // [This will ensure we trigger the bug.]
+                body.addAll(socket.read(3));
+                break;
+              case RawSocketEvent.WRITE:
+                break;
+              case RawSocketEvent.READ_CLOSED:
+                break;
+              default: throw "Unexpected event $event";
+            }
+          },
+          onError: (e, _) {
+            Expect.fail('Unexpected error: $e');
+          },
+          onDone: () {
+            Expect.equals(body.length, DATA.length);
+            for (int i = 0; i < body.length; i++) {
+              Expect.equals(body[i], DATA[i]);
+            }
+            server.close();
+            asyncEnd();
+          });
+    });
+  });
+}
diff --git a/tools/VERSION b/tools/VERSION
index db272d8..23ddd2a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 7
 PATCH 0
 PRERELEASE 4
-PRERELEASE_PATCH 2
+PRERELEASE_PATCH 3