libaml: fix gc bug, need to amltake()/amldrop() temporary buffer

we have to protect the temporary buffer allocated by rwfield()
as rwreg() calls amlmapio() which might cause further aml code
execution causing gc() which frees it under us (as it is not
referenced from the interpreter state).

this fixes a panic on boot of a

Lenovo Thinkpad P17 Gen1 Professional Mobile Workstation
This commit is contained in:
cinap_lenrek 2021-07-14 17:04:40 +00:00
parent 6560e7c6fd
commit 1a46b6c19e

View file

@ -285,7 +285,7 @@ mk(int tag, int size)
int a; int a;
a = sizeof(Heap) + size; a = sizeof(Heap) + size;
assert(a >= 0); assert(a >= sizeof(Heap));
h = amlalloc(a); h = amlalloc(a);
h->size = size; h->size = size;
h->tag = tag; h->tag = tag;
@ -615,20 +615,16 @@ rwfieldunit(Field *f, int off, int len, uvlong v, int write)
{ {
if(f->index){ if(f->index){
if(TAG(f->reg) == 'f'){ if(TAG(f->reg) == 'f'){
void *b;
/* set index field */ /* set index field */
rwfield(f->index, mki(off), 1); rwfield(f->index, mki(off), 1);
/* set data field */ /* set or get data field */
f = f->reg;
if(write){ if(write){
b = mk('b', len); void *b = mk('b', len);
putle(b, len, v); putle(b, len, v);
rwfield(f, b, 1); rwfield(f->reg, b, 1);
}else{ }else{
b = rwfield(f, nil, 0); v = ival(rwfield(f->reg, nil, 0));
v = getle(b, len);
} }
return v; return v;
} }
@ -661,6 +657,11 @@ rwfield(Field *f, void *v, int write)
} }
} else } else
b = mk('b', (blen+7)/8); b = mk('b', (blen+7)/8);
/*
* don't free b while in rwfieldunit()/rwreg(),
* gc can't find this temporary object referenced.
*/
amltake(b);
wa = fieldalign(f->flags); wa = fieldalign(f->flags);
wd = wa*8; wd = wa*8;
boff = 0; boff = 0;
@ -688,6 +689,7 @@ rwfield(Field *f, void *v, int write)
} }
} }
} }
amldrop(b);
if(write) if(write)
return nil; return nil;
if(blen > 64) if(blen > 64)