[vm/io] Range check Filter_Process arguments
Add a check both in the native implementation and on the Dart side (to avoid throwing uncatchable ApiError). Simplify native implementation: Dart_ListGetAsBytes has fast path for byte sized typed data lists, so there is no reason to inline the same fast path into the caller. Reported by Kyounghwan Kim (@drg2533) TEST=runtime/tests/vm/dart/regress_b508627933_test.dart Bug: b/508627933 Change-Id: I14c0f5270f143ed2386200241b13313f6a6a6964 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/500461 Commit-Queue: Slava Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
0f9ce46c6d
commit
d2903a568c
+19
-36
@@ -167,10 +167,6 @@ void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) {
|
||||
Dart_Handle data_obj = Dart_GetNativeArgument(args, 1);
|
||||
intptr_t start = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
|
||||
intptr_t end = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
|
||||
intptr_t chunk_length = end - start;
|
||||
intptr_t length;
|
||||
Dart_TypedData_Type type;
|
||||
uint8_t* buffer = nullptr;
|
||||
|
||||
Filter* filter = nullptr;
|
||||
Dart_Handle err = GetFilter(filter_obj, &filter);
|
||||
@@ -178,39 +174,26 @@ void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) {
|
||||
Dart_PropagateError(err);
|
||||
}
|
||||
|
||||
Dart_Handle result = Dart_TypedDataAcquireData(
|
||||
data_obj, &type, reinterpret_cast<void**>(&buffer), &length);
|
||||
if (!Dart_IsError(result)) {
|
||||
ASSERT(type == Dart_TypedData_kUint8 || type == Dart_TypedData_kInt8);
|
||||
if (type != Dart_TypedData_kUint8 && type != Dart_TypedData_kInt8) {
|
||||
Dart_TypedDataReleaseData(data_obj);
|
||||
Dart_ThrowException(DartUtils::NewInternalError(
|
||||
"Invalid argument passed to Filter_Process"));
|
||||
}
|
||||
uint8_t* zlib_buffer = new uint8_t[chunk_length];
|
||||
if (zlib_buffer == nullptr) {
|
||||
Dart_TypedDataReleaseData(data_obj);
|
||||
Dart_PropagateError(Dart_NewApiError("Could not allocate zlib buffer"));
|
||||
}
|
||||
|
||||
memmove(zlib_buffer, buffer + start, chunk_length);
|
||||
Dart_TypedDataReleaseData(data_obj);
|
||||
buffer = zlib_buffer;
|
||||
} else {
|
||||
err = Dart_ListLength(data_obj, &length);
|
||||
if (Dart_IsError(err)) {
|
||||
Dart_PropagateError(err);
|
||||
}
|
||||
buffer = new uint8_t[chunk_length];
|
||||
if (buffer == nullptr) {
|
||||
Dart_PropagateError(Dart_NewApiError("Could not allocate buffer"));
|
||||
}
|
||||
err = Dart_ListGetAsBytes(data_obj, start, buffer, chunk_length);
|
||||
if (Dart_IsError(err)) {
|
||||
delete[] buffer;
|
||||
Dart_PropagateError(err);
|
||||
}
|
||||
intptr_t length;
|
||||
err = Dart_ListLength(data_obj, &length);
|
||||
if (Dart_IsError(err)) {
|
||||
Dart_PropagateError(err);
|
||||
}
|
||||
if (!(0 <= start && start <= end && end <= length)) {
|
||||
Dart_PropagateError(Dart_NewApiError("Invalid range"));
|
||||
}
|
||||
|
||||
intptr_t chunk_length = end - start;
|
||||
uint8_t* buffer = new uint8_t[chunk_length];
|
||||
if (buffer == nullptr) {
|
||||
Dart_PropagateError(Dart_NewApiError("Could not allocate buffer"));
|
||||
}
|
||||
err = Dart_ListGetAsBytes(data_obj, start, buffer, chunk_length);
|
||||
if (Dart_IsError(err)) {
|
||||
delete[] buffer;
|
||||
Dart_PropagateError(err);
|
||||
}
|
||||
|
||||
// Process will take ownership of buffer, if successful.
|
||||
if (!filter->Process(buffer, chunk_length)) {
|
||||
delete[] buffer;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2026, 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.
|
||||
|
||||
// Check that RawZLibFilter.process validates its arguments.
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
void main() {
|
||||
Expect.throwsRangeError(
|
||||
() => RawZLibFilter.deflateFilter().process([1, 2, 3], -1, 0),
|
||||
);
|
||||
Expect.throwsRangeError(
|
||||
() => RawZLibFilter.deflateFilter().process([1, 2, 3], -2, -1),
|
||||
);
|
||||
Expect.throwsRangeError(
|
||||
() => RawZLibFilter.deflateFilter().process([1, 2, 3], 0, -1),
|
||||
);
|
||||
Expect.throwsRangeError(
|
||||
() => RawZLibFilter.deflateFilter().process([1, 2, 3], 4, 2),
|
||||
);
|
||||
Expect.throwsRangeError(
|
||||
() => RawZLibFilter.deflateFilter().process([1, 2, 3], 2, 4),
|
||||
);
|
||||
Expect.throwsRangeError(
|
||||
() => RawZLibFilter.deflateFilter().process([1, 2, 3], 5, 6),
|
||||
);
|
||||
}
|
||||
@@ -7,7 +7,12 @@ part of "common_patch.dart";
|
||||
base class _FilterImpl extends NativeFieldWrapperClass1
|
||||
implements RawZLibFilter {
|
||||
@pragma("vm:external-name", "Filter_Process")
|
||||
external void process(List<int> data, int start, int end);
|
||||
external void _process(List<int> data, int start, int end);
|
||||
|
||||
void process(List<int> data, int start, int end) {
|
||||
RangeError.checkValidRange(start, end, data.length);
|
||||
_process(data, start, end);
|
||||
}
|
||||
|
||||
@pragma("vm:external-name", "Filter_Processed")
|
||||
external List<int>? processed({bool flush = true, bool end = false});
|
||||
|
||||
Reference in New Issue
Block a user