brotli 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +22 -0
- data/ext/brotli/brotli.c +44 -4
- data/lib/brotli/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 69c5177d348df73fc4a46b6885e0432228c9050a0c003daa70ac19ec8a161c33
|
|
4
|
+
data.tar.gz: 80b2f49422f8e77dec0c297f2c74e5d3ee8f326f06f958c86d215f4391150527
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4574d6aaeecfcd073d3bb8bdfa21a766f71843f52d9e7e8446549fb93748a79775a7f296dcf2756e28b796daaef229d696c900d68e159c0dc3cee74357c1b1da
|
|
7
|
+
data.tar.gz: 86002231379c75386cce7da64fadae167c04afb5d635fcc46d1bad0b6137d4921e65736463c8585d6c7c8f6b3818db1a453bf1c7091ab59d482c9d7940f270ae
|
data/README.md
CHANGED
|
@@ -192,6 +192,28 @@ You usually do not need `output_buffer_limit:` when:
|
|
|
192
192
|
- you are using `Brotli::Reader`, which already handles incremental buffering for IO-style reads
|
|
193
193
|
- you are happy for each `#process` call to return all currently available output
|
|
194
194
|
|
|
195
|
+
### Large-window Brotli
|
|
196
|
+
|
|
197
|
+
RFC 9841 large-window streams are rejected by default. Applications that require
|
|
198
|
+
this extension, such as readers of the PDF Association Brotli extension, can opt
|
|
199
|
+
in for a single decoder:
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
Brotli.inflate(compressed, large_window: true)
|
|
203
|
+
Brotli::Reader.new(io, large_window: true)
|
|
204
|
+
Brotli::Decompressor.new(large_window: true)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The option does not enable shared dictionaries or a framing format and does not
|
|
208
|
+
change the default for other decoders.
|
|
209
|
+
|
|
210
|
+
**Memory warning:** with `large_window: true`, the stream header may request a
|
|
211
|
+
window of up to 1 GiB (2^30 bytes), and the decoder allocates its ring buffer
|
|
212
|
+
to match. A small untrusted input can therefore make a single decoder reserve
|
|
213
|
+
close to 1 GiB. `output_buffer_limit:` does not bound this allocation. Enable
|
|
214
|
+
the option only for trusted input, or enforce a memory limit at the process or
|
|
215
|
+
container level.
|
|
216
|
+
|
|
195
217
|
See test/brotli_test.rb for more examples.
|
|
196
218
|
|
|
197
219
|
## Development
|
data/ext/brotli/brotli.c
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
static VALUE rb_eBrotli;
|
|
4
4
|
static ID id_cmp;
|
|
5
5
|
static ID id_dictionary;
|
|
6
|
+
static ID id_large_window;
|
|
6
7
|
static ID id_font;
|
|
7
8
|
static ID id_generic;
|
|
8
9
|
static ID id_lgblock;
|
|
@@ -144,6 +145,13 @@ brotli_inflate_take_result(VALUE arg)
|
|
|
144
145
|
return rb_str_new(args->buffer->ptr, args->buffer->used);
|
|
145
146
|
}
|
|
146
147
|
|
|
148
|
+
static VALUE
|
|
149
|
+
brotli_inflate_run(VALUE arg)
|
|
150
|
+
{
|
|
151
|
+
rb_thread_call_without_gvl(brotli_inflate_no_gvl, (void *)arg, NULL, NULL);
|
|
152
|
+
return Qnil;
|
|
153
|
+
}
|
|
154
|
+
|
|
147
155
|
static VALUE
|
|
148
156
|
brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
149
157
|
{
|
|
@@ -153,6 +161,7 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
|
153
161
|
VALUE dict = Qnil;
|
|
154
162
|
const char *error = NULL;
|
|
155
163
|
brotli_inflate_args_t args = {0};
|
|
164
|
+
int state = 0;
|
|
156
165
|
|
|
157
166
|
(void)self;
|
|
158
167
|
|
|
@@ -178,6 +187,12 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
|
178
187
|
}
|
|
179
188
|
args.r = BROTLI_DECODER_RESULT_ERROR;
|
|
180
189
|
|
|
190
|
+
if (RTEST(brotli_hash_lookup(opts, id_large_window)) &&
|
|
191
|
+
!BrotliDecoderSetParameter(args.s, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1)) {
|
|
192
|
+
brotli_inflate_cleanup(&args);
|
|
193
|
+
rb_raise(rb_eBrotli, "Failed to enable large-window decompression");
|
|
194
|
+
}
|
|
195
|
+
|
|
181
196
|
if (!NIL_P(dict)) {
|
|
182
197
|
args.dict = (uint8_t*)RSTRING_PTR(dict);
|
|
183
198
|
args.dict_len = (size_t)RSTRING_LEN(dict);
|
|
@@ -186,9 +201,18 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
|
186
201
|
args.dict_len = 0;
|
|
187
202
|
}
|
|
188
203
|
|
|
189
|
-
|
|
204
|
+
/*
|
|
205
|
+
* rb_thread_call_without_gvl() handles pending interrupts (Thread#raise,
|
|
206
|
+
* Timeout, signals) around the worker and may raise from there. Catch it
|
|
207
|
+
* so the decoder state and output buffer are released before re-raising.
|
|
208
|
+
*/
|
|
209
|
+
rb_protect(brotli_inflate_run, (VALUE)&args, &state);
|
|
190
210
|
RB_GC_GUARD(str);
|
|
191
211
|
RB_GC_GUARD(dict);
|
|
212
|
+
if (state) {
|
|
213
|
+
brotli_inflate_cleanup(&args);
|
|
214
|
+
rb_jump_tag(state);
|
|
215
|
+
}
|
|
192
216
|
|
|
193
217
|
/* Check before args.r: a failed final append leaves r at SUCCESS. */
|
|
194
218
|
if (args.oom) {
|
|
@@ -197,7 +221,6 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
|
197
221
|
}
|
|
198
222
|
|
|
199
223
|
if (args.r == BROTLI_DECODER_RESULT_SUCCESS) {
|
|
200
|
-
int state = 0;
|
|
201
224
|
value = rb_protect(brotli_inflate_take_result, (VALUE)&args, &state);
|
|
202
225
|
if (state) {
|
|
203
226
|
brotli_inflate_cleanup(&args);
|
|
@@ -406,6 +429,13 @@ brotli_deflate_take_result(VALUE arg)
|
|
|
406
429
|
return rb_str_new(args->buffer->ptr, args->buffer->used);
|
|
407
430
|
}
|
|
408
431
|
|
|
432
|
+
static VALUE
|
|
433
|
+
brotli_deflate_run(VALUE arg)
|
|
434
|
+
{
|
|
435
|
+
rb_thread_call_without_gvl(brotli_deflate_no_gvl, (void *)arg, NULL, NULL);
|
|
436
|
+
return Qnil;
|
|
437
|
+
}
|
|
438
|
+
|
|
409
439
|
static VALUE
|
|
410
440
|
brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
411
441
|
{
|
|
@@ -416,6 +446,7 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
|
416
446
|
brotli_deflate_args_t args = {0};
|
|
417
447
|
size_t max_compressed_size;
|
|
418
448
|
const char *err;
|
|
449
|
+
int state = 0;
|
|
419
450
|
|
|
420
451
|
(void)self;
|
|
421
452
|
|
|
@@ -465,15 +496,19 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
|
465
496
|
}
|
|
466
497
|
}
|
|
467
498
|
|
|
468
|
-
|
|
499
|
+
/* See brotli_inflate: an interrupt may raise out of the GVL release. */
|
|
500
|
+
rb_protect(brotli_deflate_run, (VALUE)&args, &state);
|
|
469
501
|
RB_GC_GUARD(str);
|
|
470
502
|
RB_GC_GUARD(dict);
|
|
503
|
+
if (state) {
|
|
504
|
+
brotli_deflate_cleanup(&args);
|
|
505
|
+
rb_jump_tag(state);
|
|
506
|
+
}
|
|
471
507
|
if (args.oom) {
|
|
472
508
|
brotli_deflate_cleanup(&args);
|
|
473
509
|
rb_raise(rb_eNoMemError, "failed to allocate compression buffer");
|
|
474
510
|
}
|
|
475
511
|
if (args.finished == BROTLI_TRUE) {
|
|
476
|
-
int state = 0;
|
|
477
512
|
value = rb_protect(brotli_deflate_take_result, (VALUE)&args, &state);
|
|
478
513
|
if (state) {
|
|
479
514
|
brotli_deflate_cleanup(&args);
|
|
@@ -971,6 +1006,10 @@ rb_decompressor_initialize(int argc, VALUE* argv, VALUE self)
|
|
|
971
1006
|
rb_scan_args(argc, argv, "01", &opts);
|
|
972
1007
|
TypedData_Get_Struct(self, brotli_decompressor_t, &brotli_decompressor_data_type, br);
|
|
973
1008
|
brotli_decompressor_reset(self, br);
|
|
1009
|
+
if (RTEST(brotli_hash_lookup(opts, id_large_window)) &&
|
|
1010
|
+
!BrotliDecoderSetParameter(br->state, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1)) {
|
|
1011
|
+
rb_raise(rb_eBrotli, "Failed to enable large-window decompression");
|
|
1012
|
+
}
|
|
974
1013
|
brotli_decompressor_attach_dictionary(br, opts);
|
|
975
1014
|
|
|
976
1015
|
return self;
|
|
@@ -1216,6 +1255,7 @@ Init_brotli(void)
|
|
|
1216
1255
|
rb_define_singleton_method(rb_mBrotli, "version", brotli_version, 0);
|
|
1217
1256
|
id_cmp = rb_intern("<=>");
|
|
1218
1257
|
id_dictionary = rb_intern("dictionary");
|
|
1258
|
+
id_large_window = rb_intern("large_window");
|
|
1219
1259
|
id_font = rb_intern("font");
|
|
1220
1260
|
id_generic = rb_intern("generic");
|
|
1221
1261
|
id_lgblock = rb_intern("lgblock");
|
data/lib/brotli/version.rb
CHANGED