Skip to content

Commit 24065ee

Browse files
committed
Merge remote-tracking branch 'origin/fix-GHSL-2022-091'
2 parents 58e6da8 + ac01008 commit 24065ee

File tree

1 file changed

+49
-34
lines changed

1 file changed

+49
-34
lines changed

extensions/table.c

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@ static cmark_node__internal_flags CMARK_NODE__TABLE_VISITED;
1717
cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
1818
CMARK_NODE_TABLE_CELL;
1919

20+
typedef struct {
21+
cmark_strbuf *buf;
22+
int start_offset, end_offset, internal_offset;
23+
} node_cell;
24+
2025
typedef struct {
2126
uint16_t n_columns;
2227
int paragraph_offset;
23-
cmark_llist *cells;
28+
node_cell *cells;
2429
} table_row;
2530

2631
typedef struct {
@@ -32,24 +37,24 @@ typedef struct {
3237
bool is_header;
3338
} node_table_row;
3439

35-
typedef struct {
36-
cmark_strbuf *buf;
37-
int start_offset, end_offset, internal_offset;
38-
} node_cell;
39-
40-
static void free_table_cell(cmark_mem *mem, void *data) {
41-
node_cell *cell = (node_cell *)data;
40+
static void free_table_cell(cmark_mem *mem, node_cell *cell) {
4241
cmark_strbuf_free((cmark_strbuf *)cell->buf);
4342
mem->free(cell->buf);
44-
mem->free(cell);
43+
}
44+
45+
static void free_row_cells(cmark_mem *mem, table_row *row) {
46+
while (row->n_columns > 0) {
47+
free_table_cell(mem, &row->cells[--row->n_columns]);
48+
}
49+
mem->free(row->cells);
50+
row->cells = NULL;
4551
}
4652

4753
static void free_table_row(cmark_mem *mem, table_row *row) {
4854
if (!row)
4955
return;
5056

51-
cmark_llist_free_full(mem, row->cells, (cmark_free_func)free_table_cell);
52-
57+
free_row_cells(mem, row);
5358
mem->free(row);
5459
}
5560

@@ -114,6 +119,24 @@ static cmark_strbuf *unescape_pipes(cmark_mem *mem, unsigned char *string, bufsi
114119
return res;
115120
}
116121

122+
// Adds a new cell to the end of the row. A pointer to the new cell is returned
123+
// for the caller to initialize.
124+
static node_cell* append_row_cell(cmark_mem *mem, table_row *row) {
125+
const uint32_t n_columns = row->n_columns + 1;
126+
// realloc when n_columns is a power of 2
127+
if ((n_columns & (n_columns-1)) == 0) {
128+
// make sure we never wrap row->n_columns
129+
// offset will != len and our exit will clean up as intended
130+
if (n_columns > UINT16_MAX) {
131+
return NULL;
132+
}
133+
// Use realloc to double the size of the buffer.
134+
row->cells = (node_cell *)mem->realloc(row->cells, (2 * n_columns - 1) * sizeof(node_cell));
135+
}
136+
row->n_columns = n_columns;
137+
return &row->cells[n_columns-1];
138+
}
139+
117140
static table_row *row_from_string(cmark_syntax_extension *self,
118141
cmark_parser *parser, unsigned char *string,
119142
int len) {
@@ -155,24 +178,22 @@ static table_row *row_from_string(cmark_syntax_extension *self,
155178
cell_matched);
156179
cmark_strbuf_trim(cell_buf);
157180

158-
node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
181+
node_cell *cell = append_row_cell(parser->mem, row);
182+
if (!cell) {
183+
int_overflow_abort = 1;
184+
cmark_strbuf_free(cell_buf);
185+
parser->mem->free(cell_buf);
186+
break;
187+
}
159188
cell->buf = cell_buf;
160189
cell->start_offset = offset;
161190
cell->end_offset = offset + cell_matched - 1;
191+
cell->internal_offset = 0;
162192

163193
while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
164194
--cell->start_offset;
165195
++cell->internal_offset;
166196
}
167-
168-
// make sure we never wrap row->n_columns
169-
// offset will != len and our exit will clean up as intended
170-
if (row->n_columns == UINT16_MAX) {
171-
int_overflow_abort = 1;
172-
break;
173-
}
174-
row->n_columns += 1;
175-
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
176197
}
177198

178199
offset += cell_matched + pipe_matched;
@@ -190,9 +211,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
190211
if (row_end_offset && offset != len) {
191212
row->paragraph_offset = offset;
192213

193-
cmark_llist_free_full(parser->mem, row->cells, (cmark_free_func)free_table_cell);
194-
row->cells = NULL;
195-
row->n_columns = 0;
214+
free_row_cells(parser->mem, row);
196215

197216
// Scan past the (optional) leading pipe.
198217
offset += scan_table_cell_end(string, len, offset);
@@ -311,9 +330,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
311330
// since we populate the alignments array based on marker_row->cells
312331
uint8_t *alignments =
313332
(uint8_t *)parser->mem->calloc(marker_row->n_columns, sizeof(uint8_t));
314-
cmark_llist *it = marker_row->cells;
315-
for (i = 0; it; it = it->next, ++i) {
316-
node_cell *node = (node_cell *)it->data;
333+
for (i = 0; i < marker_row->n_columns; ++i) {
334+
node_cell *node = &marker_row->cells[i];
317335
bool left = node->buf->ptr[0] == ':', right = node->buf->ptr[node->buf->size - 1] == ':';
318336

319337
if (left && right)
@@ -336,10 +354,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
336354
ntr->is_header = true;
337355

338356
{
339-
cmark_llist *tmp;
340-
341-
for (tmp = header_row->cells; tmp; tmp = tmp->next) {
342-
node_cell *cell = (node_cell *) tmp->data;
357+
for (i = 0; i < header_row->n_columns; ++i) {
358+
node_cell *cell = &header_row->cells[i];
343359
cmark_node *header_cell = cmark_parser_add_child(parser, table_header,
344360
CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
345361
header_cell->start_line = header_cell->end_line = parent_container->start_line;
@@ -386,11 +402,10 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
386402
}
387403

388404
{
389-
cmark_llist *tmp;
390405
int i, table_columns = get_n_table_columns(parent_container);
391406

392-
for (tmp = row->cells, i = 0; tmp && i < table_columns; tmp = tmp->next, ++i) {
393-
node_cell *cell = (node_cell *) tmp->data;
407+
for (i = 0; i < row->n_columns && i < table_columns; ++i) {
408+
node_cell *cell = &row->cells[i];
394409
cmark_node *node = cmark_parser_add_child(parser, table_row_block,
395410
CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
396411
node->internal_offset = cell->internal_offset;

0 commit comments

Comments
 (0)