Fix clobbered variable warning in regex.c:run_trace. Fixes #162

This commit is contained in:
TQ Hirsch 2016-08-10 16:02:46 +02:00
parent ed2694c41f
commit 5abdeea9b8

View file

@ -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++) {