brotli 0.9.1 → 0.9.2
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/ext/brotli/brotli.c +32 -3
- data/ext/brotli/buffer.c +35 -11
- data/ext/brotli/buffer.h +3 -1
- data/ext/brotli/extconf.rb +14 -0
- 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: 035e04e32804b36b5525cf4ba7688e19a199288e0056fcfceeeac67f11f72c9f
|
|
4
|
+
data.tar.gz: 8ce5e925a781060c0d46dfebd69beb367c62622fb808ef247906e0bf2229aaa8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 70c2bdf0f5028d80f5f0c578f89bf2c6818de1c9c4f795fe61aeeffbbcf570353d97699ce02f9e44e713f54e34fd9c0a745d9b6f3ef9e7f9b62e5ffc6f1b0707
|
|
7
|
+
data.tar.gz: dd17edfde50109928ca623452044288b6d369cd6a29706727248623f8ad6d03ea89857fd668e67ca01b22a1baf39b27fbd47c86635a2455ec1c1d2400c4c5d77
|
data/ext/brotli/brotli.c
CHANGED
|
@@ -74,6 +74,7 @@ typedef struct {
|
|
|
74
74
|
BrotliDecoderResult r;
|
|
75
75
|
uint8_t* dict;
|
|
76
76
|
size_t dict_len;
|
|
77
|
+
int oom;
|
|
77
78
|
} brotli_inflate_args_t;
|
|
78
79
|
|
|
79
80
|
static void
|
|
@@ -116,14 +117,19 @@ brotli_inflate_no_gvl(void *arg)
|
|
|
116
117
|
if (r != BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
|
117
118
|
break;
|
|
118
119
|
}
|
|
119
|
-
append_buffer(buffer, output, BUFSIZ)
|
|
120
|
+
if (append_buffer(buffer, output, BUFSIZ) != 0) {
|
|
121
|
+
args->oom = 1;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
120
124
|
available_out = BUFSIZ;
|
|
121
125
|
next_out = output;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
if (r == BROTLI_DECODER_RESULT_SUCCESS) {
|
|
125
129
|
if (next_out != output) {
|
|
126
|
-
append_buffer(buffer, output, next_out - output)
|
|
130
|
+
if (append_buffer(buffer, output, next_out - output) != 0) {
|
|
131
|
+
args->oom = 1;
|
|
132
|
+
}
|
|
127
133
|
}
|
|
128
134
|
}
|
|
129
135
|
args->r = r;
|
|
@@ -166,6 +172,10 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
|
166
172
|
args.len = (size_t)RSTRING_LEN(str);
|
|
167
173
|
args.s = brotli_decoder_state_create();
|
|
168
174
|
args.buffer = create_buffer(BUFSIZ);
|
|
175
|
+
if (!args.buffer) {
|
|
176
|
+
brotli_inflate_cleanup(&args);
|
|
177
|
+
rb_raise(rb_eNoMemError, "failed to allocate decompression buffer");
|
|
178
|
+
}
|
|
169
179
|
args.r = BROTLI_DECODER_RESULT_ERROR;
|
|
170
180
|
|
|
171
181
|
if (!NIL_P(dict)) {
|
|
@@ -180,6 +190,12 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
|
|
|
180
190
|
RB_GC_GUARD(str);
|
|
181
191
|
RB_GC_GUARD(dict);
|
|
182
192
|
|
|
193
|
+
/* Check before args.r: a failed final append leaves r at SUCCESS. */
|
|
194
|
+
if (args.oom) {
|
|
195
|
+
brotli_inflate_cleanup(&args);
|
|
196
|
+
rb_raise(rb_eNoMemError, "failed to allocate decompression buffer");
|
|
197
|
+
}
|
|
198
|
+
|
|
183
199
|
if (args.r == BROTLI_DECODER_RESULT_SUCCESS) {
|
|
184
200
|
int state = 0;
|
|
185
201
|
value = rb_protect(brotli_inflate_take_result, (VALUE)&args, &state);
|
|
@@ -324,6 +340,7 @@ typedef struct {
|
|
|
324
340
|
buffer_t* buffer;
|
|
325
341
|
BROTLI_BOOL finished;
|
|
326
342
|
BrotliEncoderPreparedDictionary* prepared_dict;
|
|
343
|
+
int oom;
|
|
327
344
|
} brotli_deflate_args_t;
|
|
328
345
|
|
|
329
346
|
static void
|
|
@@ -364,7 +381,11 @@ brotli_deflate_no_gvl(void *arg)
|
|
|
364
381
|
args->finished = BROTLI_FALSE;
|
|
365
382
|
break;
|
|
366
383
|
} else {
|
|
367
|
-
append_buffer(buffer, output, next_out - output)
|
|
384
|
+
if (append_buffer(buffer, output, next_out - output) != 0) {
|
|
385
|
+
args->oom = 1;
|
|
386
|
+
args->finished = BROTLI_FALSE;
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
368
389
|
available_out = BUFSIZ;
|
|
369
390
|
next_out = output;
|
|
370
391
|
|
|
@@ -418,6 +439,10 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
|
418
439
|
}
|
|
419
440
|
max_compressed_size = BrotliEncoderMaxCompressedSize(args.len);
|
|
420
441
|
args.buffer = create_buffer(max_compressed_size);
|
|
442
|
+
if (!args.buffer) {
|
|
443
|
+
brotli_deflate_cleanup(&args);
|
|
444
|
+
rb_raise(rb_eNoMemError, "failed to allocate compression buffer");
|
|
445
|
+
}
|
|
421
446
|
args.finished = BROTLI_FALSE;
|
|
422
447
|
|
|
423
448
|
args.prepared_dict = NULL;
|
|
@@ -443,6 +468,10 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
|
443
468
|
rb_thread_call_without_gvl(brotli_deflate_no_gvl, &args, NULL, NULL);
|
|
444
469
|
RB_GC_GUARD(str);
|
|
445
470
|
RB_GC_GUARD(dict);
|
|
471
|
+
if (args.oom) {
|
|
472
|
+
brotli_deflate_cleanup(&args);
|
|
473
|
+
rb_raise(rb_eNoMemError, "failed to allocate compression buffer");
|
|
474
|
+
}
|
|
446
475
|
if (args.finished == BROTLI_TRUE) {
|
|
447
476
|
int state = 0;
|
|
448
477
|
value = rb_protect(brotli_deflate_take_result, (VALUE)&args, &state);
|
data/ext/brotli/buffer.c
CHANGED
|
@@ -1,18 +1,32 @@
|
|
|
1
1
|
#include "buffer.h"
|
|
2
|
-
#include "ruby/ruby.h"
|
|
3
2
|
|
|
4
3
|
#include <stdint.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
5
|
#include <string.h>
|
|
6
6
|
|
|
7
7
|
#define BUFFER_INITIAL_SIZE 1024
|
|
8
8
|
|
|
9
|
+
/*
|
|
10
|
+
* append_buffer runs inside rb_thread_call_without_gvl. A failing Ruby
|
|
11
|
+
* allocator there raises NoMemoryError past the caller's cleanup, so this
|
|
12
|
+
* buffer uses malloc/realloc/free and reports failure through return values.
|
|
13
|
+
*/
|
|
14
|
+
|
|
9
15
|
buffer_t*
|
|
10
16
|
create_buffer(size_t initial)
|
|
11
17
|
{
|
|
12
|
-
buffer_t *buffer =
|
|
18
|
+
buffer_t *buffer = malloc(sizeof(*buffer));
|
|
19
|
+
|
|
20
|
+
if (!buffer) {
|
|
21
|
+
return NULL;
|
|
22
|
+
}
|
|
13
23
|
buffer->used = 0;
|
|
14
24
|
buffer->size = initial > 0 ? initial : BUFFER_INITIAL_SIZE;
|
|
15
|
-
buffer->ptr =
|
|
25
|
+
buffer->ptr = malloc(buffer->size);
|
|
26
|
+
if (!buffer->ptr) {
|
|
27
|
+
free(buffer);
|
|
28
|
+
return NULL;
|
|
29
|
+
}
|
|
16
30
|
return buffer;
|
|
17
31
|
}
|
|
18
32
|
|
|
@@ -23,8 +37,8 @@ delete_buffer(buffer_t* buffer)
|
|
|
23
37
|
return;
|
|
24
38
|
}
|
|
25
39
|
|
|
26
|
-
|
|
27
|
-
|
|
40
|
+
free(buffer->ptr);
|
|
41
|
+
free(buffer);
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
static size_t
|
|
@@ -42,27 +56,37 @@ buffer_size_for(size_t current, size_t required)
|
|
|
42
56
|
return size;
|
|
43
57
|
}
|
|
44
58
|
|
|
45
|
-
static
|
|
59
|
+
static int
|
|
46
60
|
expand_buffer(buffer_t* buffer, size_t required)
|
|
47
61
|
{
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
size_t size = buffer_size_for(buffer->size, required);
|
|
63
|
+
char* ptr = realloc(buffer->ptr, size);
|
|
64
|
+
|
|
65
|
+
if (!ptr) {
|
|
66
|
+
return -1;
|
|
67
|
+
}
|
|
68
|
+
buffer->ptr = ptr;
|
|
69
|
+
buffer->size = size;
|
|
70
|
+
return 0;
|
|
50
71
|
}
|
|
51
72
|
|
|
52
|
-
|
|
73
|
+
int
|
|
53
74
|
append_buffer(buffer_t* buffer, const void* ptr, size_t size)
|
|
54
75
|
{
|
|
55
76
|
size_t required;
|
|
56
77
|
|
|
57
78
|
if (size == 0) {
|
|
58
|
-
return;
|
|
79
|
+
return 0;
|
|
59
80
|
}
|
|
60
81
|
|
|
61
82
|
required = buffer->used + size;
|
|
62
83
|
if (required > buffer->size) {
|
|
63
|
-
expand_buffer(buffer, required)
|
|
84
|
+
if (expand_buffer(buffer, required) != 0) {
|
|
85
|
+
return -1;
|
|
86
|
+
}
|
|
64
87
|
}
|
|
65
88
|
|
|
66
89
|
memcpy(buffer->ptr + buffer->used, ptr, size);
|
|
67
90
|
buffer->used += size;
|
|
91
|
+
return 0;
|
|
68
92
|
}
|
data/ext/brotli/buffer.h
CHANGED
|
@@ -9,8 +9,10 @@ typedef struct {
|
|
|
9
9
|
size_t used;
|
|
10
10
|
} buffer_t;
|
|
11
11
|
|
|
12
|
+
/* Never raise, so they are safe without the GVL. create_buffer returns NULL
|
|
13
|
+
* and append_buffer returns -1 when allocation fails. */
|
|
12
14
|
buffer_t* create_buffer(size_t initial);
|
|
13
15
|
void delete_buffer(buffer_t* buffer);
|
|
14
|
-
|
|
16
|
+
int append_buffer(buffer_t* buffer, const void* ptr, size_t size);
|
|
15
17
|
|
|
16
18
|
#endif /* BUFFER_H */
|
data/ext/brotli/extconf.rb
CHANGED
|
@@ -129,5 +129,19 @@ if use_vendored_brotli
|
|
|
129
129
|
$INCFLAGS << " -Ienc -Idec -Icommon -Iinclude"
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
+
# Leak-harness build hooks (inert unless the env var is set).
|
|
133
|
+
# One append reaches brotli.c, buffer.c, and the vendored sources, because
|
|
134
|
+
# add_vendored_sources_to_makefile rewrites ORIG_SRCS/OBJS after create_makefile.
|
|
135
|
+
if ENV["BROTLI_DEBUG"] || ENV["BROTLI_ASAN"]
|
|
136
|
+
# Append -O0 last so it overrides any earlier optimization flag already in
|
|
137
|
+
# $CFLAGS (-O2/-O3/-Os/-Ofast/bare -O) -- the last -O on the command line wins
|
|
138
|
+
# for both gcc and clang. A gsub(/-O\d/) would miss -Os/-Ofast/-O.
|
|
139
|
+
$CFLAGS << " -O0 -g3 -fno-omit-frame-pointer"
|
|
140
|
+
end
|
|
141
|
+
if ENV["BROTLI_ASAN"]
|
|
142
|
+
$CFLAGS << " -fsanitize=address"
|
|
143
|
+
$LDFLAGS << " -fsanitize=address"
|
|
144
|
+
end
|
|
145
|
+
|
|
132
146
|
create_makefile("brotli/brotli")
|
|
133
147
|
add_vendored_sources_to_makefile if use_vendored_brotli
|
data/lib/brotli/version.rb
CHANGED