Index: chrome/browser/extensions/api/usb/usb_api.cc |
=================================================================== |
--- chrome/browser/extensions/api/usb/usb_api.cc (revision 177716) |
+++ chrome/browser/extensions/api/usb/usb_api.cc (working copy) |
@@ -62,7 +62,10 @@ |
static const char* kErrorNoDevice = "No such device."; |
static const char* kErrorPermissionDenied = |
"Permission to access device was denied"; |
+static const char* kErrorInvalidTransferLength = "Transfer length must be a " |
+ "positive number less than 104,857,600."; |
+static const size_t kMaxTransferLength = 100 * 1024 * 1024; |
static UsbDevice* device_for_test_ = NULL; |
static bool ConvertDirection(const Direction& input, |
@@ -129,7 +132,8 @@ |
static bool GetTransferSize(const T& input, size_t* output) { |
if (input.direction == usb::DIRECTION_IN) { |
const int* length = input.length.get(); |
- if (length) { |
+ if (length && *length >= 0 && |
+ static_cast<size_t>(*length) < kMaxTransferLength) { |
*output = *length; |
return true; |
} |
@@ -143,9 +147,10 @@ |
} |
template<class T> |
-static scoped_refptr<net::IOBuffer> CreateBufferForTransfer(const T& input) { |
- size_t size = 0; |
- if (!GetTransferSize(input, &size)) |
+static scoped_refptr<net::IOBuffer> CreateBufferForTransfer( |
+ const T& input, UsbDevice::TransferDirection direction, size_t size) { |
+ |
+ if (size > kMaxTransferLength) |
return NULL; |
// Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This |
@@ -153,11 +158,17 @@ |
// cannot represent a zero-length buffer, while an URB can. |
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( |
static_cast<size_t>(1), size)); |
- if (!input.data.get()) |
+ |
+ if (direction == UsbDevice::INBOUND) { |
return buffer; |
- |
- memcpy(buffer->data(), input.data->data(), size); |
- return buffer; |
+ } else if (direction == UsbDevice::OUTBOUND) { |
+ if (input.data.get() && size <= input.data->size()) { |
+ memcpy(buffer->data(), input.data->data(), size); |
+ return buffer; |
+ } |
+ } |
+ NOTREACHED(); |
+ return NULL; |
} |
static const char* ConvertTransferStatusToErrorString( |
@@ -475,8 +486,7 @@ |
UsbDevice::TransferDirection direction; |
UsbDevice::TransferRequestType request_type; |
UsbDevice::TransferRecipient recipient; |
- size_t size; |
- scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); |
+ size_t size = 0; |
if (!ConvertDirectionSafely(transfer.direction, &direction) || |
!ConvertRequestTypeSafely(transfer.request_type, &request_type) || |
@@ -485,7 +495,14 @@ |
return; |
} |
- if (!GetTransferSize(transfer, &size) || !buffer) { |
+ if (!GetTransferSize(transfer, &size)) { |
+ CompleteWithError(kErrorInvalidTransferLength); |
+ return; |
+ } |
+ |
+ scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
+ transfer, direction, size); |
+ if (!buffer) { |
CompleteWithError(kErrorMalformedParameters); |
return; |
} |
@@ -516,15 +533,21 @@ |
const GenericTransferInfo& transfer = parameters_->transfer_info; |
UsbDevice::TransferDirection direction; |
- size_t size; |
- scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); |
+ size_t size = 0; |
if (!ConvertDirectionSafely(transfer.direction, &direction)) { |
AsyncWorkCompleted(); |
return; |
} |
- if (!GetTransferSize(transfer, &size) || !buffer) { |
+ if (!GetTransferSize(transfer, &size)) { |
+ CompleteWithError(kErrorInvalidTransferLength); |
+ return; |
+ } |
+ |
+ scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
+ transfer, direction, size); |
+ if (!buffer) { |
CompleteWithError(kErrorMalformedParameters); |
return; |
} |
@@ -554,15 +577,21 @@ |
const GenericTransferInfo& transfer = parameters_->transfer_info; |
UsbDevice::TransferDirection direction; |
- size_t size; |
- scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); |
+ size_t size = 0; |
if (!ConvertDirectionSafely(transfer.direction, &direction)) { |
AsyncWorkCompleted(); |
return; |
} |
- if (!GetTransferSize(transfer, &size) || !buffer) { |
+ if (!GetTransferSize(transfer, &size)) { |
+ CompleteWithError(kErrorInvalidTransferLength); |
+ return; |
+ } |
+ |
+ scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
+ transfer, direction, size); |
+ if (!buffer) { |
CompleteWithError(kErrorMalformedParameters); |
return; |
} |
@@ -592,21 +621,26 @@ |
const IsochronousTransferInfo& transfer = parameters_->transfer_info; |
const GenericTransferInfo& generic_transfer = transfer.transfer_info; |
- size_t size; |
+ size_t size = 0; |
UsbDevice::TransferDirection direction; |
- scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
- generic_transfer); |
if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { |
AsyncWorkCompleted(); |
return; |
} |
- if (!GetTransferSize(generic_transfer, &size) || !buffer) { |
- CompleteWithError(kErrorNoDevice); |
+ if (!GetTransferSize(generic_transfer, &size)) { |
+ CompleteWithError(kErrorInvalidTransferLength); |
return; |
} |
+ scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
+ generic_transfer, direction, size); |
+ if (!buffer) { |
+ CompleteWithError(kErrorMalformedParameters); |
+ return; |
+ } |
+ |
device->device()->IsochronousTransfer(direction, generic_transfer.endpoint, |
buffer, size, transfer.packets, transfer.packet_length, 0, base::Bind( |
&UsbIsochronousTransferFunction::OnCompleted, this)); |