fix(scanner): fix segfault

Signed-off-by: Michael Hoffmann <mhoffm@posteo.de>
This commit is contained in:
Michael Hoffmann
2023-11-11 11:06:07 +01:00
parent 229d8e50ab
commit fdf6463216
3 changed files with 43 additions and 39 deletions

View File

@@ -11,6 +11,7 @@
void *tmp = realloc((vec).data, (_cap) * sizeof((vec).data[0])); \ void *tmp = realloc((vec).data, (_cap) * sizeof((vec).data[0])); \
assert(tmp != NULL); \ assert(tmp != NULL); \
(vec).data = tmp; \ (vec).data = tmp; \
assert((vec).data != NULL); \
(vec).cap = (_cap); (vec).cap = (_cap);
#define VEC_PUSH(vec, el) \ #define VEC_PUSH(vec, el) \
@@ -31,22 +32,23 @@
{ \ { \
if ((vec).data != NULL) \ if ((vec).data != NULL) \
free((vec).data); \ free((vec).data); \
(vec).data = NULL; \
} }
#define VEC_CLEAR(vec) \ #define VEC_CLEAR(vec) \
{ \ { \
for (int i = 0; i < (vec).len; i++) { \ for (uint32_t i = 0; i < (vec).len; i++) { \
STRING_FREE((vec).data[i].heredoc_identifier); \ STRING_FREE((vec).data[i].heredoc_identifier); \
} \ } \
(vec).len = 0; \ (vec).len = 0; \
} }
#define STRING_RESIZE(vec, _cap) \ #define STRING_RESIZE(vec, _cap) \
void *tmp = realloc((vec).data, (_cap + 1) * sizeof((vec).data[0])); \ void *tmp = realloc((vec).data, ((_cap) + 1) * sizeof((vec).data[0])); \
assert(tmp != NULL); \ assert(tmp != NULL); \
(vec).data = tmp; \ (vec).data = tmp; \
memset((vec).data + (vec).len, 0, \ memset((vec).data + (vec).len, 0, \
((_cap + 1) - (vec).len) * sizeof((vec).data[0])); \ (((_cap) + 1) - (vec).len) * sizeof((vec).data[0])); \
(vec).cap = (_cap); (vec).cap = (_cap);
#define STRING_GROW(vec, _cap) \ #define STRING_GROW(vec, _cap) \
@@ -61,10 +63,9 @@
(vec).data[(vec).len++] = (el); (vec).data[(vec).len++] = (el);
#define STRING_FREE(vec) \ #define STRING_FREE(vec) \
{ \
if ((vec).data != NULL) \ if ((vec).data != NULL) \
free((vec).data); \ free((vec).data); \
} (vec).data = NULL;
enum TokenType { enum TokenType {
QUOTED_TEMPLATE_START, QUOTED_TEMPLATE_START,
@@ -105,14 +106,10 @@ typedef struct {
String heredoc_identifier; String heredoc_identifier;
} Context; } Context;
Context context_new(enum ContextType type, const char *data) { Context context_new(enum ContextType type) {
Context ctx = { Context ctx = {
.type = type, .type = type,
.heredoc_identifier = string_new(),
}; };
ctx.heredoc_identifier.len = strlen(data);
ctx.heredoc_identifier.cap = strlen(data);
memcpy(ctx.heredoc_identifier.data, data, ctx.heredoc_identifier.len);
return ctx; return ctx;
} }
@@ -160,8 +157,8 @@ static void deserialize(Scanner *scanner, const char *buffer, unsigned length) {
if (length == 0) { if (length == 0) {
return; return;
} }
VEC_CLEAR(scanner->context_stack); VEC_CLEAR(scanner->context_stack);
unsigned size = 0; unsigned size = 0;
uint32_t context_stack_size; uint32_t context_stack_size;
memcpy(&context_stack_size, &buffer[size], sizeof(uint32_t)); memcpy(&context_stack_size, &buffer[size], sizeof(uint32_t));
@@ -249,7 +246,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
} }
// manage quoted context // manage quoted context
if (valid_symbols[QUOTED_TEMPLATE_START] && !in_quoted_context(scanner) && lexer->lookahead == '"') { if (valid_symbols[QUOTED_TEMPLATE_START] && !in_quoted_context(scanner) && lexer->lookahead == '"') {
Context ctx = context_new(QUOTED_TEMPLATE, ""); Context ctx = context_new(QUOTED_TEMPLATE);
ctx.heredoc_identifier = string_new();
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_and_advance(lexer, QUOTED_TEMPLATE_START); return accept_and_advance(lexer, QUOTED_TEMPLATE_START);
} }
@@ -263,7 +261,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
!in_interpolation_context(scanner) && lexer->lookahead == '$') { !in_interpolation_context(scanner) && lexer->lookahead == '$') {
advance(lexer); advance(lexer);
if (lexer->lookahead == '{') { if (lexer->lookahead == '{') {
Context ctx = context_new(TEMPLATE_INTERPOLATION, ""); Context ctx = context_new(TEMPLATE_INTERPOLATION);
ctx.heredoc_identifier = string_new();
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_and_advance(lexer, TEMPLATE_INTERPOLATION_START); return accept_and_advance(lexer, TEMPLATE_INTERPOLATION_START);
} }
@@ -287,7 +286,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
!in_directive_context(scanner) && lexer->lookahead == '%') { !in_directive_context(scanner) && lexer->lookahead == '%') {
advance(lexer); advance(lexer);
if (lexer->lookahead == '{') { if (lexer->lookahead == '{') {
Context ctx = context_new(TEMPLATE_DIRECTIVE, ""); Context ctx = context_new(TEMPLATE_DIRECTIVE);
ctx.heredoc_identifier = string_new();
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_and_advance(lexer, TEMPLATE_DIRECTIVE_START); return accept_and_advance(lexer, TEMPLATE_DIRECTIVE_START);
} }
@@ -314,7 +314,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
STRING_PUSH(identifier, lexer->lookahead); STRING_PUSH(identifier, lexer->lookahead);
advance(lexer); advance(lexer);
} }
Context ctx = {HEREDOC_TEMPLATE, identifier}; Context ctx = context_new(HEREDOC_TEMPLATE);
ctx.heredoc_identifier = identifier;
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_inplace(lexer, HEREDOC_IDENTIFIER); return accept_inplace(lexer, HEREDOC_IDENTIFIER);
} }
@@ -386,28 +387,28 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
return false; return false;
} }
void *tree_sitter_hcl_external_scanner_create() { void *tree_sitter_terraform_external_scanner_create() {
Scanner *scanner = calloc(1, sizeof(Scanner)); Scanner *scanner = calloc(1, sizeof(Scanner));
scanner->context_stack.data = calloc(1, sizeof(Context)); scanner->context_stack.data = calloc(1, sizeof(Context));
return scanner; return scanner;
} }
unsigned tree_sitter_hcl_external_scanner_serialize(void *payload, char *buffer) { unsigned tree_sitter_terraform_external_scanner_serialize(void *payload, char *buffer) {
Scanner *scanner = (Scanner *)payload; Scanner *scanner = (Scanner *)payload;
return serialize(scanner, buffer); return serialize(scanner, buffer);
} }
void tree_sitter_hcl_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { void tree_sitter_terraform_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
Scanner *scanner = (Scanner *)payload; Scanner *scanner = (Scanner *)payload;
deserialize(scanner, buffer, length); deserialize(scanner, buffer, length);
} }
bool tree_sitter_hcl_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { bool tree_sitter_terraform_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
Scanner *scanner = (Scanner *)payload; Scanner *scanner = (Scanner *)payload;
return scan(scanner, lexer, valid_symbols); return scan(scanner, lexer, valid_symbols);
} }
void tree_sitter_hcl_external_scanner_destroy(void *payload) { void tree_sitter_terraform_external_scanner_destroy(void *payload) {
Scanner *scanner = (Scanner *)payload; Scanner *scanner = (Scanner *)payload;
for (int i = 0; i < scanner->context_stack.len; i++) { for (int i = 0; i < scanner->context_stack.len; i++) {
STRING_FREE(scanner->context_stack.data[i].heredoc_identifier); STRING_FREE(scanner->context_stack.data[i].heredoc_identifier);

View File

@@ -4,6 +4,8 @@ in
pkgs.mkShell { pkgs.mkShell {
name = "env"; name = "env";
buildInputs = with pkgs; [ buildInputs = with pkgs; [
gdb
valgrind
nodejs nodejs
tree-sitter tree-sitter
emscripten emscripten

View File

@@ -11,6 +11,7 @@
void *tmp = realloc((vec).data, (_cap) * sizeof((vec).data[0])); \ void *tmp = realloc((vec).data, (_cap) * sizeof((vec).data[0])); \
assert(tmp != NULL); \ assert(tmp != NULL); \
(vec).data = tmp; \ (vec).data = tmp; \
assert((vec).data != NULL); \
(vec).cap = (_cap); (vec).cap = (_cap);
#define VEC_PUSH(vec, el) \ #define VEC_PUSH(vec, el) \
@@ -31,22 +32,23 @@
{ \ { \
if ((vec).data != NULL) \ if ((vec).data != NULL) \
free((vec).data); \ free((vec).data); \
(vec).data = NULL; \
} }
#define VEC_CLEAR(vec) \ #define VEC_CLEAR(vec) \
{ \ { \
for (int i = 0; i < (vec).len; i++) { \ for (uint32_t i = 0; i < (vec).len; i++) { \
STRING_FREE((vec).data[i].heredoc_identifier); \ STRING_FREE((vec).data[i].heredoc_identifier); \
} \ } \
(vec).len = 0; \ (vec).len = 0; \
} }
#define STRING_RESIZE(vec, _cap) \ #define STRING_RESIZE(vec, _cap) \
void *tmp = realloc((vec).data, (_cap + 1) * sizeof((vec).data[0])); \ void *tmp = realloc((vec).data, ((_cap) + 1) * sizeof((vec).data[0])); \
assert(tmp != NULL); \ assert(tmp != NULL); \
(vec).data = tmp; \ (vec).data = tmp; \
memset((vec).data + (vec).len, 0, \ memset((vec).data + (vec).len, 0, \
((_cap + 1) - (vec).len) * sizeof((vec).data[0])); \ (((_cap) + 1) - (vec).len) * sizeof((vec).data[0])); \
(vec).cap = (_cap); (vec).cap = (_cap);
#define STRING_GROW(vec, _cap) \ #define STRING_GROW(vec, _cap) \
@@ -61,10 +63,9 @@
(vec).data[(vec).len++] = (el); (vec).data[(vec).len++] = (el);
#define STRING_FREE(vec) \ #define STRING_FREE(vec) \
{ \
if ((vec).data != NULL) \ if ((vec).data != NULL) \
free((vec).data); \ free((vec).data); \
} (vec).data = NULL;
enum TokenType { enum TokenType {
QUOTED_TEMPLATE_START, QUOTED_TEMPLATE_START,
@@ -105,14 +106,10 @@ typedef struct {
String heredoc_identifier; String heredoc_identifier;
} Context; } Context;
Context context_new(enum ContextType type, const char *data) { Context context_new(enum ContextType type) {
Context ctx = { Context ctx = {
.type = type, .type = type,
.heredoc_identifier = string_new(),
}; };
ctx.heredoc_identifier.len = strlen(data);
ctx.heredoc_identifier.cap = strlen(data);
memcpy(ctx.heredoc_identifier.data, data, ctx.heredoc_identifier.len);
return ctx; return ctx;
} }
@@ -160,8 +157,8 @@ static void deserialize(Scanner *scanner, const char *buffer, unsigned length) {
if (length == 0) { if (length == 0) {
return; return;
} }
VEC_CLEAR(scanner->context_stack); VEC_CLEAR(scanner->context_stack);
unsigned size = 0; unsigned size = 0;
uint32_t context_stack_size; uint32_t context_stack_size;
memcpy(&context_stack_size, &buffer[size], sizeof(uint32_t)); memcpy(&context_stack_size, &buffer[size], sizeof(uint32_t));
@@ -249,7 +246,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
} }
// manage quoted context // manage quoted context
if (valid_symbols[QUOTED_TEMPLATE_START] && !in_quoted_context(scanner) && lexer->lookahead == '"') { if (valid_symbols[QUOTED_TEMPLATE_START] && !in_quoted_context(scanner) && lexer->lookahead == '"') {
Context ctx = context_new(QUOTED_TEMPLATE, ""); Context ctx = context_new(QUOTED_TEMPLATE);
ctx.heredoc_identifier = string_new();
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_and_advance(lexer, QUOTED_TEMPLATE_START); return accept_and_advance(lexer, QUOTED_TEMPLATE_START);
} }
@@ -263,7 +261,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
!in_interpolation_context(scanner) && lexer->lookahead == '$') { !in_interpolation_context(scanner) && lexer->lookahead == '$') {
advance(lexer); advance(lexer);
if (lexer->lookahead == '{') { if (lexer->lookahead == '{') {
Context ctx = context_new(TEMPLATE_INTERPOLATION, ""); Context ctx = context_new(TEMPLATE_INTERPOLATION);
ctx.heredoc_identifier = string_new();
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_and_advance(lexer, TEMPLATE_INTERPOLATION_START); return accept_and_advance(lexer, TEMPLATE_INTERPOLATION_START);
} }
@@ -287,7 +286,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
!in_directive_context(scanner) && lexer->lookahead == '%') { !in_directive_context(scanner) && lexer->lookahead == '%') {
advance(lexer); advance(lexer);
if (lexer->lookahead == '{') { if (lexer->lookahead == '{') {
Context ctx = context_new(TEMPLATE_DIRECTIVE, ""); Context ctx = context_new(TEMPLATE_DIRECTIVE);
ctx.heredoc_identifier = string_new();
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_and_advance(lexer, TEMPLATE_DIRECTIVE_START); return accept_and_advance(lexer, TEMPLATE_DIRECTIVE_START);
} }
@@ -314,7 +314,8 @@ static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
STRING_PUSH(identifier, lexer->lookahead); STRING_PUSH(identifier, lexer->lookahead);
advance(lexer); advance(lexer);
} }
Context ctx = {HEREDOC_TEMPLATE, identifier}; Context ctx = context_new(HEREDOC_TEMPLATE);
ctx.heredoc_identifier = identifier;
VEC_PUSH(scanner->context_stack, ctx); VEC_PUSH(scanner->context_stack, ctx);
return accept_inplace(lexer, HEREDOC_IDENTIFIER); return accept_inplace(lexer, HEREDOC_IDENTIFIER);
} }