Fix clobbered variable warning in regex.c:run_trace. Fixes #162
This commit is contained in:
parent
ed2694c41f
commit
5abdeea9b8
1 changed files with 50 additions and 15 deletions
|
|
@ -206,16 +206,43 @@ bool svm_stack_ensure_cap(HAllocator *mm__, HSVMContext *ctx, size_t addl) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GCC produces the following diagnostic on this function:
|
||||||
|
*
|
||||||
|
* error: argument 'trace' might be clobbered by 'longjmp' or 'vfork' [-Werror=clobbered]
|
||||||
|
*
|
||||||
|
* However, this is spurious; what is happening is that the trace
|
||||||
|
* argument gets reused to store cur, and GCC doesn't know enough
|
||||||
|
* about setjmp to know that the second return only returns nonzero
|
||||||
|
* (and therefore the now-clobbered value of trace is invalid.)
|
||||||
|
*
|
||||||
|
* A side effect of disabling this warning is that we need to be
|
||||||
|
* careful about undefined behaviour involving automatic
|
||||||
|
* variables. Specifically, any automatic variable in this function
|
||||||
|
* whose value gets modified after setjmp has an undefined value after
|
||||||
|
* the second return; here, the only variables that could matter for
|
||||||
|
* are arena and ctx (because they're referenced in "goto fail").
|
||||||
|
*/
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||||
|
#pragma GCC diagnostic ignored "-Wclobbered"
|
||||||
|
#endif
|
||||||
HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, const uint8_t *input, int len) {
|
HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, const uint8_t *input, int len) {
|
||||||
// orig_prog is only used for the action table
|
// orig_prog is only used for the action table
|
||||||
HSVMContext ctx;
|
HSVMContext *ctx = NULL;
|
||||||
HArena *arena = h_new_arena(mm__, 0);
|
HArena *arena = h_new_arena(mm__, 0);
|
||||||
ctx.stack_count = 0;
|
if (arena == NULL) {
|
||||||
ctx.stack_capacity = 16;
|
return NULL;
|
||||||
ctx.stack = h_new(HParsedToken*, ctx.stack_capacity);
|
}
|
||||||
|
ctx = h_new(HSVMContext, 1);
|
||||||
|
if (!ctx) goto fail;
|
||||||
|
ctx->stack_count = 0;
|
||||||
|
ctx->stack_capacity = 16;
|
||||||
|
ctx->stack = h_new(HParsedToken*, ctx->stack_capacity);
|
||||||
|
|
||||||
// out of memory handling
|
// out of memory handling
|
||||||
if(!arena || !ctx.stack)
|
if(!arena || !ctx->stack)
|
||||||
goto fail;
|
goto fail;
|
||||||
jmp_buf except;
|
jmp_buf except;
|
||||||
h_arena_set_except(arena, &except);
|
h_arena_set_except(arena, &except);
|
||||||
|
|
@ -227,20 +254,20 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace,
|
||||||
for (cur = trace; cur; cur = cur->next) {
|
for (cur = trace; cur; cur = cur->next) {
|
||||||
switch (cur->opcode) {
|
switch (cur->opcode) {
|
||||||
case SVM_PUSH:
|
case SVM_PUSH:
|
||||||
if (!svm_stack_ensure_cap(mm__, &ctx, 1)) {
|
if (!svm_stack_ensure_cap(mm__, ctx, 1)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
tmp_res = a_new(HParsedToken, 1);
|
tmp_res = a_new(HParsedToken, 1);
|
||||||
tmp_res->token_type = TT_MARK;
|
tmp_res->token_type = TT_MARK;
|
||||||
tmp_res->index = cur->input_pos;
|
tmp_res->index = cur->input_pos;
|
||||||
tmp_res->bit_offset = 0;
|
tmp_res->bit_offset = 0;
|
||||||
ctx.stack[ctx.stack_count++] = tmp_res;
|
ctx->stack[ctx->stack_count++] = tmp_res;
|
||||||
break;
|
break;
|
||||||
case SVM_NOP:
|
case SVM_NOP:
|
||||||
break;
|
break;
|
||||||
case SVM_ACTION:
|
case SVM_ACTION:
|
||||||
// Action should modify stack appropriately
|
// Action should modify stack appropriately
|
||||||
if (!orig_prog->actions[cur->arg].action(arena, &ctx, orig_prog->actions[cur->arg].env)) {
|
if (!orig_prog->actions[cur->arg].action(arena, ctx, orig_prog->actions[cur->arg].env)) {
|
||||||
|
|
||||||
// action failed... abort somehow
|
// action failed... abort somehow
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -249,9 +276,9 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace,
|
||||||
case SVM_CAPTURE:
|
case SVM_CAPTURE:
|
||||||
// Top of stack must be a mark
|
// Top of stack must be a mark
|
||||||
// This replaces said mark in-place with a TT_BYTES.
|
// This replaces said mark in-place with a TT_BYTES.
|
||||||
assert(ctx.stack[ctx.stack_count-1]->token_type == TT_MARK);
|
assert(ctx->stack[ctx->stack_count-1]->token_type == TT_MARK);
|
||||||
|
|
||||||
tmp_res = ctx.stack[ctx.stack_count-1];
|
tmp_res = ctx->stack[ctx->stack_count-1];
|
||||||
tmp_res->token_type = TT_BYTES;
|
tmp_res->token_type = TT_BYTES;
|
||||||
// TODO: Will need to copy if bit_offset is nonzero
|
// TODO: Will need to copy if bit_offset is nonzero
|
||||||
assert(tmp_res->bit_offset == 0);
|
assert(tmp_res->bit_offset == 0);
|
||||||
|
|
@ -260,25 +287,33 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace,
|
||||||
tmp_res->bytes.len = cur->input_pos - tmp_res->index;
|
tmp_res->bytes.len = cur->input_pos - tmp_res->index;
|
||||||
break;
|
break;
|
||||||
case SVM_ACCEPT:
|
case SVM_ACCEPT:
|
||||||
assert(ctx.stack_count <= 1);
|
assert(ctx->stack_count <= 1);
|
||||||
HParseResult *res = a_new(HParseResult, 1);
|
HParseResult *res = a_new(HParseResult, 1);
|
||||||
if (ctx.stack_count == 1) {
|
if (ctx->stack_count == 1) {
|
||||||
res->ast = ctx.stack[0];
|
res->ast = ctx->stack[0];
|
||||||
} else {
|
} else {
|
||||||
res->ast = NULL;
|
res->ast = NULL;
|
||||||
}
|
}
|
||||||
res->bit_length = cur->input_pos * 8;
|
res->bit_length = cur->input_pos * 8;
|
||||||
res->arena = arena;
|
res->arena = arena;
|
||||||
h_arena_set_except(arena, NULL);
|
h_arena_set_except(arena, NULL);
|
||||||
h_free(ctx.stack);
|
h_free(ctx->stack);
|
||||||
|
h_free(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
if (arena) h_delete_arena(arena);
|
if (arena) h_delete_arena(arena);
|
||||||
if (ctx.stack) h_free(ctx.stack);
|
if (ctx) {
|
||||||
|
if (ctx->stack) h_free(ctx->stack);
|
||||||
|
h_free(ctx);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// Reenable -Wclobber
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t h_rvm_create_action(HRVMProg *prog, HSVMActionFunc action_func, void* env) {
|
uint16_t h_rvm_create_action(HRVMProg *prog, HSVMActionFunc action_func, void* env) {
|
||||||
for (uint16_t i = 0; i < prog->action_count; i++) {
|
for (uint16_t i = 0; i < prog->action_count; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue