mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Fix refcount leak, fix #618
This commit is contained in:
@@ -643,14 +643,14 @@ block gen_collect(block expr) {
|
|||||||
|
|
||||||
return BLOCK(c,
|
return BLOCK(c,
|
||||||
gen_op_target(FORK, tail),
|
gen_op_target(FORK, tail),
|
||||||
expr,
|
expr,
|
||||||
tail,
|
tail,
|
||||||
gen_op_bound(LOADVN, array_var));
|
gen_op_bound(LOADVN, array_var));
|
||||||
}
|
}
|
||||||
|
|
||||||
block gen_reduce(const char* varname, block source, block init, block body) {
|
block gen_reduce(const char* varname, block source, block init, block body) {
|
||||||
block res_var = gen_op_var_fresh(STOREV, "reduce");
|
block res_var = gen_op_var_fresh(STOREV, "reduce");
|
||||||
block loop = BLOCK(gen_op_simple(DUP),
|
block loop = BLOCK(gen_op_simple(DUPN),
|
||||||
source,
|
source,
|
||||||
block_bind(gen_op_unbound(STOREV, varname),
|
block_bind(gen_op_unbound(STOREV, varname),
|
||||||
BLOCK(gen_op_bound(LOADVN, res_var),
|
BLOCK(gen_op_bound(LOADVN, res_var),
|
||||||
@@ -669,7 +669,7 @@ block gen_reduce(const char* varname, block source, block init, block body) {
|
|||||||
block gen_foreach(const char* varname, block source, block init, block update, block extract) {
|
block gen_foreach(const char* varname, block source, block init, block update, block extract) {
|
||||||
block output = gen_op_targetlater(JUMP);
|
block output = gen_op_targetlater(JUMP);
|
||||||
block state_var = gen_op_var_fresh(STOREV, "foreach");
|
block state_var = gen_op_var_fresh(STOREV, "foreach");
|
||||||
block loop = BLOCK(gen_op_simple(DUP),
|
block loop = BLOCK(gen_op_simple(DUPN),
|
||||||
// get a value from the source expression:
|
// get a value from the source expression:
|
||||||
source,
|
source,
|
||||||
// bind the $varname to that value for all the code in
|
// bind the $varname to that value for all the code in
|
||||||
|
22
execute.c
22
execute.c
@@ -168,6 +168,19 @@ jv stack_pop(jq_state *jq) {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like stack_pop(), but assert !stack_pop_will_free() and replace with
|
||||||
|
// jv_null() on the stack.
|
||||||
|
jv stack_popn(jq_state *jq) {
|
||||||
|
jv* sval = stack_block(&jq->stk, jq->stk_top);
|
||||||
|
jv val = *sval;
|
||||||
|
if (!stack_pop_will_free(&jq->stk, jq->stk_top)) {
|
||||||
|
*sval = jv_null();
|
||||||
|
}
|
||||||
|
jq->stk_top = stack_pop_block(&jq->stk, jq->stk_top, sizeof(jv));
|
||||||
|
assert(jv_is_valid(val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct forkpoint {
|
struct forkpoint {
|
||||||
stack_ptr saved_data_stack;
|
stack_ptr saved_data_stack;
|
||||||
@@ -341,6 +354,13 @@ jv jq_next(jq_state *jq) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DUPN: {
|
||||||
|
jv v = stack_popn(jq);
|
||||||
|
stack_push(jq, jv_copy(v));
|
||||||
|
stack_push(jq, v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case DUP2: {
|
case DUP2: {
|
||||||
jv keep = stack_pop(jq);
|
jv keep = stack_pop(jq);
|
||||||
jv v = stack_pop(jq);
|
jv v = stack_pop(jq);
|
||||||
@@ -457,7 +477,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
jv_dump(jv_copy(*var), 0);
|
jv_dump(jv_copy(*var), 0);
|
||||||
printf(" (%d)\n", jv_get_refcnt(*var));
|
printf(" (%d)\n", jv_get_refcnt(*var));
|
||||||
}
|
}
|
||||||
jv_free(stack_pop(jq));
|
jv_free(stack_popn(jq));
|
||||||
stack_push(jq, *var);
|
stack_push(jq, *var);
|
||||||
*var = jv_null();
|
*var = jv_null();
|
||||||
break;
|
break;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
OP(LOADK, CONSTANT, 1, 1)
|
OP(LOADK, CONSTANT, 1, 1)
|
||||||
OP(DUP, NONE, 1, 2)
|
OP(DUP, NONE, 1, 2)
|
||||||
|
OP(DUPN, NONE, 1, 2)
|
||||||
OP(DUP2, NONE, 2, 3)
|
OP(DUP2, NONE, 2, 3)
|
||||||
OP(POP, NONE, 1, 0)
|
OP(POP, NONE, 1, 0)
|
||||||
OP(LOADV, VARIABLE, 1, 1)
|
OP(LOADV, VARIABLE, 1, 1)
|
||||||
|
Reference in New Issue
Block a user