mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-05 18:30:24 -08:00
bytevm: fix a possible segmentation fault in OP_PUSHKEYS
The issue was revealed by registering long (EQL LIST) elements as cons types -- essentially we've reached the frame size limit in the middle of the loop, the frame was resized, but the pointer `first' was relative to the old frame base. The solution is to reinitialize the pointer before each iteration.
This commit is contained in:
parent
b9e0a7f949
commit
f04f0ac160
2 changed files with 17 additions and 16 deletions
|
|
@ -653,12 +653,10 @@ ecl_interpret(cl_object frame, cl_object closure, cl_object bytecodes)
|
||||||
Checks the stack frame for keyword arguments.
|
Checks the stack frame for keyword arguments.
|
||||||
*/
|
*/
|
||||||
CASE(OP_PUSHKEYS); {
|
CASE(OP_PUSHKEYS); {
|
||||||
cl_object keys_list, aok, *first, *last;
|
cl_object keys_list, aok, *ptr, *end;
|
||||||
cl_index count;
|
cl_index count, limit;
|
||||||
GET_DATA(keys_list, vector, data);
|
GET_DATA(keys_list, vector, data);
|
||||||
first = ECL_STACK_FRAME_PTR(frame) + frame_index;
|
limit = count = frame->frame.size - frame_index;
|
||||||
count = frame->frame.size - frame_index;
|
|
||||||
last = first + count;
|
|
||||||
if (ecl_unlikely(count & 1)) {
|
if (ecl_unlikely(count & 1)) {
|
||||||
VEbad_lambda_odd_keys(bytecodes, frame);
|
VEbad_lambda_odd_keys(bytecodes, frame);
|
||||||
}
|
}
|
||||||
|
|
@ -667,28 +665,32 @@ ecl_interpret(cl_object frame, cl_object closure, cl_object bytecodes)
|
||||||
cl_object name = ECL_CONS_CAR(keys_list);
|
cl_object name = ECL_CONS_CAR(keys_list);
|
||||||
cl_object flag = ECL_NIL;
|
cl_object flag = ECL_NIL;
|
||||||
cl_object value = ECL_NIL;
|
cl_object value = ECL_NIL;
|
||||||
cl_object *p = first;
|
ptr = ECL_STACK_FRAME_PTR(frame) + frame_index;
|
||||||
for (; p != last; ++p) {
|
end = ptr + limit;
|
||||||
if (*(p++) == name) {
|
for (; ptr != end; ptr++) {
|
||||||
|
if (*(ptr++) == name) {
|
||||||
count -= 2;
|
count -= 2;
|
||||||
if (flag == ECL_NIL) {
|
if (flag == ECL_NIL) {
|
||||||
flag = ECL_T;
|
flag = ECL_T;
|
||||||
value = *p;
|
value = *ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Pushing to the stack may resize it, so be careful to reinitialize
|
||||||
|
pointers using the new value of ECL_STACK_FRAME_PTR. */
|
||||||
if (flag != ECL_NIL) ECL_STACK_PUSH(the_env, value);
|
if (flag != ECL_NIL) ECL_STACK_PUSH(the_env, value);
|
||||||
ECL_STACK_PUSH(the_env, flag);
|
ECL_STACK_PUSH(the_env, flag);
|
||||||
}
|
}
|
||||||
if (count && Null(aok)) {
|
if (count && Null(aok)) {
|
||||||
cl_object *p = first;
|
ptr = ECL_STACK_FRAME_PTR(frame) + frame_index;
|
||||||
for (; p != last; ++p) {
|
end = ptr + limit;
|
||||||
if (*(p++) == @':allow-other-keys') {
|
for (; ptr != end; ptr++) {
|
||||||
aok = *p;
|
if (*(ptr++) == @':allow-other-keys') {
|
||||||
|
aok = *ptr;
|
||||||
count -= 2;
|
count -= 2;
|
||||||
/* only the first :allow-other-keys argument is considered */
|
/* only the first :allow-other-keys argument is considered */
|
||||||
for (++p; p != last; ++p) {
|
for (ptr++; ptr != end; ptr++) {
|
||||||
if (*(p++) != @':allow-other-keys')
|
if (*(ptr++) != @':allow-other-keys')
|
||||||
break;
|
break;
|
||||||
count -= 2;
|
count -= 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -392,7 +392,6 @@ ecl_bds_overflow(void)
|
||||||
cl_env_ptr env = ecl_process_env();
|
cl_env_ptr env = ecl_process_env();
|
||||||
cl_index margin = ecl_option_values[ECL_OPT_BIND_STACK_SAFETY_AREA];
|
cl_index margin = ecl_option_values[ECL_OPT_BIND_STACK_SAFETY_AREA];
|
||||||
cl_index size = env->bds_stack.size;
|
cl_index size = env->bds_stack.size;
|
||||||
cl_index limit_size = env->bds_stack.limit_size;
|
|
||||||
ecl_bds_ptr org = env->bds_stack.org;
|
ecl_bds_ptr org = env->bds_stack.org;
|
||||||
ecl_bds_ptr last = org + size;
|
ecl_bds_ptr last = org + size;
|
||||||
if (env->bds_stack.limit >= last) {
|
if (env->bds_stack.limit >= last) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue