diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc index 48c384ae401..0d8e494ffa7 100644 --- a/runtime/bin/file_win.cc +++ b/runtime/bin/file_win.cc @@ -146,10 +146,15 @@ int64_t File::Read(void* buffer, int64_t num_bytes) { int64_t File::Write(const void* buffer, int64_t num_bytes) { int fd = handle_->fd(); - ASSERT(fd >= 0); + // TODO(zichangguo): num_bytes from signed integer to unsigned integer. + ASSERT(fd >= 0 && num_bytes >= 0); HANDLE handle = reinterpret_cast(_get_osfhandle(fd)); + // On Windows, int64_t is much larger than required size DWORD(unsigned long). + // Limit the size to be a valid DWORD(unsigned long). + COMPILE_ASSERT(sizeof(uint32_t) == sizeof(DWORD)); + DWORD bytes_to_write = num_bytes > MAXDWORD ? MAXDWORD : num_bytes; DWORD written = 0; - BOOL result = WriteFile(handle, buffer, num_bytes, &written, NULL); + BOOL result = WriteFile(handle, buffer, bytes_to_write, &written, NULL); if (!result) { return -1; } diff --git a/tests/standalone_2/io/file_write_as_test.dart b/tests/standalone_2/io/file_write_as_test.dart index ce13ebdca8c..ca1380d169c 100644 --- a/tests/standalone_2/io/file_write_as_test.dart +++ b/tests/standalone_2/io/file_write_as_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:io'; +import 'dart:typed_data'; import "package:async_helper/async_helper.dart"; import "package:expect/expect.dart"; @@ -27,6 +28,19 @@ testWriteAsStringSync(dir) { Expect.equals('$data$data', f.readAsStringSync()); } +testWriteWithLargeList(dir) { + var f; + if (Platform.isWindows) { + f = File('NUL'); + } else { + f = File('/dev/null'); + } + // 0x100000000 exceeds the maximum of unsigned long. + // This should no longer hang. + // Issue: https://github.com/dart-lang/sdk/issues/40339 + f.writeAsBytesSync(Uint8List(0x100000000)); +} + Future testWriteAsBytes(dir) { var completer = new Completer(); var f = new File('${dir.path}/bytes.txt'); @@ -73,6 +87,7 @@ main() { var tempDir = Directory.systemTemp.createTempSync('dart_file_write_as'); testWriteAsBytesSync(tempDir); testWriteAsStringSync(tempDir); + testWriteWithLargeList(tempDir); testWriteAsBytes(tempDir).then((_) { return testWriteAsString(tempDir); }).then((_) {