Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build-node-openssl-fips.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ jobs:
path: artifacts/${{ env.NODE_ARCHIVE_LATEST }}

- name: Upload Node archive to release
# Keep branch builds in run-scoped artifacts so they cannot replace the
# shared release used by the regular Node 22 build process.
if: github.ref == 'refs/heads/v22.21.1'
uses: softprops/action-gh-release@v1
with:
name: node-${{ env.NODE_VERSION }}-fips-LATEST
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/build-node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ jobs:
path: artifacts/${{ env.NODE_ARCHIVE_LATEST }}

- name: Upload Node archive to release
# Keep branch builds in run-scoped artifacts so they cannot replace the
# shared release used by fibers and native-package builds.
if: github.ref == 'refs/heads/v22.21.1'
uses: softprops/action-gh-release@v1
with:
name: node-${{ env.NODE_VERSION }}-LATEST
Expand Down
87 changes: 58 additions & 29 deletions deps/brotli/c/dec/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ static BrotliDecoderErrorCode DecodeContextMap(brotli_reg_t context_map_size,

/* Decodes a command or literal and updates block type ring-buffer.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
static BROTLI_INLINE BrotliDecoderErrorCode DecodeBlockTypeAndLength(
int safe, BrotliDecoderState* s, int tree_type) {
brotli_reg_t max_block_type = s->num_block_types[tree_type];
const HuffmanCode* type_tree = &s->block_type_trees[
Expand All @@ -1135,7 +1135,7 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];
brotli_reg_t block_type;
if (max_block_type <= 1) {
return BROTLI_FALSE;
return BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH;
}

/* Read 0..15 + 3..39 bits. */
Expand All @@ -1145,11 +1145,13 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
} else {
BrotliBitReaderState memento;
BrotliBitReaderSaveState(br, &memento);
if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;
if (!SafeReadSymbol(type_tree, br, &block_type)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
BrotliBitReaderRestoreState(br, &memento);
return BROTLI_FALSE;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
}

Expand All @@ -1165,7 +1167,7 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
}
ringbuffer[0] = ringbuffer[1];
ringbuffer[1] = block_type;
return BROTLI_TRUE;
return BROTLI_DECODER_SUCCESS;
}

static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(
Expand Down Expand Up @@ -1202,59 +1204,65 @@ static BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {

/* Decodes the block type and updates the state for literal context.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(
static BROTLI_INLINE BrotliDecoderErrorCode DecodeLiteralBlockSwitchInternal(
int safe, BrotliDecoderState* s) {
if (!DecodeBlockTypeAndLength(safe, s, 0)) {
return BROTLI_FALSE;
BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 0);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
PrepareLiteralDecoding(s);
return BROTLI_TRUE;
return BROTLI_DECODER_SUCCESS;
}

static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
DecodeLiteralBlockSwitchInternal(0, s);
static BROTLI_NOINLINE BrotliDecoderErrorCode
DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
return DecodeLiteralBlockSwitchInternal(0, s);
}

static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(
static BROTLI_NOINLINE BrotliDecoderErrorCode SafeDecodeLiteralBlockSwitch(
BrotliDecoderState* s) {
return DecodeLiteralBlockSwitchInternal(1, s);
}

/* Block switch for insert/copy length.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(
static BROTLI_INLINE BrotliDecoderErrorCode DecodeCommandBlockSwitchInternal(
int safe, BrotliDecoderState* s) {
if (!DecodeBlockTypeAndLength(safe, s, 1)) {
return BROTLI_FALSE;
BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 1);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];
return BROTLI_TRUE;
return BROTLI_DECODER_SUCCESS;
}

static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {
DecodeCommandBlockSwitchInternal(0, s);
static BROTLI_NOINLINE BrotliDecoderErrorCode
DecodeCommandBlockSwitch(BrotliDecoderState* s) {
return DecodeCommandBlockSwitchInternal(0, s);
}

static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(
BrotliDecoderState* s) {
static BROTLI_NOINLINE BrotliDecoderErrorCode
SafeDecodeCommandBlockSwitch(BrotliDecoderState* s) {
return DecodeCommandBlockSwitchInternal(1, s);
}

/* Block switch for distance codes.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(
static BROTLI_INLINE BrotliDecoderErrorCode DecodeDistanceBlockSwitchInternal(
int safe, BrotliDecoderState* s) {
if (!DecodeBlockTypeAndLength(safe, s, 2)) {
return BROTLI_FALSE;
BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 2);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
s->dist_context_map_slice = s->dist_context_map +
(s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);
s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
return BROTLI_TRUE;
return BROTLI_DECODER_SUCCESS;
}

static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
DecodeDistanceBlockSwitchInternal(0, s);
static BROTLI_NOINLINE BrotliDecoderErrorCode
DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
return DecodeDistanceBlockSwitchInternal(0, s);
}

static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(
Expand Down Expand Up @@ -1887,6 +1895,9 @@ static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
return BrotliCheckInputAmount(br);
}

/* NB: METHOD should return BROTLI_FALSE only in case there is not enough input;
in case of "unsafe" execution, when input is guaranteed to be sufficient,
result is ignored. */
#define BROTLI_SAFE(METHOD) \
{ \
if (safe) { \
Expand All @@ -1899,6 +1910,22 @@ static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
} \
}

/* NB: METHOD should return BROTLI_DECODER_SUCCESS, BROTLI_DECODER_ERROR_*, or
BROTLI_DECODER_NEEDS_MORE_INPUT; the later two break the processing. */
#define BROTLI_SAFE_WITH_STATUS(METHOD) \
{ \
BrotliDecoderErrorCode status; \
if (safe) { \
status = Safe##METHOD; \
} else { \
status = METHOD; \
} \
if (status != BROTLI_DECODER_SUCCESS) { \
result = status; \
goto saveStateAndReturn; \
} \
}

static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
int safe, BrotliDecoderState* s) {
int pos = s->pos;
Expand Down Expand Up @@ -1938,7 +1965,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
goto saveStateAndReturn;
}
if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {
BROTLI_SAFE(DecodeCommandBlockSwitch(s));
BROTLI_SAFE_WITH_STATUS(DecodeCommandBlockSwitch(s));
goto CommandBegin;
}
/* Read the insert/copy length in the command. */
Expand Down Expand Up @@ -2046,7 +2073,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
} else {
/* Read distance code in the command, unless it was implicitly zero. */
if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {
BROTLI_SAFE(DecodeDistanceBlockSwitch(s));
BROTLI_SAFE_WITH_STATUS(DecodeDistanceBlockSwitch(s));
}
BROTLI_SAFE(ReadDistance(s, br));
}
Expand Down Expand Up @@ -2240,7 +2267,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
}

NextLiteralBlock:
BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
BROTLI_SAFE_WITH_STATUS(DecodeLiteralBlockSwitch(s));
goto CommandInner;

saveStateAndReturn:
Expand Down Expand Up @@ -2462,6 +2489,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
BROTLI_DCHECK(s->meta_block_remaining_len <=
(int)BROTLI_BLOCK_SIZE_CAP);
BROTLI_LOG_UINT(s->is_last_metablock);
BROTLI_LOG_UINT(s->meta_block_remaining_len);
BROTLI_LOG_UINT(s->is_metadata);
Expand Down
4 changes: 1 addition & 3 deletions deps/brotli/c/include/brotli/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@ typedef enum {
BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \
BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \
BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \
\
/* -17 code is reserved */ \
\
BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_SWITCH, -17) SEPARATOR \
BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \
BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \
BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \
Expand Down
1 change: 1 addition & 0 deletions src/node_zlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,7 @@ void DefineZlibConstants(Local<Object> target) {
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_PADDING_1);
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_PADDING_2);
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_DISTANCE);
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH);
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_INVALID_ARGUMENTS);
NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);
Expand Down
27 changes: 27 additions & 0 deletions test/parallel/test-zlib-invalid-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ nonStringInputs.forEach(common.mustCall((input) => {
});
}, nonStringInputs.length));

{
// A block switch is invalid when the stream declares only one block type.
const invalidBlockSwitch = Buffer.from(
'200010414141fcffff07002228f00b60f7f41f000000',
'hex',
);
const expectedError = {
code: 'ERR__ERROR_FORMAT_BLOCK_SWITCH',
errno: zlib.constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH,
};

assert.strictEqual(expectedError.errno, -17);
assert.throws(
() => zlib.brotliDecompressSync(invalidBlockSwitch),
expectedError,
);

const brotli = zlib.createBrotliDecompress();
brotli.resume();
brotli.on('error', common.expectsError(expectedError));
brotli.on('end', common.mustNotCall());
for (let i = 0; i < invalidBlockSwitch.length; i++) {
brotli.write(invalidBlockSwitch.subarray(i, i + 1));
}
brotli.end();
}

unzips.forEach(common.mustCall((uz, i) => {
uz.on('error', common.mustCall());
uz.on('end', common.mustNotCall());
Expand Down
Loading