diff --git a/external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs b/external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs new file mode 100644 index 000000000000..5907901f844e --- /dev/null +++ b/external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Win32.SafeHandles +{ + internal sealed class SafeBrotliEncoderHandle : SafeHandle + { + public SafeBrotliEncoderHandle() : base(IntPtr.Zero, true) { } + + protected override bool ReleaseHandle() + { + Interop.Brotli.BrotliEncoderDestroyInstance(handle); + return true; + } + + public override bool IsInvalid => handle == IntPtr.Zero; + } + + internal sealed class SafeBrotliDecoderHandle : SafeHandle + { + public SafeBrotliDecoderHandle() : base(IntPtr.Zero, true) { } + + protected override bool ReleaseHandle() + { + Interop.Brotli.BrotliDecoderDestroyInstance(handle); + return true; + } + + public override bool IsInvalid => handle == IntPtr.Zero; + } +} diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c b/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c index 779749bd83d8..40a42a4b5891 100644 --- a/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c +++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c @@ -74,7 +74,7 @@ BROTLI_BOOL BrotliDecoderSetParameter( } } -DLLEXPORT BrotliDecoderState* BrotliDecoderCreateInstance( +DLLEXPORT BrotliDecoderState* MonoBrotliDecoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { BrotliDecoderState* state = 0; if (!alloc_func && !free_func) { @@ -99,7 +99,7 @@ DLLEXPORT BrotliDecoderState* BrotliDecoderCreateInstance( } /* Deinitializes and frees BrotliDecoderState instance. */ -DLLEXPORT void BrotliDecoderDestroyInstance(BrotliDecoderState* state) { +DLLEXPORT void MonoBrotliDecoderDestroyInstance(BrotliDecoderState* state) { if (!state) { return; } else { @@ -2032,7 +2032,7 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands( return ProcessCommandsInternal(1, s); } -DLLEXPORT BrotliDecoderResult BrotliDecoderDecompress( +DLLEXPORT BrotliDecoderResult MonoBrotliDecoderDecompress( size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size, uint8_t* decoded_buffer) { BrotliDecoderState s; @@ -2045,7 +2045,7 @@ DLLEXPORT BrotliDecoderResult BrotliDecoderDecompress( if (!BrotliDecoderStateInit(&s, 0, 0, 0)) { return BROTLI_DECODER_RESULT_ERROR; } - result = BrotliDecoderDecompressStream( + result = MonoBrotliDecoderDecompressStream( &s, &available_in, &next_in, &available_out, &next_out, &total_out); *decoded_size = total_out; BrotliDecoderStateCleanup(&s); @@ -2066,7 +2066,7 @@ DLLEXPORT BrotliDecoderResult BrotliDecoderDecompress( buffer ahead of time - when result is "success" decoder MUST return all unused data back to input buffer; this is possible because the invariant is held on enter */ -DLLEXPORT BrotliDecoderResult BrotliDecoderDecompressStream( +DLLEXPORT BrotliDecoderResult MonoBrotliDecoderDecompressStream( BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out) { BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS; @@ -2565,7 +2565,7 @@ const uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) { *size = requested_out - available_out; } else { /* ... or stream is broken. Normally this should be caught by - BrotliDecoderDecompressStream, this is just a safeguard. */ + MonoBrotliDecoderDecompressStream, this is just a safeguard. */ if ((int)status < 0) SaveErrorCode(s, status); *size = 0; result = 0; @@ -2578,7 +2578,7 @@ BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s) { BrotliGetAvailableBits(&s->br) != 0); } -DLLEXPORT BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s) { +DLLEXPORT BROTLI_BOOL MonoBrotliDecoderIsFinished(const BrotliDecoderState* s) { return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) && !BrotliDecoderHasMoreOutput(s); } diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c b/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c index dac29a0e8a10..38b15a8d8220 100644 --- a/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c +++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c @@ -143,7 +143,7 @@ static size_t RemainingInputBlockSize(BrotliEncoderState* s) { return block_size - (size_t)delta; } -DLLEXPORT BROTLI_BOOL BrotliEncoderSetParameter( +DLLEXPORT BROTLI_BOOL MonoBrotliEncoderSetParameter( BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) { /* Changing parameters on the fly is not implemented yet. */ if (state->is_initialized_) return BROTLI_FALSE; @@ -794,7 +794,7 @@ static void BrotliEncoderInitState(BrotliEncoderState* s) { memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); } -DLLEXPORT BrotliEncoderState* BrotliEncoderCreateInstance( +DLLEXPORT BrotliEncoderState* MonoBrotliEncoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { BrotliEncoderState* state = 0; if (!alloc_func && !free_func) { @@ -828,7 +828,7 @@ static void BrotliEncoderCleanupState(BrotliEncoderState* s) { } /* Deinitializes and frees BrotliEncoderState instance. */ -DLLEXPORT void BrotliEncoderDestroyInstance(BrotliEncoderState* state) { +DLLEXPORT void MonoBrotliEncoderDestroyInstance(BrotliEncoderState* state) { if (!state) { return; } else { @@ -1468,7 +1468,7 @@ static size_t MakeUncompressedStream( return result; } -DLLEXPORT BROTLI_BOOL BrotliEncoderCompress( +DLLEXPORT BROTLI_BOOL MonoBrotliEncoderCompress( int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, const uint8_t* input_buffer, size_t* encoded_size, uint8_t* encoded_buffer) { @@ -1499,7 +1499,7 @@ DLLEXPORT BROTLI_BOOL BrotliEncoderCompress( return BROTLI_TRUE; } - s = BrotliEncoderCreateInstance(0, 0, 0); + s = MonoBrotliEncoderCreateInstance(0, 0, 0); if (!s) { return BROTLI_FALSE; } else { @@ -1509,18 +1509,18 @@ DLLEXPORT BROTLI_BOOL BrotliEncoderCompress( uint8_t* next_out = encoded_buffer; size_t total_out = 0; BROTLI_BOOL result = BROTLI_FALSE; - BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality); - BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin); - BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode); - BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size); if (lgwin > BROTLI_MAX_WINDOW_BITS) { - BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE); } - result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH, + result = MonoBrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH, &available_in, &next_in, &available_out, &next_out, &total_out); if (!BrotliEncoderIsFinished(s)) result = 0; *encoded_size = total_out; - BrotliEncoderDestroyInstance(s); + MonoBrotliEncoderDestroyInstance(s); if (!result || (max_out_size && *encoded_size > max_out_size)) { goto fallback; } @@ -1801,7 +1801,7 @@ static void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) { } } -DLLEXPORT BROTLI_BOOL BrotliEncoderCompressStream( +DLLEXPORT BROTLI_BOOL MonoBrotliEncoderCompressStream( BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in, const uint8_t** next_in, size_t* available_out,uint8_t** next_out, size_t* total_out) { @@ -1892,10 +1892,10 @@ DLLEXPORT BROTLI_BOOL BrotliEncoderCompressStream( BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s) { return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED && - !BrotliEncoderHasMoreOutput(s)); + !MonoBrotliEncoderHasMoreOutput(s)); } -DLLEXPORT BROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s) { +DLLEXPORT BROTLI_BOOL MonoBrotliEncoderHasMoreOutput(BrotliEncoderState* s) { return TO_BROTLI_BOOL(s->available_out_ != 0); } diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h index 0f5c8f9d1117..dcd393dcf378 100644 --- a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h +++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h @@ -22,14 +22,14 @@ extern "C" { /** * Opaque structure that holds decoder state. * - * Allocated and initialized with ::BrotliDecoderCreateInstance. - * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance. + * Allocated and initialized with ::MonoBrotliDecoderCreateInstance. + * Cleaned up and deallocated with ::MonoBrotliDecoderDestroyInstance. */ typedef struct BrotliDecoderStateStruct BrotliDecoderState; /** - * Result type for ::BrotliDecoderDecompress and - * ::BrotliDecoderDecompressStream functions. + * Result type for ::MonoBrotliDecoderDecompress and + * ::MonoBrotliDecoderDecompressStream functions. */ typedef enum { /** Decoding error, e.g. corrupted input or memory allocation problem. */ @@ -158,7 +158,7 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter( * Creates an instance of ::BrotliDecoderState and initializes it. * * The instance can be used once for decoding and should then be destroyed with - * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding + * ::MonoBrotliDecoderDestroyInstance, it cannot be reused for a new decoding * session. * * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the @@ -172,7 +172,7 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter( * @returns @c 0 if instance can not be allocated or initialized * @returns pointer to initialized ::BrotliDecoderState otherwise */ -BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance( +BROTLI_DEC_API BrotliDecoderState* MonoBrotliDecoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); /** @@ -180,7 +180,7 @@ BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance( * * @param state decoder instance to be cleaned up and deallocated */ -BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state); +BROTLI_DEC_API void MonoBrotliDecoderDestroyInstance(BrotliDecoderState* state); /** * Performs one-shot memory-to-memory decompression. @@ -199,7 +199,7 @@ BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state); * allocation failed, or @p decoded_buffer is not large enough; * @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise */ -BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress( +BROTLI_DEC_API BrotliDecoderResult MonoBrotliDecoderDecompress( size_t encoded_size, const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], size_t* decoded_size, @@ -243,7 +243,7 @@ BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress( * @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more * input might be consumed and no more output will be produced */ -BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream( +BROTLI_DEC_API BrotliDecoderResult MonoBrotliDecoderDecompressStream( BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out); @@ -261,7 +261,7 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput( * Acquires pointer to internal output buffer. * * This method is used to make language bindings easier and more efficient: - * -# push data to ::BrotliDecoderDecompressStream, + * -# push data to ::MonoBrotliDecoderDecompressStream, * until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported * -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific * entity @@ -308,13 +308,13 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state); * the input and produced all of the output * @returns ::BROTLI_FALSE otherwise */ -BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished( +BROTLI_DEC_API BROTLI_BOOL MonoBrotliDecoderIsFinished( const BrotliDecoderState* state); /** * Acquires a detailed error code. * - * Should be used only after ::BrotliDecoderDecompressStream returns + * Should be used only after ::MonoBrotliDecoderDecompressStream returns * ::BROTLI_DECODER_RESULT_ERROR. * * See also ::BrotliDecoderErrorString diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h index b2774cb63162..98ed9edcb54b 100644 --- a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h +++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h @@ -77,7 +77,7 @@ typedef enum BrotliEncoderOperation { * Actual flush is performed when input stream is depleted and there is enough * space in output stream. This means that client should repeat * ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and - * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired + * ::MonoBrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired * via ::BrotliEncoderTakeOutput, then operation should be repeated after * output buffer is drained. * @@ -94,7 +94,7 @@ typedef enum BrotliEncoderOperation { * Actual finalization is performed when input stream is depleted and there is * enough space in output stream. This means that client should repeat * ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and - * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired + * ::MonoBrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired * via ::BrotliEncoderTakeOutput, then operation should be repeated after * output buffer is drained. * @@ -130,7 +130,7 @@ typedef enum BrotliEncoderOperation { BROTLI_OPERATION_EMIT_METADATA = 3 } BrotliEncoderOperation; -/** Options to be used with ::BrotliEncoderSetParameter. */ +/** Options to be used with ::MonoBrotliEncoderSetParameter. */ typedef enum BrotliEncoderParameter { /** * Tune encoder for specific input. @@ -177,7 +177,7 @@ typedef enum BrotliEncoderParameter { */ BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4, /** - * Estimated total input size for all ::BrotliEncoderCompressStream calls. + * Estimated total input size for all ::MonoBrotliEncoderCompressStream calls. * * The default value is 0, which means that the total input size is unknown. */ @@ -223,8 +223,8 @@ typedef enum BrotliEncoderParameter { /** * Opaque structure that holds encoder state. * - * Allocated and initialized with ::BrotliEncoderCreateInstance. - * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance. + * Allocated and initialized with ::MonoBrotliEncoderCreateInstance. + * Cleaned up and deallocated with ::MonoBrotliEncoderDestroyInstance. */ typedef struct BrotliEncoderStateStruct BrotliEncoderState; @@ -242,7 +242,7 @@ typedef struct BrotliEncoderStateStruct BrotliEncoderState; * @warning invalid values might be accepted in case they would not break * encoding process. */ -BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter( +BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderSetParameter( BrotliEncoderState* state, BrotliEncoderParameter param, uint32_t value); /** @@ -259,7 +259,7 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter( * @returns @c 0 if instance can not be allocated or initialized * @returns pointer to initialized ::BrotliEncoderState otherwise */ -BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance( +BROTLI_ENC_API BrotliEncoderState* MonoBrotliEncoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); /** @@ -267,13 +267,13 @@ BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance( * * @param state decoder instance to be cleaned up and deallocated */ -BROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state); +BROTLI_ENC_API void MonoBrotliEncoderDestroyInstance(BrotliEncoderState* state); /** * Calculates the output size bound for the given @p input_size. * * @warning Result is only valid if quality is at least @c 2 and, in - * case ::BrotliEncoderCompressStream was used, no flushes + * case ::MonoBrotliEncoderCompressStream was used, no flushes * (::BROTLI_OPERATION_FLUSH) were performed. * * @param input_size size of projected input @@ -309,7 +309,7 @@ BROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size); * @returns ::BROTLI_FALSE if output buffer is too small * @returns ::BROTLI_TRUE otherwise */ -BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress( +BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderCompress( int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)], size_t* encoded_size, @@ -348,17 +348,17 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress( * completing the current output block, so it could be fully decoded by stream * decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH. * Under some circumstances (e.g. lack of output stream capacity) this operation - * would require several calls to ::BrotliEncoderCompressStream. The method must + * would require several calls to ::MonoBrotliEncoderCompressStream. The method must * be called again until both input stream is depleted and encoder has no more - * output (see ::BrotliEncoderHasMoreOutput) after the method is called. + * output (see ::MonoBrotliEncoderHasMoreOutput) after the method is called. * * Finishing the stream means encoding of all input passed to encoder and * adding specific "final" marks, so stream decoder could determine that stream * is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH. * Under some circumstances (e.g. lack of output stream capacity) this operation - * would require several calls to ::BrotliEncoderCompressStream. The method must + * would require several calls to ::MonoBrotliEncoderCompressStream. The method must * be called again until both input stream is depleted and encoder has no more - * output (see ::BrotliEncoderHasMoreOutput) after the method is called. + * output (see ::MonoBrotliEncoderHasMoreOutput) after the method is called. * * @warning When flushing and finishing, @p op should not change until operation * is complete; input stream should not be swapped, reduced or @@ -377,7 +377,7 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress( * @returns ::BROTLI_FALSE if there was an error * @returns ::BROTLI_TRUE otherwise */ -BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream( +BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderCompressStream( BrotliEncoderState* state, BrotliEncoderOperation op, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out); @@ -399,15 +399,15 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* state); * @returns ::BROTLI_TRUE, if encoder has some unconsumed output * @returns ::BROTLI_FALSE otherwise */ -BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput( +BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderHasMoreOutput( BrotliEncoderState* state); /** * Acquires pointer to internal output buffer. * * This method is used to make language bindings easier and more efficient: - * -# push data to ::BrotliEncoderCompressStream, - * until ::BrotliEncoderHasMoreOutput returns BROTL_TRUE + * -# push data to ::MonoBrotliEncoderCompressStream, + * until ::MonoBrotliEncoderHasMoreOutput returns BROTL_TRUE * -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific * entity * diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c b/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c index 7c678d3d8fa5..99f133010726 100644 --- a/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c +++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c @@ -909,7 +909,7 @@ static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) { return BROTLI_FALSE; } - result = BrotliDecoderDecompressStream(s, &context->available_in, + result = MonoBrotliDecoderDecompressStream(s, &context->available_in, &context->next_in, &context->available_out, &context->next_out, 0); } } @@ -917,7 +917,7 @@ static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) { static BROTLI_BOOL DecompressFiles(Context* context) { while (NextFile(context)) { BROTLI_BOOL is_ok = BROTLI_TRUE; - BrotliDecoderState* s = BrotliDecoderCreateInstance(NULL, NULL, NULL); + BrotliDecoderState* s = MonoBrotliDecoderCreateInstance(NULL, NULL, NULL); if (!s) { fprintf(stderr, "out of memory\n"); return BROTLI_FALSE; @@ -933,7 +933,7 @@ static BROTLI_BOOL DecompressFiles(Context* context) { is_ok = BROTLI_FALSE; } if (is_ok) is_ok = DecompressFile(context, s); - BrotliDecoderDestroyInstance(s); + MonoBrotliDecoderDestroyInstance(s); if (!CloseFiles(context, is_ok)) is_ok = BROTLI_FALSE; if (!is_ok) return BROTLI_FALSE; } @@ -949,7 +949,7 @@ static BROTLI_BOOL CompressFile(Context* context, BrotliEncoderState* s) { is_eof = !HasMoreInput(context); } - if (!BrotliEncoderCompressStream(s, + if (!MonoBrotliEncoderCompressStream(s, is_eof ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS, &context->available_in, &context->next_in, &context->available_out, &context->next_out, NULL)) { @@ -978,20 +978,20 @@ static BROTLI_BOOL CompressFile(Context* context, BrotliEncoderState* s) { static BROTLI_BOOL CompressFiles(Context* context) { while (NextFile(context)) { BROTLI_BOOL is_ok = BROTLI_TRUE; - BrotliEncoderState* s = BrotliEncoderCreateInstance(NULL, NULL, NULL); + BrotliEncoderState* s = MonoBrotliEncoderCreateInstance(NULL, NULL, NULL); if (!s) { fprintf(stderr, "out of memory\n"); return BROTLI_FALSE; } - BrotliEncoderSetParameter(s, + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)context->quality); if (context->lgwin > 0) { /* Specified by user. */ /* Do not enable "large-window" extension, if not required. */ if (context->lgwin > BROTLI_MAX_WINDOW_BITS) { - BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, 1u); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, 1u); } - BrotliEncoderSetParameter(s, + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)context->lgwin); } else { /* 0, or not specified by user; could be chosen by compressor. */ @@ -1005,12 +1005,12 @@ static BROTLI_BOOL CompressFiles(Context* context) { if (lgwin == BROTLI_MAX_WINDOW_BITS) break; } } - BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, lgwin); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, lgwin); } if (context->input_file_length > 0) { uint32_t size_hint = context->input_file_length < (1 << 30) ? (uint32_t)context->input_file_length : (1u << 30); - BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, size_hint); + MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, size_hint); } is_ok = OpenFiles(context); if (is_ok && !context->current_output_path && @@ -1019,7 +1019,7 @@ static BROTLI_BOOL CompressFiles(Context* context) { is_ok = BROTLI_FALSE; } if (is_ok) is_ok = CompressFile(context, s); - BrotliEncoderDestroyInstance(s); + MonoBrotliEncoderDestroyInstance(s); if (!CloseFiles(context, is_ok)) is_ok = BROTLI_FALSE; if (!is_ok) return BROTLI_FALSE; } diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/System.IO.Compression.Brotli.sln b/external/corefx-bugfix/src/System.IO.Compression.Brotli/System.IO.Compression.Brotli.sln new file mode 100644 index 000000000000..6f2cf7407668 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/System.IO.Compression.Brotli.sln @@ -0,0 +1,60 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli.Tests", "tests\System.IO.Compression.Brotli.Tests.csproj", "{BC2E1649-291D-412E-9529-EDDA94FA7AD6}" + ProjectSection(ProjectDependencies) = postProject + {5471BFE8-8071-466F-838E-5ADAA779E742} = {5471BFE8-8071-466F-838E-5ADAA779E742} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli.Performance.Tests", "tests\Performance\System.IO.Compression.Brotli.Performance.Tests.csproj", "{1341F8C8-637A-49A1-BE0F-13867A634929}" + ProjectSection(ProjectDependencies) = postProject + {5471BFE8-8071-466F-838E-5ADAA779E742} = {5471BFE8-8071-466F-838E-5ADAA779E742} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli", "src\System.IO.Compression.Brotli.csproj", "{5471BFE8-8071-466F-838E-5ADAA779E742}" + ProjectSection(ProjectDependencies) = postProject + {4ADD9456-A929-4254-B8A2-16FC628ABFDA} = {4ADD9456-A929-4254-B8A2-16FC628ABFDA} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli", "ref\System.IO.Compression.Brotli.csproj", "{4ADD9456-A929-4254-B8A2-16FC628ABFDA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1A2F9F4A-A032-433E-B914-ADD5992BB178}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E107E9C1-E893-4E87-987E-04EF0DCEAEFD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{2E666815-2EDB-464B-9DF6-380BF4789AD4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU + {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU + {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU + {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU + {1341F8C8-637A-49A1-BE0F-13867A634929}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU + {1341F8C8-637A-49A1-BE0F-13867A634929}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU + {1341F8C8-637A-49A1-BE0F-13867A634929}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU + {1341F8C8-637A-49A1-BE0F-13867A634929}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU + {5471BFE8-8071-466F-838E-5ADAA779E742}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU + {5471BFE8-8071-466F-838E-5ADAA779E742}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU + {5471BFE8-8071-466F-838E-5ADAA779E742}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU + {5471BFE8-8071-466F-838E-5ADAA779E742}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU + {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU + {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU + {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU + {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {BC2E1649-291D-412E-9529-EDDA94FA7AD6} = {1A2F9F4A-A032-433E-B914-ADD5992BB178} + {1341F8C8-637A-49A1-BE0F-13867A634929} = {1A2F9F4A-A032-433E-B914-ADD5992BB178} + {5471BFE8-8071-466F-838E-5ADAA779E742} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD} + {4ADD9456-A929-4254-B8A2-16FC628ABFDA} = {2E666815-2EDB-464B-9DF6-380BF4789AD4} + EndGlobalSection +EndGlobal diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/dir.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/dir.props new file mode 100644 index 000000000000..4d0d97a320ee --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/dir.props @@ -0,0 +1,10 @@ + + + + + 4.2.1.0 + ECMA + true + true + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/Configurations.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/Configurations.props new file mode 100644 index 000000000000..2845c11c541d --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/Configurations.props @@ -0,0 +1,8 @@ + + + + + netcoreapp; + + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.cs new file mode 100644 index 000000000000..dd1990703efa --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the http://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.IO.Compression +{ + public partial struct BrotliDecoder : System.IDisposable + { + public System.Buffers.OperationStatus Decompress(System.ReadOnlySpan source, System.Span destination, out int bytesConsumed, out int bytesWritten) { bytesConsumed = default(int); bytesWritten = default(int); throw null; } + public static bool TryDecompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { bytesWritten = default(int); throw null; } + public void Dispose() { } + } + public partial struct BrotliEncoder : System.IDisposable + { + public BrotliEncoder(int quality, int window) { } + public System.Buffers.OperationStatus Compress(System.ReadOnlySpan source, System.Span destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) { bytesConsumed = default(int); bytesWritten = default(int); throw null; } + public System.Buffers.OperationStatus Flush(System.Span destination, out int bytesWritten) { bytesWritten = default(int); throw null; } + public void Dispose() { } + public static bool TryCompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { bytesWritten = default(int); throw null; } + public static bool TryCompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten, int quality, int window) { bytesWritten = default(int); throw null; } + public static int GetMaxCompressedLength(int inputSize) { throw null; } + } + public sealed partial class BrotliStream : System.IO.Stream + { + public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionLevel compressionLevel) { } + public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionLevel compressionLevel, bool leaveOpen) { } + public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionMode mode) { } + public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionMode mode, bool leaveOpen) { } + public System.IO.Stream BaseStream { get { throw null; } } + public override bool CanRead { get { throw null; } } + public override bool CanSeek { get { throw null; } } + public override bool CanWrite { get { throw null; } } + public override long Length { get { throw null; } } + public override long Position { get { throw null; } set { } } + protected override void Dispose(bool disposing) { } + public override void Flush() { } + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; } + public override int EndRead(IAsyncResult asyncResult) { throw null; } + public override int Read(byte[] buffer, int offset, int count) { throw null; } + public override System.Threading.Tasks.Task ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; } + public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; } + public override void SetLength(long value) { } + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; } + public override void EndWrite(IAsyncResult asyncResult) { } + public override void Write(byte[] buffer, int offset, int count) { } + public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.csproj b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.csproj new file mode 100644 index 000000000000..13f4ca5a7038 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.csproj @@ -0,0 +1,21 @@ + + + + + {4ADD9456-A929-4254-B8A2-16FC628ABFDA} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Configurations.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Configurations.props new file mode 100644 index 000000000000..17d3231f8e68 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Configurations.props @@ -0,0 +1,9 @@ + + + + + netcoreapp-Unix; + netcoreapp-Windows_NT; + + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs new file mode 100644 index 000000000000..fd34431d3bd5 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; +using size_t = System.IntPtr; + +internal static partial class Interop +{ + internal static partial class Brotli + { +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderCreateInstance")] +#endif + internal static extern SafeBrotliDecoderHandle BrotliDecoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderDecompressStream")] +#endif + internal static extern unsafe int BrotliDecoderDecompressStream( + SafeBrotliDecoderHandle state, ref size_t availableIn, byte** nextIn, + ref size_t availableOut, byte** nextOut, out size_t totalOut); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderDecompress")] +#endif + internal static extern unsafe bool BrotliDecoderDecompress(size_t availableInput, byte* inBytes, ref size_t availableOutput, byte* outBytes); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderDestroyInstance")] +#endif + internal static extern void BrotliDecoderDestroyInstance(IntPtr state); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderIsFinished")] +#endif + internal static extern bool BrotliDecoderIsFinished(SafeBrotliDecoderHandle state); + } +} + diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs new file mode 100644 index 000000000000..5fbfcbbff30a --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.IO.Compression; +using Microsoft.Win32.SafeHandles; +using size_t = System.IntPtr; + +internal static partial class Interop +{ + internal static partial class Brotli + { +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderCreateInstance")] +#endif + internal static extern SafeBrotliEncoderHandle BrotliEncoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderSetParameter")] +#endif + internal static extern bool BrotliEncoderSetParameter(SafeBrotliEncoderHandle state, BrotliEncoderParameter parameter, UInt32 value); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderCompressStream")] +#endif + internal static extern unsafe bool BrotliEncoderCompressStream( + SafeBrotliEncoderHandle state, BrotliEncoderOperation op, ref size_t availableIn, + byte** nextIn, ref size_t availableOut, byte** nextOut, out size_t totalOut); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderHasMoreOutput")] +#endif + internal static extern bool BrotliEncoderHasMoreOutput(SafeBrotliEncoderHandle state); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderDestroyInstance")] +#endif + internal static extern void BrotliEncoderDestroyInstance(IntPtr state); + +#if UNITY_WIN_PLATFORM || UNITY_AOT + [DllImport(Libraries.CompressionNative)] +#else + [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderCompress")] +#endif + internal static extern unsafe bool BrotliEncoderCompress(int quality, int window, int v, size_t availableInput, byte* inBytes, ref size_t availableOutput, byte* outBytes); + } +} + diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/PinvokeAnalyzerExceptionList.analyzerdata b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/PinvokeAnalyzerExceptionList.analyzerdata new file mode 100644 index 000000000000..f86667937a6f --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/PinvokeAnalyzerExceptionList.analyzerdata @@ -0,0 +1,23 @@ + +clrcompression.dll!BrotliDecoderCreateInstance +clrcompression.dll!BrotliDecoderDecompress +clrcompression.dll!BrotliDecoderDecompressStream +clrcompression.dll!BrotliDecoderDestroyInstance +clrcompression.dll!BrotliDecoderErrorString +clrcompression.dll!BrotliDecoderGetErrorCode +clrcompression.dll!BrotliDecoderHasMoreOutput +clrcompression.dll!BrotliDecoderIsFinished +clrcompression.dll!BrotliDecoderIsUsed +clrcompression.dll!BrotliDecoderSetParameter +clrcompression.dll!BrotliDecoderTakeOutput +clrcompression.dll!BrotliDecoderVersion +clrcompression.dll!BrotliEncoderCompress +clrcompression.dll!BrotliEncoderCompressStream +clrcompression.dll!BrotliEncoderCreateInstance +clrcompression.dll!BrotliEncoderDestroyInstance +clrcompression.dll!BrotliEncoderHasMoreOutput +clrcompression.dll!BrotliEncoderIsFinished +clrcompression.dll!BrotliEncoderMaxCompressedSize +clrcompression.dll!BrotliEncoderSetParameter +clrcompression.dll!BrotliEncoderTakeOutput +clrcompression.dll!BrotliEncoderVersion diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Resources/Strings.resx b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Resources/Strings.resx new file mode 100644 index 000000000000..0e95b1fa9e3f --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Resources/Strings.resx @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Stream does not support reading. + + + Stream does not support writing. + + + Enum value was out of legal range. + + + Can not access a closed Stream. + + + Positive number required. + + + Offset plus count is larger than the length of target array. + + + Only one asynchronous reader or writer is allowed time at one time. + + + + Failed to create BrotliEncoder instance + + + Can not access a closed Encoder. + + + Provided BrotliEncoder Quality of {0} is not between the minimum value of {1} and the maximum value of {2} + + + Provided BrotliEncoder Window of {0} is not between the minimum value of {1} and the maximum value of {2} + + + The BrotliEncoder {0} can not be changed at current encoder state. + + + + Failed to create BrotliDecoder instance + + + Decoder threw unexpected error: {0} + + + Can not access a closed Decoder. + + + + Can not perform Read operations on a BrotliStream constructed with CompressionMode.Compress. + + + Encoder ran into invalid data. + + + + Can not perform Write operations on a BrotliStream constructed with CompressionMode.Decompress. + + + Decoder ran into invalid data. + + + BrotliStream.BaseStream returned more bytes than requested in Read. + + diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj new file mode 100644 index 000000000000..2555fb0ca1a2 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj @@ -0,0 +1,61 @@ + + + + + System.IO.Compression.Brotli + Library + {5471BFE8-8071-466F-838E-5ADAA779E742} + true + + + + + + + + + + + + + + + + + + + + Common\System\Threading\Tasks\TaskToApm.cs + + + Common\Microsoft\Win32\SafeHandles\SafeBrotliHandle.cs + + + + + + Common\Interop\Windows\Interop.Libraries.cs + + + + + + Common\Interop\Unix\Interop.Libraries.cs + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliStream.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliStream.cs new file mode 100644 index 000000000000..eae7912210c1 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliStream.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace System.IO.Compression +{ + public sealed partial class BrotliStream : Stream + { + private const int DefaultInternalBufferSize = (1 << 16) - 16; //65520; + private Stream _stream; + private readonly byte[] _buffer; + private readonly bool _leaveOpen; + private readonly CompressionMode _mode; + + public BrotliStream(Stream stream, CompressionMode mode) : this(stream, mode, leaveOpen: false) { } + public BrotliStream(Stream stream, CompressionMode mode, bool leaveOpen) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + switch (mode) + { + case CompressionMode.Compress: + if (!stream.CanWrite) + throw new ArgumentException(SR.Stream_FalseCanWrite, nameof(stream)); + break; + case CompressionMode.Decompress: + if (!stream.CanRead) + throw new ArgumentException(SR.Stream_FalseCanRead, nameof(stream)); + break; + default: + throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(mode)); + } + + _mode = mode; + _stream = stream; + _leaveOpen = leaveOpen; + _buffer = new byte[DefaultInternalBufferSize]; + } + + private void EnsureNotDisposed() + { + if (_stream == null) + throw new ObjectDisposedException("stream", SR.ObjectDisposed_StreamClosed); + } + + protected override void Dispose(bool disposing) + { + try + { + if (disposing && _stream != null) + { + if (_mode == CompressionMode.Compress) + { + WriteCore(ReadOnlySpan.Empty, isFinalBlock: true); + } + + if (!_leaveOpen) + { + _stream.Dispose(); + } + } + } + finally + { + _stream = null; + _encoder.Dispose(); + _decoder.Dispose(); + base.Dispose(disposing); + } + } + + private static void ValidateParameters(byte[] array, int offset, int count) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedPosNum); + + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedPosNum); + + if (array.Length - offset < count) + throw new ArgumentException(SR.InvalidArgumentOffsetCount); + } + + public Stream BaseStream => _stream; + public override bool CanRead => _mode == CompressionMode.Decompress && _stream != null && _stream.CanRead; + public override bool CanWrite => _mode == CompressionMode.Compress && _stream != null && _stream.CanWrite; + public override bool CanSeek => false; + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); + public override long Length => throw new NotSupportedException(); + public override long Position + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + public override void SetLength(long value) => throw new NotSupportedException(); + + private int _activeAsyncOperation; // 1 == true, 0 == false + private bool AsyncOperationIsActive => _activeAsyncOperation != 0; + + private void EnsureNoActiveAsyncOperation() + { + if (AsyncOperationIsActive) + ThrowInvalidBeginCall(); + } + + private void AsyncOperationStarting() + { + if (Interlocked.CompareExchange(ref _activeAsyncOperation, 1, 0) != 0) + { + ThrowInvalidBeginCall(); + } + } + + private void AsyncOperationCompleting() + { + int oldValue = Interlocked.CompareExchange(ref _activeAsyncOperation, 0, 1); + Debug.Assert(oldValue == 1, $"Expected {nameof(_activeAsyncOperation)} to be 1, got {oldValue}"); + } + + private static void ThrowInvalidBeginCall() + { + throw new InvalidOperationException(SR.InvalidBeginCall); + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliUtils.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliUtils.cs new file mode 100644 index 000000000000..7dd6da519ae6 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliUtils.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.IO.Compression +{ + internal static partial class BrotliUtils + { + public const int WindowBits_Min = 10; + public const int WindowBits_Default = 22; + public const int WindowBits_Max = 24; + public const int Quality_Min = 0; + public const int Quality_Default = 11; + public const int Quality_Max = 11; + public const int MaxInputSize = int.MaxValue - 515; // 515 is the max compressed extra bytes + + internal static int GetQualityFromCompressionLevel(CompressionLevel level) + { + switch (level) + { + case CompressionLevel.Optimal: + return Quality_Default; + case CompressionLevel.NoCompression: + return Quality_Min; + case CompressionLevel.Fastest: + return 1; + default: + return (int)level; + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliDecoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliDecoder.cs new file mode 100644 index 000000000000..96a966b55262 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliDecoder.cs @@ -0,0 +1,109 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Buffers; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; +using size_t = System.IntPtr; + +namespace System.IO.Compression +{ + public struct BrotliDecoder : IDisposable + { + private SafeBrotliDecoderHandle _state; + private bool _disposed; + + internal void InitializeDecoder() + { + _state = Interop.Brotli.BrotliDecoderCreateInstance(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + if (_state.IsInvalid) + throw new IOException(SR.BrotliDecoder_Create); + } + + internal void EnsureInitialized() + { + EnsureNotDisposed(); + if (_state == null) + InitializeDecoder(); + } + + public void Dispose() + { + _disposed = true; + _state?.Dispose(); + } + + private void EnsureNotDisposed() + { + if (_disposed) + throw new ObjectDisposedException(nameof(BrotliDecoder), SR.BrotliDecoder_Disposed); + } + + public OperationStatus Decompress(ReadOnlySpan source, Span destination, out int bytesConsumed, out int bytesWritten) + { + EnsureInitialized(); + bytesConsumed = 0; + bytesWritten = 0; + if (Interop.Brotli.BrotliDecoderIsFinished(_state)) + return OperationStatus.Done; + size_t availableOutput = (size_t)destination.Length; + size_t availableInput = (size_t)source.Length; + unsafe + { + // We can freely cast between int and size_t for two reasons: + // 1. Interop Brotli functions will always return an availableInput/Output value lower or equal to the one passed to the function + // 2. Span's have a maximum length of the int boundary. + while ((int)availableOutput > 0) + { + fixed (byte* inBytes = &MemoryMarshal.GetReference(source)) + fixed (byte* outBytes = &MemoryMarshal.GetReference(destination)) + { + // MCS bug workaround: + byte* inBytesPtr = inBytes; + byte* outBytesPtr = outBytes; + + int brotliResult = Interop.Brotli.BrotliDecoderDecompressStream(_state, ref availableInput, &inBytesPtr, ref availableOutput, &outBytesPtr, out size_t totalOut); + if (brotliResult == 0) // Error + { + return OperationStatus.InvalidData; + } + bytesConsumed += source.Length - (int)availableInput; + bytesWritten += destination.Length - (int)availableOutput; + + switch (brotliResult) + { + case 1: // Success + return OperationStatus.Done; + case 3: // NeedsMoreOutput + return OperationStatus.DestinationTooSmall; + case 2: // NeedsMoreInput + default: + source = source.Slice(source.Length - (int)availableInput); + destination = destination.Slice(destination.Length - (int)availableOutput); + if (brotliResult == 2 && source.Length == 0) + return OperationStatus.NeedMoreData; + break; + } + } + } + return OperationStatus.DestinationTooSmall; + } + } + + public static bool TryDecompress(ReadOnlySpan source, Span destination, out int bytesWritten) + { + unsafe + { + fixed (byte* inBytes = &MemoryMarshal.GetReference(source)) + fixed (byte* outBytes = &MemoryMarshal.GetReference(destination)) + { + size_t availableOutput = (size_t)destination.Length; + bool success = Interop.Brotli.BrotliDecoderDecompress((size_t)source.Length, inBytes, ref availableOutput, outBytes); + bytesWritten = (int)availableOutput; + return success; + } + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliStream.Decompress.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliStream.Decompress.cs new file mode 100644 index 000000000000..a4489b57e82b --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliStream.Decompress.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Buffers; +using System.Threading; +using System.Threading.Tasks; + +namespace System.IO.Compression +{ + public sealed partial class BrotliStream : Stream + { + private BrotliDecoder _decoder; + private int _bufferOffset; + private int _bufferCount; + + public override int Read(byte[] buffer, int offset, int count) + { + ValidateParameters(buffer, offset, count); + return Read(new Span(buffer, offset, count)); + } + + public override int Read(Span buffer) + { + if (_mode != CompressionMode.Decompress) + throw new InvalidOperationException(SR.BrotliStream_Compress_UnsupportedOperation); + EnsureNotDisposed(); + int totalWritten = 0; + + OperationStatus lastResult = OperationStatus.DestinationTooSmall; + // We want to continue calling Decompress until we're either out of space for output or until Decompress indicates it is finished. + while (buffer.Length > 0 && lastResult != OperationStatus.Done) + { + if (lastResult == OperationStatus.NeedMoreData) + { + // Ensure any left over data is at the beginning of the array so we can fill the remainder. + if (_bufferCount > 0 && _bufferOffset != 0) + { + _buffer.AsSpan(_bufferOffset, _bufferCount).CopyTo(_buffer); + } + _bufferOffset = 0; + + int numRead = 0; + while (_bufferCount < _buffer.Length && ((numRead = _stream.Read(_buffer, _bufferCount, _buffer.Length - _bufferCount)) > 0)) + { + _bufferCount += numRead; + if (_bufferCount > _buffer.Length) + { + // The stream is either malicious or poorly implemented and returned a number of + // bytes larger than the buffer supplied to it. + throw new InvalidDataException(SR.BrotliStream_Decompress_InvalidStream); + } + } + + if (_bufferCount <= 0) + { + break; + } + } + + lastResult = _decoder.Decompress(_buffer.AsSpan(_bufferOffset, _bufferCount), buffer, out int bytesConsumed, out int bytesWritten); + if (lastResult == OperationStatus.InvalidData) + { + throw new InvalidOperationException(SR.BrotliStream_Decompress_InvalidData); + } + + if (bytesConsumed > 0) + { + _bufferOffset += bytesConsumed; + _bufferCount -= bytesConsumed; + } + + if (bytesWritten > 0) + { + totalWritten += bytesWritten; + buffer = buffer.Slice(bytesWritten); + } + } + + return totalWritten; + } + + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + TaskToApm.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState); + + public override int EndRead(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ValidateParameters(buffer, offset, count); + return ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); + } + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default(CancellationToken)) + { + if (_mode != CompressionMode.Decompress) + throw new InvalidOperationException(SR.BrotliStream_Compress_UnsupportedOperation); + EnsureNoActiveAsyncOperation(); + EnsureNotDisposed(); + + if (cancellationToken.IsCancellationRequested) + { + return new ValueTask(Task.FromCanceled(cancellationToken)); + } + return FinishReadAsyncMemory(buffer, cancellationToken); + } + + private async ValueTask FinishReadAsyncMemory(Memory buffer, CancellationToken cancellationToken) + { + AsyncOperationStarting(); + try + { + int totalWritten = 0; + Memory source = Memory.Empty; + OperationStatus lastResult = OperationStatus.DestinationTooSmall; + // We want to continue calling Decompress until we're either out of space for output or until Decompress indicates it is finished. + while (buffer.Length > 0 && lastResult != OperationStatus.Done) + { + if (lastResult == OperationStatus.NeedMoreData) + { + // Ensure any left over data is at the beginning of the array so we can fill the remainder. + if (_bufferCount > 0 && _bufferOffset != 0) + { + _buffer.AsSpan(_bufferOffset, _bufferCount).CopyTo(_buffer); + } + _bufferOffset = 0; + + int numRead = 0; + while (_bufferCount < _buffer.Length && ((numRead = await _stream.ReadAsync(new Memory(_buffer, _bufferCount, _buffer.Length - _bufferCount)).ConfigureAwait(false)) > 0)) + { + _bufferCount += numRead; + if (_bufferCount > _buffer.Length) + { + // The stream is either malicious or poorly implemented and returned a number of + // bytes larger than the buffer supplied to it. + throw new InvalidDataException(SR.BrotliStream_Decompress_InvalidStream); + } + } + + if (_bufferCount <= 0) + { + break; + } + } + + cancellationToken.ThrowIfCancellationRequested(); + lastResult = _decoder.Decompress(_buffer.AsSpan(_bufferOffset, _bufferCount), buffer.Span, out int bytesConsumed, out int bytesWritten); + if (lastResult == OperationStatus.InvalidData) + { + throw new InvalidOperationException(SR.BrotliStream_Decompress_InvalidData); + } + + if (bytesConsumed > 0) + { + _bufferOffset += bytesConsumed; + _bufferCount -= bytesConsumed; + } + + if (bytesWritten > 0) + { + totalWritten += bytesWritten; + buffer = buffer.Slice(bytesWritten); + } + } + + return totalWritten; + } + finally + { + AsyncOperationCompleting(); + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoder.cs new file mode 100644 index 000000000000..89f094c85551 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoder.cs @@ -0,0 +1,186 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Buffers; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; +using size_t = System.IntPtr; + +namespace System.IO.Compression +{ + public partial struct BrotliEncoder : IDisposable + { + internal SafeBrotliEncoderHandle _state; + private bool _disposed; + + public BrotliEncoder(int quality, int window) + { + _disposed = false; + _state = Interop.Brotli.BrotliEncoderCreateInstance(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + if (_state.IsInvalid) + throw new IOException(SR.BrotliEncoder_Create); + SetQuality(quality); + SetWindow(window); + } + + /// + /// Performs a lazy initialization of the native encoder using the default Quality and Window values: + /// BROTLI_DEFAULT_WINDOW 22 + /// BROTLI_DEFAULT_QUALITY 11 + /// + internal void InitializeEncoder() + { + EnsureNotDisposed(); + _state = Interop.Brotli.BrotliEncoderCreateInstance(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + if (_state.IsInvalid) + throw new IOException(SR.BrotliEncoder_Create); + } + + internal void EnsureInitialized() + { + EnsureNotDisposed(); + if (_state == null) + { + InitializeEncoder(); + } + } + + public void Dispose() + { + _disposed = true; + _state?.Dispose(); + } + + private void EnsureNotDisposed() + { + if (_disposed) + throw new ObjectDisposedException(nameof(BrotliEncoder), SR.BrotliEncoder_Disposed); + } + + internal void SetQuality(int quality) + { + EnsureNotDisposed(); + if (_state == null || _state.IsInvalid || _state.IsClosed) + { + InitializeEncoder(); + } + if (quality < BrotliUtils.Quality_Min || quality > BrotliUtils.Quality_Max) + { + throw new ArgumentOutOfRangeException(nameof(quality), SR.Format(SR.BrotliEncoder_Quality, quality, 0, BrotliUtils.Quality_Max)); + } + if (!Interop.Brotli.BrotliEncoderSetParameter(_state, BrotliEncoderParameter.Quality, (uint)quality)) + { + throw new InvalidOperationException(SR.Format(SR.BrotliEncoder_InvalidSetParameter, "Quality")); + } + } + + internal void SetWindow(int window) + { + EnsureNotDisposed(); + if (_state == null || _state.IsInvalid || _state.IsClosed) + { + InitializeEncoder(); + } + if (window < BrotliUtils.WindowBits_Min || window > BrotliUtils.WindowBits_Max) + { + throw new ArgumentOutOfRangeException(nameof(window), SR.Format(SR.BrotliEncoder_Window, window, BrotliUtils.WindowBits_Min, BrotliUtils.WindowBits_Max)); + } + if (!Interop.Brotli.BrotliEncoderSetParameter(_state, BrotliEncoderParameter.LGWin, (uint)window)) + { + throw new InvalidOperationException(SR.Format(SR.BrotliEncoder_InvalidSetParameter, "Window")); + } + } + + public static int GetMaxCompressedLength(int length) + { + if (length < 0 || length > BrotliUtils.MaxInputSize) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + return 1; + int numLargeBlocks = length >> 24; + int tail = length & 0xFFFFFF; + int tailOverhead = (tail > (1 << 20)) ? 4 : 3; + int overhead = 2 + (4 * numLargeBlocks) + tailOverhead + 1; + int result = length + overhead; + return result; + } + + internal OperationStatus Flush(Memory destination, out int bytesWritten) => Flush(destination.Span, out bytesWritten); + + public OperationStatus Flush(Span destination, out int bytesWritten) => Compress(ReadOnlySpan.Empty, destination, out int bytesConsumed, out bytesWritten, BrotliEncoderOperation.Flush); + + internal OperationStatus Compress(ReadOnlyMemory source, Memory destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) => Compress(source.Span, destination.Span, out bytesConsumed, out bytesWritten, isFinalBlock); + + public OperationStatus Compress(ReadOnlySpan source, Span destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) => Compress(source, destination, out bytesConsumed, out bytesWritten, isFinalBlock ? BrotliEncoderOperation.Finish : BrotliEncoderOperation.Process); + + internal OperationStatus Compress(ReadOnlySpan source, Span destination, out int bytesConsumed, out int bytesWritten, BrotliEncoderOperation operation) + { + EnsureInitialized(); + bytesWritten = 0; + bytesConsumed = 0; + size_t availableOutput = (size_t)destination.Length; + size_t availableInput = (size_t)source.Length; + unsafe + { + // We can freely cast between int and size_t for two reasons: + // 1. Interop Brotli functions will always return an availableInput/Output value lower or equal to the one passed to the function + // 2. Span's have a maximum length of the int boundary. + while ((int)availableOutput > 0) + { + fixed (byte* inBytes = &MemoryMarshal.GetReference(source)) + fixed (byte* outBytes = &MemoryMarshal.GetReference(destination)) + { + // MCS bug workaround: + byte* inBytesPtr = inBytes; + byte* outBytesPtr = outBytes; + + if (!Interop.Brotli.BrotliEncoderCompressStream(_state, operation, ref availableInput, &inBytesPtr, ref availableOutput, &outBytesPtr, out size_t totalOut)) + { + return OperationStatus.InvalidData; + } + bytesConsumed += source.Length - (int)availableInput; + bytesWritten += destination.Length - (int)availableOutput; + // no bytes written, no remaining input to give to the encoder, and no output in need of retrieving means we are Done + if ((int)availableOutput == destination.Length && !Interop.Brotli.BrotliEncoderHasMoreOutput(_state) && (int)availableInput == 0) + { + return OperationStatus.Done; + } + + source = source.Slice(source.Length - (int)availableInput); + destination = destination.Slice(destination.Length - (int)availableOutput); + } + } + + return OperationStatus.DestinationTooSmall; + } + } + + public static bool TryCompress(ReadOnlySpan source, Span destination, out int bytesWritten) => TryCompress(source, destination, out bytesWritten, BrotliUtils.Quality_Default, BrotliUtils.WindowBits_Default); + + public static bool TryCompress(ReadOnlySpan source, Span destination, out int bytesWritten, int quality, int window) + { + if (quality < 0 || quality > BrotliUtils.Quality_Max) + { + throw new ArgumentOutOfRangeException(nameof(quality), SR.Format(SR.BrotliEncoder_Quality, quality, 0, BrotliUtils.Quality_Max)); + } + if (window < BrotliUtils.WindowBits_Min || window > BrotliUtils.WindowBits_Max) + { + throw new ArgumentOutOfRangeException(nameof(window), SR.Format(SR.BrotliEncoder_Window, window, BrotliUtils.WindowBits_Min, BrotliUtils.WindowBits_Max)); + } + unsafe + { + fixed (byte* inBytes = &MemoryMarshal.GetReference(source)) + fixed (byte* outBytes = &MemoryMarshal.GetReference(destination)) + { + size_t availableOutput = (size_t)destination.Length; + bool success = Interop.Brotli.BrotliEncoderCompress(quality, window, /*BrotliEncoderMode*/ 0, (size_t)source.Length, inBytes, ref availableOutput, outBytes); + bytesWritten = (int)availableOutput; + return success; + } + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderOperation.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderOperation.cs new file mode 100644 index 000000000000..ade5d63c9bf1 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderOperation.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.IO.Compression +{ + /// + /// Process - Process input. Encoder may postpone producing output, until it has processed enough input. + /// Flush - Produce output for all processed input. Actual flush is performed when input stream is depleted and there is enough space in output stream. + /// Finish - Finalize the stream. Adding more input data to finalized stream is impossible. + /// EmitMetadata - Emit metadata block to stream. Stream is soft-flushed before metadata block is emitted. Metadata bloc MUST be no longer than 16MiB. + /// + internal enum BrotliEncoderOperation + { + Process, + Flush, + Finish, + EmitMetadata + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderParameter.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderParameter.cs new file mode 100644 index 000000000000..8d3cf110b4fb --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderParameter.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.IO.Compression +{ + /// + /// Mode - BrotliEncoderMode enumerates all available values. + /// Quality - The main compression speed-density lever. The higher the quality, the slower the compression. Range is from ::BROTLI_MIN_QUALITY to::BROTLI_MAX_QUALITY. + /// LGWin - Recommended sliding LZ77 window size. Encoder may reduce this value, e.g. if input is much smaller than window size. Range is from BROTLI_MIN_WINDOW_BITS to BROTLI_MAX_WINDOW_BITS. + /// LGBlock - Recommended input block size. Encoder may reduce this value, e.g. if input is much smaller than window size. Range is from BROTLI_MIN_INPUT_BLOCK_BITS to BROTLI_MAX_INPUT_BLOCK_BITS. Bigger input block size allows better compression, but consumes more memory. + /// LCModeling- Flag that affects usage of "literal context modeling" format feature. This flag is a "decoding-speed vs compression ratio" trade-off. + /// SizeHint - Estimated total input size for all BrotliEncoderCompressStream calls. The default value is 0, which means that the total input size is unknown. + /// + internal enum BrotliEncoderParameter + { + Mode, + Quality, + LGWin, + LGBlock, + LCModeling, + SizeHint + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs new file mode 100644 index 000000000000..0770c46989e2 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Buffers; +using System.Threading; +using System.Threading.Tasks; + +namespace System.IO.Compression +{ + public sealed partial class BrotliStream : Stream + { + private BrotliEncoder _encoder; + + public BrotliStream(Stream stream, CompressionLevel compressionLevel) : this(stream, compressionLevel, leaveOpen: false) { } + public BrotliStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen) : this(stream, CompressionMode.Compress, leaveOpen) + { + _encoder.SetQuality(BrotliUtils.GetQualityFromCompressionLevel(compressionLevel)); + } + + public override void Write(byte[] buffer, int offset, int count) + { + ValidateParameters(buffer, offset, count); + WriteCore(new ReadOnlySpan(buffer, offset, count)); + } + + public override void Write(ReadOnlySpan buffer) + { + WriteCore(buffer); + } + + internal void WriteCore(ReadOnlySpan buffer, bool isFinalBlock = false) + { + if (_mode != CompressionMode.Compress) + throw new InvalidOperationException(SR.BrotliStream_Decompress_UnsupportedOperation); + EnsureNotDisposed(); + + OperationStatus lastResult = OperationStatus.DestinationTooSmall; + Span output = new Span(_buffer); + while (lastResult == OperationStatus.DestinationTooSmall) + { + int bytesConsumed = 0; + int bytesWritten = 0; + lastResult = _encoder.Compress(buffer, output, out bytesConsumed, out bytesWritten, isFinalBlock); + if (lastResult == OperationStatus.InvalidData) + throw new InvalidOperationException(SR.BrotliStream_Compress_InvalidData); + if (bytesWritten > 0) + _stream.Write(output.Slice(0, bytesWritten)); + if (bytesConsumed > 0) + buffer = buffer.Slice(bytesConsumed); + } + } + + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + TaskToApm.Begin(WriteAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState); + + public override void EndWrite(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ValidateParameters(buffer, offset, count); + return WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); + } + + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default(CancellationToken)) + { + if (_mode != CompressionMode.Compress) + throw new InvalidOperationException(SR.BrotliStream_Decompress_UnsupportedOperation); + EnsureNoActiveAsyncOperation(); + EnsureNotDisposed(); + + return new ValueTask(cancellationToken.IsCancellationRequested ? + Task.FromCanceled(cancellationToken) : + WriteAsyncMemoryCore(buffer, cancellationToken)); + } + + private async Task WriteAsyncMemoryCore(ReadOnlyMemory buffer, CancellationToken cancellationToken) + { + AsyncOperationStarting(); + try + { + OperationStatus lastResult = OperationStatus.DestinationTooSmall; + while (lastResult == OperationStatus.DestinationTooSmall) + { + Memory output = new Memory(_buffer); + int bytesConsumed = 0; + int bytesWritten = 0; + lastResult = _encoder.Compress(buffer, output, out bytesConsumed, out bytesWritten, isFinalBlock: false); + if (lastResult == OperationStatus.InvalidData) + throw new InvalidOperationException(SR.BrotliStream_Compress_InvalidData); + if (bytesConsumed > 0) + buffer = buffer.Slice(bytesConsumed); + if (bytesWritten > 0) + await _stream.WriteAsync(new ReadOnlyMemory(_buffer, 0, bytesWritten), cancellationToken).ConfigureAwait(false); + } + } + finally + { + AsyncOperationCompleting(); + } + } + + public override void Flush() + { + EnsureNotDisposed(); + if (_mode == CompressionMode.Compress) + { + if (_encoder._state == null || _encoder._state.IsClosed) + return; + + OperationStatus lastResult = OperationStatus.DestinationTooSmall; + Span output = new Span(_buffer); + while (lastResult == OperationStatus.DestinationTooSmall) + { + int bytesWritten = 0; + lastResult = _encoder.Flush(output, out bytesWritten); + if (lastResult == OperationStatus.InvalidData) + throw new InvalidDataException(SR.BrotliStream_Compress_InvalidData); + if (bytesWritten > 0) + { + _stream.Write(output.Slice(0, bytesWritten)); + } + } + } + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + EnsureNoActiveAsyncOperation(); + EnsureNotDisposed(); + + if (cancellationToken.IsCancellationRequested) + return Task.FromCanceled(cancellationToken); + + return _mode != CompressionMode.Compress ? Task.CompletedTask : FlushAsyncCore(cancellationToken); + } + + private async Task FlushAsyncCore(CancellationToken cancellationToken) + { + AsyncOperationStarting(); + try + { + if (_encoder._state == null || _encoder._state.IsClosed) + return; + + OperationStatus lastResult = OperationStatus.DestinationTooSmall; + while (lastResult == OperationStatus.DestinationTooSmall) + { + Memory output = new Memory(_buffer); + int bytesWritten = 0; + lastResult = _encoder.Flush(output, out bytesWritten); + if (lastResult == OperationStatus.InvalidData) + throw new InvalidDataException(SR.BrotliStream_Compress_InvalidData); + if (bytesWritten > 0) + await _stream.WriteAsync(output.Slice(0, bytesWritten), cancellationToken).ConfigureAwait(false); + } + } + finally + { + AsyncOperationCompleting(); + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs new file mode 100644 index 000000000000..171d35464e34 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs @@ -0,0 +1,387 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Buffers; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace System.IO.Compression.Tests +{ + public class BrotliEncoderTests : CompressionTestBase + { + protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br"); + + [Fact] + public void InvalidQuality() + { + Assert.Throws("quality", () => new BrotliEncoder(-1, 11)); + Assert.Throws("quality", () => new BrotliEncoder(12, 11)); + Assert.Throws("quality", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, -1, 13)); + Assert.Throws("quality", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 12, 13)); + } + + [Fact] + public void InvalidWindow() + { + Assert.Throws("window", () => new BrotliEncoder(10, -1)); + Assert.Throws("window", () => new BrotliEncoder(10, 9)); + Assert.Throws("window", () => new BrotliEncoder(10, 25)); + Assert.Throws("window", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 6, -1)); + Assert.Throws("window", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 6, 9)); + Assert.Throws("window", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 6, 25)); + } + + [Fact] + public void GetMaxCompressedSize_Basic() + { + Assert.Throws("length", () => BrotliEncoder.GetMaxCompressedLength(-1)); + Assert.Throws("length", () => BrotliEncoder.GetMaxCompressedLength(2147483133)); + Assert.InRange(BrotliEncoder.GetMaxCompressedLength(2147483132), 0, Int32.MaxValue); + Assert.Equal(1, BrotliEncoder.GetMaxCompressedLength(0)); + } + + [Fact] + public void GetMaxCompressedSize() + { + string uncompressedFile = UncompressedTestFile(); + string compressedFile = CompressedTestFile(uncompressedFile); + int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength((int)new FileInfo(uncompressedFile).Length); + int actualCompressedSize = (int)new FileInfo(compressedFile).Length; + Assert.True(maxCompressedSize >= actualCompressedSize, $"MaxCompressedSize: {maxCompressedSize}, ActualCompressedSize: {actualCompressedSize}"); + } + + /// + /// Test to ensure that when given an empty Destination span, the decoder will consume no input and write no output. + /// + [Fact] + public void Decompress_WithEmptyDestination() + { + string testFile = UncompressedTestFile(); + byte[] sourceBytes = File.ReadAllBytes(CompressedTestFile(testFile)); + byte[] destinationBytes = new byte[0]; + ReadOnlySpan source = new ReadOnlySpan(sourceBytes); + Span destination = new Span(destinationBytes); + + Assert.False(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress completed successfully but should have failed due to too short of a destination array"); + Assert.Equal(0, bytesWritten); + + BrotliDecoder decoder = default; + var result = decoder.Decompress(source, destination, out int bytesConsumed, out bytesWritten); + Assert.Equal(0, bytesWritten); + Assert.Equal(0, bytesConsumed); + Assert.Equal(OperationStatus.DestinationTooSmall, result); + } + + /// + /// Test to ensure that when given an empty source span, the decoder will consume no input and write no output + /// + [Fact] + public void Decompress_WithEmptySource() + { + string testFile = UncompressedTestFile(); + byte[] sourceBytes = new byte[0]; + byte[] destinationBytes = new byte[100000]; + ReadOnlySpan source = new ReadOnlySpan(sourceBytes); + Span destination = new Span(destinationBytes); + + Assert.False(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress completed successfully but should have failed due to too short of a source array"); + Assert.Equal(0, bytesWritten); + + BrotliDecoder decoder = default; + var result = decoder.Decompress(source, destination, out int bytesConsumed, out bytesWritten); + Assert.Equal(0, bytesWritten); + Assert.Equal(0, bytesConsumed); + Assert.Equal(OperationStatus.NeedMoreData, result); + } + + /// + /// Test to ensure that when given an empty Destination span, the encoder consume no input and write no output + /// + [Fact] + public void Compress_WithEmptyDestination() + { + string testFile = UncompressedTestFile(); + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile)); + byte[] empty = new byte[0]; + ReadOnlySpan source = new ReadOnlySpan(correctUncompressedBytes); + Span destination = new Span(empty); + + Assert.False(BrotliEncoder.TryCompress(source, destination, out int bytesWritten), "TryCompress completed successfully but should have failed due to too short of a destination array"); + Assert.Equal(0, bytesWritten); + + BrotliEncoder encoder = default; + var result = encoder.Compress(source, destination, out int bytesConsumed, out bytesWritten, false); + Assert.Equal(0, bytesWritten); + Assert.Equal(0, bytesConsumed); + Assert.Equal(OperationStatus.DestinationTooSmall, result); + + result = encoder.Compress(source, destination, out bytesConsumed, out bytesWritten, isFinalBlock: true); + Assert.Equal(0, bytesWritten); + Assert.Equal(0, bytesConsumed); + Assert.Equal(OperationStatus.DestinationTooSmall, result); + } + + /// + /// Test to ensure that when given an empty source span, the decoder will consume no input and write no output (until the finishing block) + /// + [Fact] + public void Compress_WithEmptySource() + { + string testFile = UncompressedTestFile(); + byte[] sourceBytes = new byte[0]; + byte[] destinationBytes = new byte[100000]; + ReadOnlySpan source = new ReadOnlySpan(sourceBytes); + Span destination = new Span(destinationBytes); + + Assert.True(BrotliEncoder.TryCompress(source, destination, out int bytesWritten)); + // The only byte written should be the Brotli end of stream byte which varies based on the window/quality + Assert.Equal(1, bytesWritten); + + BrotliEncoder encoder = default; + var result = encoder.Compress(source, destination, out int bytesConsumed, out bytesWritten, false); + Assert.Equal(0, bytesWritten); + Assert.Equal(0, bytesConsumed); + Assert.Equal(OperationStatus.Done, result); + + result = encoder.Compress(source, destination, out bytesConsumed, out bytesWritten, isFinalBlock: true); + Assert.Equal(1, bytesWritten); + Assert.Equal(0, bytesConsumed); + Assert.Equal(OperationStatus.Done, result); + } + + /// + /// Test that the decoder can handle partial chunks of flushed encoded data sent from the BrotliEncoder + /// + [Fact] + public void RoundTrip_Chunks() + { + int chunkSize = 100; + int totalSize = 20000; + BrotliEncoder encoder = default; + BrotliDecoder decoder = default; + for (int i = 0; i < totalSize; i += chunkSize) + { + byte[] uncompressed = new byte[chunkSize]; + new Random().NextBytes(uncompressed); + byte[] compressed = new byte[BrotliEncoder.GetMaxCompressedLength(chunkSize)]; + byte[] deompressed = new byte[chunkSize]; + var uncompressedSpan = new ReadOnlySpan(uncompressed); + var compressedSpan = new Span(compressed); + var decompressedSpan = new Span(deompressed); + + int totalWrittenThisIteration = 0; + var compress = encoder.Compress(uncompressedSpan, compressedSpan, out int bytesConsumed, out int bytesWritten, isFinalBlock: false); + totalWrittenThisIteration += bytesWritten; + compress = encoder.Flush(compressedSpan.Slice(bytesWritten), out bytesWritten); + totalWrittenThisIteration += bytesWritten; + + var res = decoder.Decompress(compressedSpan.Slice(0, totalWrittenThisIteration), decompressedSpan, out int decompressbytesConsumed, out int decompressbytesWritten); + Assert.Equal(totalWrittenThisIteration, decompressbytesConsumed); + Assert.Equal(bytesConsumed, decompressbytesWritten); + for (int j = 0; j < bytesConsumed; j++) + Assert.Equal(uncompressed[j], decompressedSpan[j]); + + } + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void ReadFully(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile)); + byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length + 10000]; + ReadOnlySpan source = new ReadOnlySpan(compressedBytes); + Span destination = new Span(actualUncompressedBytes); + Assert.True(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress did not complete successfully"); + Assert.Equal(correctUncompressedBytes.Length, bytesWritten); + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void ReadWithState(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile)); + byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length]; + Decompress_WithState(compressedBytes, actualUncompressedBytes); + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void ReadWithoutState(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile)); + byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length]; + Decompress_WithoutState(compressedBytes, actualUncompressedBytes); + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void WriteFully(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)]; + byte[] actualUncompressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)]; + + Span destination = new Span(compressedBytes); + + Assert.True(BrotliEncoder.TryCompress(correctUncompressedBytes, destination, out int bytesWritten)); + Assert.True(BrotliDecoder.TryDecompress(destination, actualUncompressedBytes, out bytesWritten)); + Assert.Equal(correctUncompressedBytes.Length, bytesWritten); + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void WriteWithState(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)]; + byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length]; + + Compress_WithState(correctUncompressedBytes, compressedBytes); + Decompress_WithState(compressedBytes, actualUncompressedBytes); + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void WriteWithoutState(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)]; + byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length]; + + Compress_WithoutState(correctUncompressedBytes, compressedBytes); + Decompress_WithoutState(compressedBytes, actualUncompressedBytes); + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [Theory] + [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")] + [MemberData(nameof(UncompressedTestFiles))] + public void WriteStream(string testFile) + { + byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); + byte[] compressedBytes = Compress_Stream(correctUncompressedBytes, CompressionLevel.Optimal).ToArray(); + byte[] actualUncompressedBytes = Decompress_Stream(compressedBytes).ToArray(); + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]); + } + + [OuterLoop("Full set of tests takes seconds to run")] + [Theory] + [InlineData(1, 0x400001, false)] + [InlineData(1, 0x400001, true)] + [InlineData(4, 0x800000, false)] + [InlineData(4, 0x800000, true)] + [InlineData(53, 12345, false)] + [InlineData(53, 12345, true)] + public static async Task Roundtrip_VaryingSizeReadsAndLengths_Success(int readSize, int totalLength, bool useAsync) + { + byte[] correctUncompressedBytes = Enumerable.Range(0, totalLength).Select(i => (byte)i).ToArray(); + byte[] compressedBytes = Compress_Stream(correctUncompressedBytes, CompressionLevel.Fastest).ToArray(); + byte[] actualBytes = new byte[correctUncompressedBytes.Length]; + + using (var s = new BrotliStream(new MemoryStream(compressedBytes), CompressionMode.Decompress)) + { + int totalRead = 0; + while (totalRead < actualBytes.Length) + { + int numRead = useAsync ? + await s.ReadAsync(actualBytes, totalRead, Math.Min(readSize, actualBytes.Length - totalRead)) : + s.Read(actualBytes, totalRead, Math.Min(readSize, actualBytes.Length - totalRead)); + totalRead += numRead; + } + + for (int i = 0; i < correctUncompressedBytes.Length; i++) + { + Assert.Equal(correctUncompressedBytes[i], actualBytes[i]); + } + } + } + + public static void Compress_WithState(ReadOnlySpan input, Span output) + { + BrotliEncoder encoder = default; + while (!input.IsEmpty && !output.IsEmpty) + { + encoder.Compress(input, output, out int bytesConsumed, out int written, isFinalBlock: false); + input = input.Slice(bytesConsumed); + output = output.Slice(written); + } + encoder.Compress(ReadOnlySpan.Empty, output, out int bytesConsumed2, out int bytesWritten, isFinalBlock: true); + } + + public static void Decompress_WithState(ReadOnlySpan input, Span output) + { + BrotliDecoder decoder = default; + while (!input.IsEmpty && !output.IsEmpty) + { + decoder.Decompress(input, output, out int bytesConsumed, out int written); + input = input.Slice(bytesConsumed); + output = output.Slice(written); + } + } + + public static void Compress_WithoutState(ReadOnlySpan input, Span output) + { + BrotliEncoder.TryCompress(input, output, out int bytesWritten); + } + + public static void Decompress_WithoutState(ReadOnlySpan input, Span output) + { + BrotliDecoder.TryDecompress(input, output, out int bytesWritten); + } + + public static MemoryStream Compress_Stream(ReadOnlySpan input, CompressionLevel compressionLevel) + { + using (var inputStream = new MemoryStream(input.ToArray())) + { + var outputStream = new MemoryStream(); + var compressor = new BrotliStream(outputStream, compressionLevel, true); + inputStream.CopyTo(compressor); + compressor.Dispose(); + return outputStream; + } + } + + public static MemoryStream Decompress_Stream(ReadOnlySpan input) + { + using (var inputStream = new MemoryStream(input.ToArray())) + { + var outputStream = new MemoryStream(); + var decompressor = new BrotliStream(inputStream, CompressionMode.Decompress, true); + decompressor.CopyTo(outputStream); + decompressor.Dispose(); + return outputStream; + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs new file mode 100644 index 000000000000..8f066aa2856a --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Xunit; + +namespace System.IO.Compression.Tests +{ + public class BrotliGoogleTestData + { + public static IEnumerable GoogleTestData() + { + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "10x10y") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "64x") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "backward65536") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "compressed_file") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "compressed_repeated") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "empty") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "mapsdatazrh") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "monkey") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "quickfox") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "quickfox_repeated") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "random_org_10k.bin") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "x") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "ukkonooa") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "xyzzy") }; + yield return new object[] { Path.Combine("UncompressedTestFiles", "GoogleTestData", "zeros") }; + } + + private string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", "GoogleTestData", Path.GetFileName(uncompressedPath) + ".br"); + + + [Theory] + [MemberData(nameof(GoogleTestData))] + public void DecompressFile(string fileName) + { + byte[] bytes = File.ReadAllBytes(CompressedTestFile(fileName)); + byte[] expected = File.ReadAllBytes(fileName); + + ValidateCompressedData(bytes, expected); + } + + [Theory] + [MemberData(nameof(GoogleTestData))] + public void RoundtripCompressDecompressFile(string fileName) + { + byte[] bytes = File.ReadAllBytes(fileName); + MemoryStream memoryStream = new MemoryStream(); + using (BrotliStream brotliStream = new BrotliStream(memoryStream, CompressionMode.Compress, true)) + { + brotliStream.Write(bytes, 0, bytes.Length); + } + memoryStream.Position = 0; + ValidateCompressedData(memoryStream.ToArray(), bytes); + memoryStream.Dispose(); + } + + private void ValidateCompressedData(byte[] compressedData, byte[] expected) + { + MemoryStream compressed = new MemoryStream(compressedData); + using (MemoryStream decompressed = new MemoryStream()) + using (var decompressor = new BrotliStream(compressed, CompressionMode.Decompress, true)) + { + decompressor.CopyTo(decompressed); + Assert.Equal(expected.Length, decompressed.ToArray().Length); + Assert.Equal(expected, decompressed.ToArray()); + } + } + } + +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs new file mode 100644 index 000000000000..84db45dc53fc --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.IO.Compression +{ + public class BrotliStreamUnitTests : CompressionStreamUnitTestBase + { + public override Stream CreateStream(Stream stream, CompressionMode mode) => new BrotliStream(stream, mode); + public override Stream CreateStream(Stream stream, CompressionMode mode, bool leaveOpen) => new BrotliStream(stream, mode, leaveOpen); + public override Stream CreateStream(Stream stream, CompressionLevel level) => new BrotliStream(stream, level); + public override Stream CreateStream(Stream stream, CompressionLevel level, bool leaveOpen) => new BrotliStream(stream, level, leaveOpen); + public override Stream BaseStream(Stream stream) => ((BrotliStream)stream).BaseStream; + public override int BufferSize { get => 65520; } + protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br"); + + [Fact] + public void Precancellation() + { + var ms = new MemoryStream(); + using (Stream compressor = new BrotliStream(ms, CompressionMode.Compress, leaveOpen: true)) + { + Assert.True(compressor.WriteAsync(new byte[1], 0, 1, new CancellationToken(true)).IsCanceled); + Assert.True(compressor.FlushAsync(new CancellationToken(true)).IsCanceled); + } + using (Stream decompressor = CreateStream(ms, CompressionMode.Decompress, leaveOpen: true)) + { + Assert.True(decompressor.ReadAsync(new byte[1], 0, 1, new CancellationToken(true)).IsCanceled); + } + } + + [Fact] + [OuterLoop("Test takes ~6 seconds to run")] + public override void FlushAsync_DuringWriteAsync() { base.FlushAsync_DuringWriteAsync(); } + + [Fact] + [OuterLoop("Test takes ~6 seconds to run")] + public override void WriteAsync_DuringWriteAsync() { base.WriteAsync_DuringWriteAsync(); } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Configurations.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Configurations.props new file mode 100644 index 000000000000..17d3231f8e68 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Configurations.props @@ -0,0 +1,9 @@ + + + + + netcoreapp-Unix; + netcoreapp-Windows_NT; + + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs new file mode 100644 index 000000000000..410b6cc14b8e --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Microsoft.Xunit.Performance; +using Xunit; + +namespace System.IO.Compression +{ + public class BrotliPerfTests : CompressionTestBase + { + protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br"); + + public static IEnumerable UncompressedTestFiles_WithCompressionLevel() + { + foreach (CompressionLevel compressionLevel in Enum.GetValues(typeof(CompressionLevel))) + { + foreach (object[] testFile in UncompressedTestFiles()) + { + yield return new object[] { testFile[0], compressionLevel }; + } + } + } + + [Benchmark(InnerIterationCount=10)] // limits the max iterations to 100 + [MemberData(nameof(UncompressedTestFiles_WithCompressionLevel))] + public void Compress_Canterbury_WithState(string uncompressedFileName, CompressionLevel compressLevel) + { + byte[] bytes = File.ReadAllBytes(uncompressedFileName); + ReadOnlySpan uncompressedData = new ReadOnlySpan(bytes); + int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength(bytes.Length); + byte[] compressedDataArray = new byte[maxCompressedSize]; + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + using (BrotliEncoder encoder = new BrotliEncoder()) + { + Span output = new Span(compressedDataArray); + ReadOnlySpan input = uncompressedData; + while (!input.IsEmpty && !output.IsEmpty) + { + encoder.Compress(input, output, out int bytesConsumed, out int written, isFinalBlock:false); + input = input.Slice(bytesConsumed); + output = output.Slice(written); + } + encoder.Compress(input, output, out int bytesConsumed2, out int written2, isFinalBlock: true); + } + } + } + + [Benchmark(InnerIterationCount=100)] + [MemberData(nameof(UncompressedTestFiles))] + public void Decompress_Canterbury_WithState(string uncompressedFileName) + { + int innerIterations = (int)Benchmark.InnerIterationCount; + byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(uncompressedFileName)); + ReadOnlySpan compressedData = new ReadOnlySpan(compressedBytes); + List uncompressedDataArrays = new List(innerIterations); + foreach (var iteration in Benchmark.Iterations) + { + for (int i = 0; i < innerIterations; i++) + { + uncompressedDataArrays.Add(new byte[65520]); + } + using (iteration.StartMeasurement()) + { + for (int i = 0; i < innerIterations; i++) + { + using (BrotliDecoder decoder = new BrotliDecoder()) + { + Span output = new Span(uncompressedDataArrays[i]); + ReadOnlySpan input = compressedData; + while (!input.IsEmpty && !output.IsEmpty) + { + decoder.Decompress(input, output, out int bytesConsumed, out int written); + input = input.Slice(bytesConsumed); + output = output.Slice(written); + } + } + } + } + } + } + + [Benchmark(InnerIterationCount=10)] // limits the max iterations to 100 + [MemberData(nameof(UncompressedTestFiles_WithCompressionLevel))] + public void Compress_Canterbury_WithoutState(string uncompressedFileName, CompressionLevel compressLevel) + { + byte[] bytes = File.ReadAllBytes(uncompressedFileName); + ReadOnlySpan uncompressedData = new ReadOnlySpan(bytes); + int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength(bytes.Length); + byte[] compressedDataArray = new byte[maxCompressedSize]; + int compressLevelBrotli = compressLevel == CompressionLevel.Optimal ? 11 : compressLevel == CompressionLevel.Fastest ? 1 : 0; + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Assert.True(BrotliEncoder.TryCompress(uncompressedData, compressedDataArray, out int bytesWritten, compressLevelBrotli, 22)); + } + } + } + + /// + /// The perf tests for the instant decompression aren't exactly indicative of real-world scenarios since they require you to know + /// either the exact figure or the upper bound of the uncompressed size of your given compressed data. + /// + [Benchmark(InnerIterationCount=100)] + [MemberData(nameof(UncompressedTestFiles))] + public void Decompress_Canterbury_WithoutState(string uncompressedFileName) + { + int innerIterations = (int)Benchmark.InnerIterationCount; + byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(uncompressedFileName)); + ReadOnlySpan compressedData = new ReadOnlySpan(compressedBytes); + int uncompressedSize = (int)new FileInfo(uncompressedFileName).Length; + List uncompressedDataArrays = new List(innerIterations); + foreach (var iteration in Benchmark.Iterations) + { + for (int i = 0; i < innerIterations; i++) + { + uncompressedDataArrays.Add(new byte[uncompressedSize]); + } + using (iteration.StartMeasurement()) + { + for (int i = 0; i < innerIterations; i++) + { + Assert.True(BrotliDecoder.TryDecompress(compressedData, uncompressedDataArrays[i], out int bytesWritten)); + } + } + } + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/CompressionStreamPerfTests.Brotli.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/CompressionStreamPerfTests.Brotli.cs new file mode 100644 index 000000000000..439f23961c47 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/CompressionStreamPerfTests.Brotli.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.IO.Compression +{ + public class BrotliStreamPerfTests : CompressionStreamPerfTestBase + { + public override Stream CreateStream(Stream stream, CompressionMode mode) => new BrotliStream(stream, mode); + public override Stream CreateStream(Stream stream, CompressionMode mode, bool leaveOpen) => new BrotliStream(stream, mode, leaveOpen); + public override Stream CreateStream(Stream stream, CompressionLevel level) => new BrotliStream(stream, level); + public override Stream CreateStream(Stream stream, CompressionLevel level, bool leaveOpen) => new BrotliStream(stream, level, leaveOpen); + public override Stream BaseStream(Stream stream) => ((BrotliStream)stream).BaseStream; + public override bool FlushCompletes { get => false; } + public override int BufferSize { get => 65520; } + protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br"); + } +} diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/Configurations.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/Configurations.props new file mode 100644 index 000000000000..9b2f102c3a28 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/Configurations.props @@ -0,0 +1,9 @@ + + + + + netcoreapp-Unix; + netcoreapp-Windows_NT; + + + diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj new file mode 100644 index 000000000000..85e6b196f896 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj @@ -0,0 +1,35 @@ + + + + + System.IO.Compression.Brotli.Performance.Tests + true + {1341F8C8-637A-49A1-BE0F-13867A634929} + + + + + + + + + + Common\System\IO\Compression\CompressionStreamTestBase.cs + + + Common\System\IO\Compression\CompressionStreamPerfTestBase.cs + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {69e46a6f-9966-45a5-8945-2559fe337827} + PerfRunner + + + + \ No newline at end of file diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj new file mode 100644 index 000000000000..087a5bcf526d --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj @@ -0,0 +1,44 @@ + + + + + {BC2E1649-291D-412E-9529-EDDA94FA7AD6} + $(DefineConstants);STREAM_MEMORY_OVERLOADS_AVAILABLE + + + + + + + + + + + Common\System\IO\Compression\CompressionStreamTestBase.cs + + + Common\System\IO\Compression\CompressionStreamUnitTestBase.cs + + + Common\System\IO\Compression\LocalMemoryStream.cs + + + Common\System\IO\Compression\StreamHelpers.cs + + + Common\System\IO\TempFile.cs + + + Common\System\Threading\Tasks\TaskToApm.cs + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + + + \ No newline at end of file diff --git a/mcs/class/System.IO.Compression/System.IO.Compression.dll.sources b/mcs/class/System.IO.Compression/System.IO.Compression.dll.sources index 9415ecfbf84c..d2b6ba4254aa 100644 --- a/mcs/class/System.IO.Compression/System.IO.Compression.dll.sources +++ b/mcs/class/System.IO.Compression/System.IO.Compression.dll.sources @@ -38,9 +38,9 @@ corefx/SR.cs ../../../external/corefx/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/OutputWindow.cs # Brotli -../../../external/corefx/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/*.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/*.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/System/IO/Compression/*.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/*.cs -../../../external/corefx/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/*.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/*.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/*.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/*.cs +../../../external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs corefx/Interop.Libraries.cs diff --git a/mcs/class/System.IO.Compression/System.IO.Compression_xtest.dll.sources b/mcs/class/System.IO.Compression/System.IO.Compression_xtest.dll.sources index 7ff2353229a0..52e0ac93c12d 100644 --- a/mcs/class/System.IO.Compression/System.IO.Compression_xtest.dll.sources +++ b/mcs/class/System.IO.Compression/System.IO.Compression_xtest.dll.sources @@ -1,5 +1,5 @@ ../../../external/corefx/src/CoreFx.Private.TestUtilities/src/System/AssertExtensions.cs -../../../external/corefx/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs ../../../external/corefx/src/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs ../../../external/corefx/src/Common/tests/System/IO/Compression/CompressionStreamTestBase.cs ../../../external/corefx/src/Common/tests/System/IO/Compression/LocalMemoryStream.cs diff --git a/mcs/class/System.IO.Compression/wasm_System.IO.Compression.dll.exclude.sources b/mcs/class/System.IO.Compression/wasm_System.IO.Compression.dll.exclude.sources index 7db3f6a7ff30..efd3e97116c8 100644 --- a/mcs/class/System.IO.Compression/wasm_System.IO.Compression.dll.exclude.sources +++ b/mcs/class/System.IO.Compression/wasm_System.IO.Compression.dll.exclude.sources @@ -1,3 +1,3 @@ corefx/Interop.Libraries.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs diff --git a/mcs/class/System.IO.Compression/win32_net_4_x_System.IO.Compression.dll.exclude.sources b/mcs/class/System.IO.Compression/win32_net_4_x_System.IO.Compression.dll.exclude.sources index 7db3f6a7ff30..efd3e97116c8 100644 --- a/mcs/class/System.IO.Compression/win32_net_4_x_System.IO.Compression.dll.exclude.sources +++ b/mcs/class/System.IO.Compression/win32_net_4_x_System.IO.Compression.dll.exclude.sources @@ -1,3 +1,3 @@ corefx/Interop.Libraries.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs diff --git a/mcs/class/System.IO.Compression/winaot_System.IO.Compression.dll.exclude.sources b/mcs/class/System.IO.Compression/winaot_System.IO.Compression.dll.exclude.sources index 7db3f6a7ff30..efd3e97116c8 100644 --- a/mcs/class/System.IO.Compression/winaot_System.IO.Compression.dll.exclude.sources +++ b/mcs/class/System.IO.Compression/winaot_System.IO.Compression.dll.exclude.sources @@ -1,3 +1,3 @@ corefx/Interop.Libraries.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs -../../../external/corefx/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs +../../../external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs