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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05ff932639bf540d1187af86b6fedc95bbda8bbdfecee33631a6d8fb279c3c4f
4
- data.tar.gz: d5041a8558bddb2935739372f95fa2c3a145155ac7fa1c0482f01048b20489ab
3
+ metadata.gz: 035e04e32804b36b5525cf4ba7688e19a199288e0056fcfceeeac67f11f72c9f
4
+ data.tar.gz: 8ce5e925a781060c0d46dfebd69beb367c62622fb808ef247906e0bf2229aaa8
5
5
  SHA512:
6
- metadata.gz: 3f4cb09e9781d26a84bc7395a599f4ae5978c590aa67e7ecb56699d20e5a0834851d14330a09cad9213c42e42bd1c31ee387a030882da60835c788777f77ec69
7
- data.tar.gz: 89156626b80f23ff447e51fd903f1b94e63952a1fa6ed9b53b08272287a6c22ca40f81e1f17155a242a28da9739a07f2c4b7fa4a8305807870abb8e2d6d6a0e9
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 = ruby_xmalloc(sizeof(*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 = ruby_xmalloc(buffer->size);
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
- ruby_xfree(buffer->ptr);
27
- ruby_xfree(buffer);
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 void
59
+ static int
46
60
  expand_buffer(buffer_t* buffer, size_t required)
47
61
  {
48
- buffer->size = buffer_size_for(buffer->size, required);
49
- buffer->ptr = ruby_xrealloc(buffer->ptr, buffer->size);
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
- void
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
- void append_buffer(buffer_t* buffer, const void* ptr, size_t size);
16
+ int append_buffer(buffer_t* buffer, const void* ptr, size_t size);
15
17
 
16
18
  #endif /* BUFFER_H */
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Brotli
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brotli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - miyucy