Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Open
Description
Bug report
Bug description:
The pythonarray
module is not currently free-thread safe. The error generator below can generate segfaults of aborts for most of thearray
object methods. I found#116738 which lists this module as in need of an audit, an apparenly closed start on this in#120103 and no owner for this module in the Experts Index, so decided to give it a go (see attached PR).
Reproducer, any singlecheck(...)
call below will generate some kind of segfault or abort fairly quickly.
fromarrayimportarrayfromioimportBytesIOfromrandomimportrandintimportthreadingdefpop1(b,a):# MODIFIES!b.wait()try:a.pop()exceptIndexError:passdefappend1(b,a):# MODIFIES!b.wait()a.append(2)definsert1(b,a):# MODIFIES!b.wait()a.insert(0,2)defextend(b,a):# MODIFIES!c=array('i', [2])b.wait()a.extend(c)defextend2(b,a,c):# MODIFIES!b.wait()a.extend(c)definplace_concat(b,a):# MODIFIES!c=array('i', [2])b.wait()a+=cdefinplace_concat2(b,a,c):# MODIFIES!b.wait()a+=cdefinplace_repeat2(b,a):# MODIFIES!b.wait()a*=2defclear(b,a,*args):# MODIFIES!b.wait()a.clear()defclear2(b,a,c):# MODIFIES c!b.wait()try:c.clear()exceptBufferError:passdefremove1(b,a):# MODIFIES!b.wait()try:a.remove(1)exceptValueError:passdeffromunicode(b,a):# MODIFIES!b.wait()a.fromunicode('test')deffrombytes(b,a):# MODIFIES!b.wait()a.frombytes(b'0000')deffrombytes2(b,a,c):# MODIFIES!b.wait()a.frombytes(c)deffromlist(b,a):# MODIFIES!n=randint(0,100)b.wait()a.fromlist([2]*n)defass_subscr2(b,a,c):# MODIFIES!b.wait()a[:]=cdefass0(b,a):# modifies inplaceb.wait()try:a[0]=0exceptIndexError:passdefbyteswap(b,a):# modifies inplaceb.wait()a.byteswap()deftounicode(b,a):b.wait()a.tounicode()deftobytes(b,a):b.wait()a.tobytes()deftolist(b,a):b.wait()a.tolist()deftofile(b,a):f=BytesIO()b.wait()a.tofile(f)defreduce_ex2(b,a):b.wait()a.__reduce_ex__(2)defreduce_ex3(b,a):b.wait()c=a.__reduce_ex__(3)assertnotc[1]orb'\xdd'notinc[1][3]defcopy(b,a):b.wait()c=a.__copy__()assertnotcor0xddnotincdefrepr1(b,a):b.wait()repr(a)defrepeat2(b,a):b.wait()a*2defcount1(b,a):b.wait()a.count(1)defindex1(b,a):b.wait()try:a.index(1)exceptValueError:passdefcontains1(b,a):b.wait()try:1inaexceptValueError:passdefsubscr0(b,a):b.wait()try:a[0]exceptIndexError:passdefconcat(b,a):b.wait()a+adefconcat2(b,a,c):b.wait()a+cdefrichcmplhs(b,a):c=a[:]b.wait()a==cdefrichcmprhs(b,a):c=a[:]b.wait()c==adefnew(b,a):tc=a.typecodeb.wait()array(tc,a)defrepr_(b,a):b.wait()repr(a)defirepeat(b,a):# MODIFIES!b.wait()a*=2defnewi(b,l):b.wait()array('i',l)deffromlistl(b,a,l):# MODIFIES!b.wait()a.fromlist(l)deffromlistlclear(b,a,l):# MODIFIES LIST!b.wait()l.clear()defiter_next(b,a,it):# MODIFIES ITERATOR!b.wait()list(it)defiter_reduce(b,a,it):b.wait()c=it.__reduce__()assertnotc[1]orb'\xdd'notinc[1][0]defcheck(funcs,a=None,*args):ifaisNone:a=array('i', [1])barrier=threading.Barrier(len(funcs))thrds= []forfuncinfuncs:thrd=threading.Thread(target=func,args=(barrier,a,*args))thrds.append(thrd)thrd.start()forthrdinthrds:thrd.join()if__name__=="__main__":whileTrue:check([pop1]*10)check([pop1]+ [subscr0]*10)check([append1]*10)check([insert1]*10)check([pop1]+ [index1]*10)check([pop1]+ [contains1]*10)check([insert1]+ [repeat2]*10)check([pop1]+ [repr1]*10)check([inplace_repeat2]*10)check([byteswap]*10)check([insert1]+ [clear]*10)check([pop1]+ [count1]*10)check([remove1]*10)check([clear]+ [copy]*10,array('B',b'0'*0x400000))check([pop1]+ [reduce_ex2]*10)check([clear]+ [reduce_ex3]*10,array('B',b'0'*0x400000))check([pop1]+ [tobytes]*10)check([pop1]+ [tolist]*10)check([clear,tounicode]*10,array('w','a'*10000))check([clear,tofile]*10,array('w','a'*10000))check([clear]+ [extend]*10)check([clear]+ [inplace_concat]*10)check([clear]+ [concat]*10,array('w','a'*10000))check([fromunicode]*10,array('w','a'))check([frombytes]*10)check([fromlist]*10)check([clear]+ [richcmplhs]*10,array('i', [1]*10000))check([clear]+ [richcmprhs]*10,array('i', [1]*10000))check([clear,ass0]*10,array('i', [1]*10000))# to test array_ass_item must disable Py_mp_ass_subscriptcheck([clear]+ [new]*10,array('w','a'*10000))check([clear]+ [repr_]*10,array('B',b'0'*0x40000))check([clear]+ [repr_]*10,array('B',b'0'*0x40000))check([clear]+ [irepeat]*10,array('B',b'0'*0x40000))check([clear]+ [iter_reduce]*10,a:=array('B',b'0'*0x400),iter(a))# make sure we handle non-self objects correctlycheck([clear]+ [newi]*10, [2]*randint(0,100))check([fromlistlclear]+ [fromlistl]*10,array('i', [1]), [2]*randint(0,100))check([clear2]+ [concat2]*10,array('w','a'*10000),array('w','a'*10000))check([clear2]+ [inplace_concat2]*10,array('w','a'*10000),array('w','a'*10000))check([clear2]+ [extend2]*10,array('w','a'*10000),array('w','a'*10000))check([clear2]+ [ass_subscr2]*10,array('w','a'*10000),array('w','a'*10000))check([clear2]+ [frombytes2]*10,array('w','a'*10000),array('B',b'a'*10000))# iterator stuffcheck([clear]+ [iter_next]*10,a:=array('i', [1]*10),iter(a))
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux