commonmarker 0.23.2 → 0.23.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of commonmarker might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9994d57ada57273f14d8098d2dbce3c923adf271fd7cbbc57d617cd3b78922a
4
- data.tar.gz: 49911d1ce9bf022eb5b6f4698da9d3839476c20dffc2d2a3910784b483d74481
3
+ metadata.gz: bc6d71b6e85fb61abc438252b07369d3264982cf8fb327d96e5e8333bb23841e
4
+ data.tar.gz: 1911965561ddf20104db09c44c4e5d25f65a277a28b825bc0c03bb172779a623
5
5
  SHA512:
6
- metadata.gz: a79d35be4e6046cc07ba6061ef8f3563ae31a78ee24e114675cf98c1188c13b40bec8eed1265ccd11ae39eef6032bc91d57ce8254f9b676f198c2a057c6ea7d3
7
- data.tar.gz: bb887c9aa1d34dc200622b001b6a09ecb53625807de66a226331afe090db4d2d61fd5edce9be7b61fdd27e23ed1c8a70b41089f088e93936115b9f517b6bef03
6
+ metadata.gz: 59737cb433c3f4f3d53e06d3466f1f3dcd8a40e201e8b0f26be4d553f45667137e05d980100304e720d0e8fda178da3eaa9e421608cf4e53c6d159ff9261ae3e
7
+ data.tar.gz: c3088c3219da29bdb0356f46a5b7a7f2881410c825e101f7ced3964760bfcfcb5cef57e7f3ebf5bd9f686b974ad80887fc93899e616afb211dc0e648d6352cd2
data/bin/commonmarker CHANGED
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'optparse'
5
- require 'ostruct'
6
5
 
7
6
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
8
7
  require 'commonmarker'
@@ -11,17 +10,13 @@ root = File.expand_path('..', __dir__)
11
10
  $LOAD_PATH.unshift File.expand_path('lib', root)
12
11
 
13
12
  def parse_options
14
- options = OpenStruct.new
13
+ options = Struct.new(:active_extensions, :active_parse_options, :active_render_options, :output_format, :renderer)
14
+ .new([], [:DEFAULT], [:DEFAULT], :html)
15
15
  extensions = CommonMarker.extensions
16
16
  parse_options = CommonMarker::Config::OPTS.fetch(:parse)
17
17
  render_options = CommonMarker::Config::OPTS.fetch(:render)
18
18
  format_options = CommonMarker::Config::OPTS.fetch(:format)
19
19
 
20
- options.active_extensions = []
21
- options.active_parse_options = [:DEFAULT]
22
- options.active_render_options = [:DEFAULT]
23
- options.output_format = :html
24
-
25
20
  option_parser = OptionParser.new do |opts|
26
21
  opts.banner = 'Usage: commonmarker [--html-renderer] [--extension=EXTENSION]'
27
22
  opts.separator ' [--to=FORMAT]'
data/commonmarker.gemspec CHANGED
@@ -23,6 +23,8 @@ Gem::Specification.new do |s|
23
23
  s.require_paths = %w[lib ext]
24
24
  s.required_ruby_version = ['>= 2.6', '< 4.0']
25
25
 
26
+ s.metadata['rubygems_mfa_required'] = 'true'
27
+
26
28
  s.rdoc_options += ['-x', 'ext/commonmarker/cmark/.*']
27
29
 
28
30
  s.add_development_dependency 'awesome_print'
@@ -1,7 +1,7 @@
1
1
  #ifndef CMARK_GFM_VERSION_H
2
2
  #define CMARK_GFM_VERSION_H
3
3
 
4
- #define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 2)
5
- #define CMARK_GFM_VERSION_STRING "0.29.0.gfm.2"
4
+ #define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 3)
5
+ #define CMARK_GFM_VERSION_STRING "0.29.0.gfm.3"
6
6
 
7
7
  #endif
@@ -115,25 +115,23 @@ static void rb_parent_removed(VALUE val) {
115
115
  RDATA(val)->dfree = rb_free_c_struct;
116
116
  }
117
117
 
118
- static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions, cmark_mem *mem) {
118
+ static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions) {
119
119
  int options;
120
- int extensions_len;
121
120
  VALUE rb_ext_name;
122
121
  int i;
123
122
 
124
- Check_Type(rb_options, T_FIXNUM);
123
+ FIXNUM_P(rb_options);
124
+ options = FIX2INT(rb_options);
125
+
125
126
  Check_Type(rb_extensions, T_ARRAY);
126
127
 
127
- options = FIX2INT(rb_options);
128
- extensions_len = RARRAY_LEN(rb_extensions);
128
+ cmark_parser *parser = cmark_parser_new(options);
129
129
 
130
- cmark_parser *parser = cmark_parser_new_with_mem(options, mem);
131
- for (i = 0; i < extensions_len; ++i) {
132
- rb_ext_name = RARRAY_PTR(rb_extensions)[i];
130
+ for (i = 0; i < RARRAY_LEN(rb_extensions); ++i) {
131
+ rb_ext_name = rb_ary_entry(rb_extensions, i);
133
132
 
134
133
  if (!SYMBOL_P(rb_ext_name)) {
135
134
  cmark_parser_free(parser);
136
- cmark_arena_reset();
137
135
  rb_raise(rb_eTypeError, "extension names should be Symbols; got a %"PRIsVALUE"", rb_obj_class(rb_ext_name));
138
136
  }
139
137
 
@@ -142,7 +140,6 @@ static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions, cmark
142
140
 
143
141
  if (!syntax_extension) {
144
142
  cmark_parser_free(parser);
145
- cmark_arena_reset();
146
143
  rb_raise(rb_eArgError, "extension %s not found", rb_id2name(SYM2ID(rb_ext_name)));
147
144
  }
148
145
 
@@ -157,33 +154,28 @@ static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions, cmark
157
154
  *
158
155
  */
159
156
  static VALUE rb_markdown_to_html(VALUE self, VALUE rb_text, VALUE rb_options, VALUE rb_extensions) {
160
- char *str, *html;
161
- int len;
157
+ char *html;
162
158
  cmark_parser *parser;
163
159
  cmark_node *doc;
164
- Check_Type(rb_text, T_STRING);
165
- Check_Type(rb_options, T_FIXNUM);
166
160
 
167
- parser = prepare_parser(rb_options, rb_extensions, cmark_get_arena_mem_allocator());
161
+ Check_Type(rb_text, T_STRING);
168
162
 
169
- str = (char *)RSTRING_PTR(rb_text);
170
- len = RSTRING_LEN(rb_text);
163
+ parser = prepare_parser(rb_options, rb_extensions);
171
164
 
172
- cmark_parser_feed(parser, str, len);
165
+ cmark_parser_feed(parser, StringValuePtr(rb_text), RSTRING_LEN(rb_text));
173
166
  doc = cmark_parser_finish(parser);
167
+
174
168
  if (doc == NULL) {
175
- cmark_arena_reset();
169
+ cmark_parser_free(parser);
176
170
  rb_raise(rb_eNodeError, "error parsing document");
177
171
  }
178
172
 
179
- cmark_mem *default_mem = cmark_get_default_mem_allocator();
180
- html = cmark_render_html_with_mem(doc, FIX2INT(rb_options), parser->syntax_extensions, default_mem);
181
- cmark_arena_reset();
173
+ html = cmark_render_html(doc, parser->options, parser->syntax_extensions);
182
174
 
183
- VALUE ruby_html = rb_str_new2(html);
184
- default_mem->free(html);
175
+ cmark_parser_free(parser);
176
+ cmark_node_free(doc);
185
177
 
186
- return ruby_html;
178
+ return rb_utf8_str_new_cstr(html);
187
179
  }
188
180
 
189
181
  /*
@@ -191,33 +183,28 @@ static VALUE rb_markdown_to_html(VALUE self, VALUE rb_text, VALUE rb_options, VA
191
183
  *
192
184
  */
193
185
  static VALUE rb_markdown_to_xml(VALUE self, VALUE rb_text, VALUE rb_options, VALUE rb_extensions) {
194
- char *str, *xml;
195
- int len;
186
+ char *xml;
196
187
  cmark_parser *parser;
197
188
  cmark_node *doc;
198
- Check_Type(rb_text, T_STRING);
199
- Check_Type(rb_options, T_FIXNUM);
200
189
 
201
- parser = prepare_parser(rb_options, rb_extensions, cmark_get_arena_mem_allocator());
190
+ Check_Type(rb_text, T_STRING);
202
191
 
203
- str = (char *)RSTRING_PTR(rb_text);
204
- len = RSTRING_LEN(rb_text);
192
+ parser = prepare_parser(rb_options, rb_extensions);
205
193
 
206
- cmark_parser_feed(parser, str, len);
194
+ cmark_parser_feed(parser, StringValuePtr(rb_text), RSTRING_LEN(rb_text));
207
195
  doc = cmark_parser_finish(parser);
196
+
208
197
  if (doc == NULL) {
209
- cmark_arena_reset();
198
+ cmark_parser_free(parser);
210
199
  rb_raise(rb_eNodeError, "error parsing document");
211
200
  }
212
201
 
213
- cmark_mem *default_mem = cmark_get_default_mem_allocator();
214
- xml = cmark_render_xml_with_mem(doc, FIX2INT(rb_options), default_mem);
215
- cmark_arena_reset();
202
+ xml = cmark_render_xml(doc, parser->options);
216
203
 
217
- VALUE ruby_xml = rb_str_new2(xml);
218
- default_mem->free(xml);
204
+ cmark_parser_free(parser);
205
+ cmark_node_free(doc);
219
206
 
220
- return ruby_xml;
207
+ return rb_utf8_str_new_cstr(xml);
221
208
  }
222
209
 
223
210
  /*
@@ -308,18 +295,17 @@ static VALUE rb_node_new(VALUE self, VALUE type) {
308
295
  static VALUE rb_parse_document(VALUE self, VALUE rb_text, VALUE rb_len,
309
296
  VALUE rb_options, VALUE rb_extensions) {
310
297
  char *text;
311
- int len, options;
298
+ int len;
312
299
  cmark_parser *parser;
313
300
  cmark_node *doc;
314
301
  Check_Type(rb_text, T_STRING);
315
302
  Check_Type(rb_len, T_FIXNUM);
316
303
  Check_Type(rb_options, T_FIXNUM);
317
304
 
318
- parser = prepare_parser(rb_options, rb_extensions, cmark_get_default_mem_allocator());
305
+ parser = prepare_parser(rb_options, rb_extensions);
319
306
 
320
307
  text = (char *)RSTRING_PTR(rb_text);
321
308
  len = FIX2INT(rb_len);
322
- options = FIX2INT(rb_options);
323
309
 
324
310
  cmark_parser_feed(parser, text, len);
325
311
  doc = cmark_parser_finish(parser);
@@ -614,7 +600,6 @@ static VALUE rb_render_html(VALUE self, VALUE rb_options, VALUE rb_extensions) {
614
600
  */
615
601
  static VALUE rb_render_xml(VALUE self, VALUE rb_options) {
616
602
  int options;
617
- int i;
618
603
  cmark_node *node;
619
604
  Check_Type(rb_options, T_FIXNUM);
620
605
 
@@ -129,6 +129,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
129
129
  bufsize_t cell_matched = 1, pipe_matched = 1, offset;
130
130
  int expect_more_cells = 1;
131
131
  int row_end_offset = 0;
132
+ int int_overflow_abort = 0;
132
133
 
133
134
  row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
134
135
  row->n_columns = 0;
@@ -161,6 +162,12 @@ static table_row *row_from_string(cmark_syntax_extension *self,
161
162
  ++cell->internal_offset;
162
163
  }
163
164
 
165
+ // make sure we never wrap row->n_columns
166
+ // offset will != len and our exit will clean up as intended
167
+ if (row->n_columns == UINT16_MAX) {
168
+ int_overflow_abort = 1;
169
+ break;
170
+ }
164
171
  row->n_columns += 1;
165
172
  row->cells = cmark_llist_append(parser->mem, row->cells, cell);
166
173
  }
@@ -194,7 +201,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
194
201
  }
195
202
  }
196
203
 
197
- if (offset != len || row->n_columns == 0) {
204
+ if (offset != len || row->n_columns == 0 || int_overflow_abort) {
198
205
  free_table_row(parser->mem, row);
199
206
  row = NULL;
200
207
  }
@@ -241,6 +248,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
241
248
  marker_row = row_from_string(self, parser,
242
249
  input + cmark_parser_get_first_nonspace(parser),
243
250
  len - cmark_parser_get_first_nonspace(parser));
251
+ // assert may be optimized out, don't rely on it for security boundaries
252
+ if (!marker_row) {
253
+ return parent_container;
254
+ }
255
+
244
256
  assert(marker_row);
245
257
 
246
258
  cmark_arena_push();
@@ -264,6 +276,12 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
264
276
  len - cmark_parser_get_first_nonspace(parser));
265
277
  header_row = row_from_string(self, parser, (unsigned char *)parent_string,
266
278
  (int)strlen(parent_string));
279
+ // row_from_string can return NULL, add additional check to ensure n_columns match
280
+ if (!marker_row || !header_row || header_row->n_columns != marker_row->n_columns) {
281
+ free_table_row(parser->mem, marker_row);
282
+ free_table_row(parser->mem, header_row);
283
+ return parent_container;
284
+ }
267
285
  }
268
286
 
269
287
  if (!cmark_node_set_type(parent_container, CMARK_NODE_TABLE)) {
@@ -281,8 +299,10 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
281
299
  parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
282
300
  set_n_table_columns(parent_container, header_row->n_columns);
283
301
 
302
+ // allocate alignments based on marker_row->n_columns
303
+ // since we populate the alignments array based on marker_row->cells
284
304
  uint8_t *alignments =
285
- (uint8_t *)parser->mem->calloc(header_row->n_columns, sizeof(uint8_t));
305
+ (uint8_t *)parser->mem->calloc(marker_row->n_columns, sizeof(uint8_t));
286
306
  cmark_llist *it = marker_row->cells;
287
307
  for (i = 0; it; it = it->next, ++i) {
288
308
  node_cell *node = (node_cell *)it->data;
@@ -351,6 +371,12 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
351
371
  row = row_from_string(self, parser, input + cmark_parser_get_first_nonspace(parser),
352
372
  len - cmark_parser_get_first_nonspace(parser));
353
373
 
374
+ if (!row) {
375
+ // clean up the dangling node
376
+ cmark_node_free(table_row_block);
377
+ return NULL;
378
+ }
379
+
354
380
  {
355
381
  cmark_llist *tmp;
356
382
  int i, table_columns = get_n_table_columns(parent_container);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CommonMarker
4
- VERSION = '0.23.2'
4
+ VERSION = '0.23.4'
5
5
  end
data/lib/commonmarker.rb CHANGED
@@ -23,9 +23,7 @@ module CommonMarker
23
23
  raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
24
24
 
25
25
  opts = Config.process_options(options, :render)
26
- text = text.encode('UTF-8')
27
- html = Node.markdown_to_html(text, opts, extensions)
28
- html.force_encoding('UTF-8')
26
+ Node.markdown_to_html(text.encode('UTF-8'), opts, extensions)
29
27
  end
30
28
 
31
29
  # Public: Parses a Markdown string into a `document` node.
data/test/benchmark.rb CHANGED
@@ -1,32 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'benchmark/ips'
3
4
  require 'commonmarker'
4
- require 'github/markdown'
5
5
  require 'redcarpet'
6
6
  require 'kramdown'
7
7
  require 'benchmark'
8
8
 
9
- def dobench(name, &blk)
10
- puts name
11
- puts Benchmark.measure(&blk)
12
- end
9
+ benchinput = File.read('test/benchinput.md').freeze
13
10
 
14
- benchinput = File.open('test/benchinput.md', 'r').read
11
+ printf("input size = %<bytes>d bytes\n\n", { bytes: benchinput.bytesize })
15
12
 
16
- printf("input size = %<bytes>d bytes\n\n", benchinput.bytesize)
13
+ Benchmark.ips do |x|
14
+ x.report('redcarpet') do
15
+ Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: false, tables: false).render(benchinput)
16
+ end
17
17
 
18
- dobench('redcarpet') do
19
- Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: false, tables: false).render(benchinput)
20
- end
18
+ x.report('commonmarker with to_html') do
19
+ CommonMarker.render_html(benchinput)
20
+ end
21
21
 
22
- dobench('commonmarker with to_html') do
23
- CommonMarker.render_html(benchinput)
24
- end
22
+ x.report('commonmarker with to_xml') do
23
+ CommonMarker.render_html(benchinput)
24
+ end
25
25
 
26
- dobench('commonmarker with ruby HtmlRenderer') do
27
- CommonMarker::HtmlRenderer.new.render(CommonMarker.render_doc(benchinput))
28
- end
26
+ x.report('commonmarker with ruby HtmlRenderer') do
27
+ CommonMarker::HtmlRenderer.new.render(CommonMarker.render_doc(benchinput))
28
+ end
29
+
30
+ x.report('commonmarker with render_doc.to_html') do
31
+ CommonMarker.render_doc(benchinput, :DEFAULT, [:autolink]).to_html(:DEFAULT, [:autolink])
32
+ end
33
+
34
+ x.report('kramdown') do
35
+ Kramdown::Document.new(benchinput).to_html(benchinput)
36
+ end
29
37
 
30
- dobench('kramdown') do
31
- Kramdown::Document.new(benchinput).to_html(benchinput)
38
+ x.compare!
32
39
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: commonmarker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.2
4
+ version: 0.23.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen Torikian
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-09-17 00:00:00.000000000 Z
12
+ date: 2022-03-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: awesome_print
@@ -259,7 +259,8 @@ files:
259
259
  homepage: https://github.com/gjtorikian/commonmarker
260
260
  licenses:
261
261
  - MIT
262
- metadata: {}
262
+ metadata:
263
+ rubygems_mfa_required: 'true'
263
264
  post_install_message:
264
265
  rdoc_options:
265
266
  - "-x"
@@ -281,34 +282,34 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
282
  - !ruby/object:Gem::Version
282
283
  version: '0'
283
284
  requirements: []
284
- rubygems_version: 3.1.4
285
+ rubygems_version: 3.3.3
285
286
  signing_key:
286
287
  specification_version: 4
287
288
  summary: CommonMark parser and renderer. Written in C, wrapped in Ruby.
288
289
  test_files:
290
+ - test/benchmark.rb
291
+ - test/fixtures/curly.md
292
+ - test/fixtures/dingus.md
293
+ - test/fixtures/strong.md
294
+ - test/fixtures/table.md
289
295
  - test/test_attributes.rb
290
- - test/test_linebreaks.rb
291
- - test/test_doc.rb
292
- - test/test_plaintext.rb
293
- - test/test_pathological_inputs.rb
294
- - test/test_node.rb
295
- - test/test_maliciousness.rb
296
+ - test/test_basics.rb
296
297
  - test/test_commands.rb
297
- - test/test_tasklists.rb
298
298
  - test/test_commonmark.rb
299
+ - test/test_doc.rb
299
300
  - test/test_encoding.rb
300
- - test/test_smartpunct.rb
301
- - test/test_spec.rb
302
- - test/test_footnotes.rb
303
301
  - test/test_extensions.rb
304
- - test/fixtures/dingus.md
305
- - test/fixtures/strong.md
306
- - test/fixtures/table.md
307
- - test/fixtures/curly.md
302
+ - test/test_footnotes.rb
303
+ - test/test_gc.rb
308
304
  - test/test_helper.rb
305
+ - test/test_linebreaks.rb
306
+ - test/test_maliciousness.rb
307
+ - test/test_node.rb
309
308
  - test/test_options.rb
310
- - test/benchmark.rb
311
- - test/test_xml.rb
312
- - test/test_basics.rb
309
+ - test/test_pathological_inputs.rb
310
+ - test/test_plaintext.rb
313
311
  - test/test_renderer.rb
314
- - test/test_gc.rb
312
+ - test/test_smartpunct.rb
313
+ - test/test_spec.rb
314
+ - test/test_tasklists.rb
315
+ - test/test_xml.rb