TCF Agent: fixed: error in location expression can cause seg fault
diff --git a/agent/tcf/services/vm.c b/agent/tcf/services/vm.c
index a62afdb..6832bbf 100644
--- a/agent/tcf/services/vm.c
+++ b/agent/tcf/services/vm.c
@@ -705,38 +705,43 @@
LocationExpressionState entry_state;
int frame = get_prev_frame(s->ctx, get_info_frame(s->ctx, s->stack_frame));
uint32_t size = read_u4leb128();
+ Trap trap;
get_state(s);
- memset(&entry_state, 0, sizeof(entry_state));
- entry_state.ctx = s->ctx;
- if (get_frame_info(s->ctx, frame, &entry_state.stack_frame) < 0) exception(errno);
- entry_state.reg_id_scope = s->reg_id_scope;
- entry_state.addr_size = s->addr_size;
- entry_state.code = s->code + s->code_pos;
- entry_state.code_len = size;
- entry_state.client_op = s->client_op;
- if (evaluate_vm_expression(&entry_state) < 0) exception(errno);
- if (entry_state.pieces_cnt > 0) {
- size_t i;
- uint64_t value = 0;
- void * value_addr = NULL;
- size_t value_size = 0;
- read_location_pieces(entry_state.ctx, entry_state.stack_frame,
- entry_state.pieces, entry_state.pieces_cnt, 0,
- &value_addr, &value_size);
- if (value_size > sizeof(value)) inv_dwarf("Invalid OP_entry_value expression");
- for (i = 0; i < value_size; i++) {
- value |= ((uint8_t *)value_addr)[i] << (i * 8);
+ if (set_trap(&trap)) {
+ memset(&entry_state, 0, sizeof(entry_state));
+ entry_state.ctx = s->ctx;
+ if (get_frame_info(s->ctx, frame, &entry_state.stack_frame) < 0) exception(errno);
+ entry_state.reg_id_scope = s->reg_id_scope;
+ entry_state.addr_size = s->addr_size;
+ entry_state.code = s->code + s->code_pos;
+ entry_state.code_len = size;
+ entry_state.client_op = s->client_op;
+ if (evaluate_vm_expression(&entry_state) < 0) exception(errno);
+ if (entry_state.pieces_cnt > 0) {
+ size_t i;
+ uint64_t value = 0;
+ void * value_addr = NULL;
+ size_t value_size = 0;
+ read_location_pieces(entry_state.ctx, entry_state.stack_frame,
+ entry_state.pieces, entry_state.pieces_cnt, 0,
+ &value_addr, &value_size);
+ if (value_size > sizeof(value)) inv_dwarf("Invalid OP_entry_value expression");
+ for (i = 0; i < value_size; i++) {
+ value |= ((uint8_t *)value_addr)[i] << (i * 8);
+ }
+ s->stk[s->stk_pos++] = value;
}
- s->stk[s->stk_pos++] = value;
- }
- else if (entry_state.stk_pos == 1) {
- s->stk[s->stk_pos++] = entry_state.stk[entry_state.stk_pos - 1];
- }
- else {
- inv_dwarf("Invalid OP_entry_value expression");
+ else if (entry_state.stk_pos == 1) {
+ s->stk[s->stk_pos++] = entry_state.stk[entry_state.stk_pos - 1];
+ }
+ else {
+ inv_dwarf("Invalid OP_entry_value expression");
+ }
+ clear_trap(&trap);
}
s->code_pos += size;
set_state(s);
+ if (trap.error) exception(trap.error);
#else
inv_dwarf("Cannot execute OP_entry_value: stack trace not available");
#endif
@@ -748,9 +753,14 @@
default:
{
LocationExpressionState * s = state;
+ Trap trap;
get_state(s);
- s->client_op(op);
+ if (set_trap(&trap)) {
+ s->client_op(op);
+ clear_trap(&trap);
+ }
set_state(s);
+ if (trap.error) exception(trap.error);
}
}
}