summaryrefslogtreecommitdiff
path: root/app-arch/brotli/files/brotli-1.2.0-detect-invalid-stream.patch
blob: 92eaa594c38f5915cf2acce76a385e6307e57590 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
https://github.com/google/brotli/commit/0ed4268a4401abcb4472096340477cf4af7d1a2b
From: Evgenii Kliuchnikov <eustas@google.com>
Date: Fri, 27 Feb 2026 05:10:32 -0800
Subject: [PATCH] Detect and report invalid stream earlier.

PiperOrigin-RevId: 876198329
--- a/c/dec/decode.c
+++ b/c/dec/decode.c
@@ -1176,7 +1176,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[
@@ -1187,7 +1187,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. */
@@ -1197,11 +1197,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;
     }
   }

@@ -1217,7 +1219,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(
@@ -1254,59 +1256,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(
@@ -1940,6 +1948,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) {                                   \
@@ -1952,6 +1963,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;
@@ -1991,7 +2018,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. */
@@ -2136,7 +2163,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));
   }
@@ -2330,7 +2357,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
   }

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

 saveStateAndReturn:
@@ -2552,6 +2579,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);
--- a/c/include/brotli/decode.h
+++ b/c/include/brotli/decode.h
@@ -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             \