fix hanging of write on Windows
When using File::Write(), Var size in int64_t is casted to DWORD(unsigned long). When Var size is out of DWORD range, casted value will be zero. Before calling into File::Write() on Windows, validate the size. Bug: https://github.com/dart-lang/sdk/issues/40339 Change-Id: I36fade62dfa3025f418405cb3e45c286dd6b7db1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134440 Reviewed-by: Zach Anderson <zra@google.com> Commit-Queue: Zichang Guo <zichangguo@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
c33935faa8
commit
eb075dcc21
@@ -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<HANDLE>(_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;
|
||||
}
|
||||
|
||||
@@ -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((_) {
|
||||
|
||||
Reference in New Issue
Block a user