[Python-Dev] Fw: Access violation when no memory

Vladimir Marangozov Vladimir.Marangozov@inrialpes.fr
Mon, 26 Jun 2000 13:33:56 +0200 (CEST)


Mark Hammond wrote:
> 
> >From the newsgroup.  Any thoughts?
> 
> Mark.
> 
> "Phil Mayes" <nospam@bitbucket.com> wrote in message
> news:<olD35.82$_%.4481@newsfeed.avtel.net>...
> > The following program progressively allocates all memory:
> >     size = 1 << 20
> >     list = [None,]
> >     while size:
> >         try:
> >             mem = [None] * size
> >             mem[0] = list
> >             list = mem
> >         except:
> >             size = size / 2
> >
> > It fails with an access violation.  (Turn off virtual memory
> > to provoke it.)

I had a closer look at this report. It revealed a buglet in Instance_New
and raises a question on how to handle the possible NULL values pushed
on the stack in ceval.c, at the exception handling code block:

> > 3. the NULL pointer at tb is pushed here:
> >      ceval.c line 1816:    PUSH(tb);
> >      ceval.c line 1817:    PUSH(val);
> >      ceval.c line 1818:    PUSH(exc);

1. In PyInstance_New, when the inst->in_dict allocation fails, there's
   a DECREF(inst) which triggers the instance_dealloc function. The latter
   goes on checking whether __del__ is defined in the instance's dict
   (by calling getattr2) whithout checking first whether inst->in_dict
   is not NULL. I.e. the dealloc_function assumes the instance has been
   initialized successfully. The net effect is a segfault in PyDict_GetItem
   which is called with a NULL dict.

   There are two possible fixes, and I'm not sure which one is better:

   a) Fix the Instance_New code, by freeing the instance on inst->in_dict
      allocation failure (without decref'ing the instance).

   b) Fix the dealloc code, by checking whether in_dict is not NULL
      before proceeding with the __del__ finalization logic.

   Opinions?

2. In ceval.c, there are indeed cases where 'tb' and 'exc' are NULL on
   low-memory conditions. They are pushed on the stack, then popped with
   a segfault.  The only reasonable behavior I get, after some testing,
   is by setting the tb and exc to Py_None if any of them is NULL before
   pushing them onto the stack. The program succeeds or the process is
   killed by the OS (tested on Linux).

   However, I'm not sure that setting tb and/or exc to Py_None, if NULL,
   makes any sense and won't cause side effects.

   Any other suggestions?

-- 
       Vladimir MARANGOZOV          | Vladimir.Marangozov@inrialpes.fr
http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252