[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pypy-dev
Subject:    Re: [pypy-dev] using python-ldap under pypy
From:       Elmir Jagudin <elmir () unity3d ! com>
Date:       2015-12-14 11:38:10
Message-ID: CAN1hHsro_mzuyhTwERvfho3e6hep9=qaRw8z4wJ5d-DgegCNVg () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


On Mon, Dec 14, 2015 at 10:01 AM, Armin Rigo <arigo@tunes.org> wrote:

> Hi Elmir,
> 
> On Sun, Dec 13, 2015 at 10:19 PM, Elmir Jagudin <elmir@unity3d.com> wrote:
> > The error happens in the python-ldap C code that converts ["uid", "cn"]
> > array to char **.
> > 
> > In this file:
> > 
> http://python-ldap.cvs.sourceforge.net/viewvc/python-ldap/python-ldap/Modules/LDAPObject.c?revision=1.91&view=markup
> 
> > 
> > in function attrs_from_List() there is this code (lines 289-290):
> > 
> > 289:     attrs[i] = PyString_AsString(item);
> > 290:      Py_DECREF(item);
> > 
> > On line 289 the assigned string is correct, however after executing line
> > 290, the string will be corrupted.
> > 
> > I have noticed that under cpython, the refcount for 'item' is larger
> then 1.
> > However under pypy it is always 1, and I guess after decreasing it, the
> > 'item' is freed, and attrs[i] pointer becomes invalid.
> 
> Ok.  However the sentence "under CPython the refcount for 'item' is
> larger than 1" is not true in all cases.  It is true for simple lists
> or tuples, but not for more complex types.  That means that you can
> probably get already-freed strings under CPython too.  Try for
> example:
> 
> class CustomSeq(object):
> def __getitem__(self, i):
> return str(i)     # returns a refcount=1 result
> def __len__(self):
> return 2
> 
> res = l.search_s(BASE_DN,
> ldap.SCOPE_SUBTREE,
> FILTER,
> CustomSeq())
> 
> 
> So it means it's really a bug of python-ldap, which just happens to
> crash more often on PyPy than on CPython.  It should be fixed there.
> 

Yepp, you are right. Following version of the code above clearly shows that
it's broken under CPython as well:

class CustomSeq(object):
    def __getitem__(self, i):
        return str(i)     # returns a refcount=1 result
    def __len__(self):
        return 20

The resulting query send over network will be wrong.

Thanks for clarification.

/Elmir


[Attachment #5 (text/html)]

<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec \
14, 2015 at 10:01 AM, Armin Rigo <span dir="ltr">&lt;<a href="mailto:arigo@tunes.org" \
target="_blank">arigo@tunes.org</a>&gt;</span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex">Hi Elmir,<br> <span class=""><br>
On Sun, Dec 13, 2015 at 10:19 PM, Elmir Jagudin &lt;<a \
href="mailto:elmir@unity3d.com">elmir@unity3d.com</a>&gt; wrote:<br> &gt; The error \
happens in the python-ldap C code that converts [&quot;uid&quot;, &quot;cn&quot;]<br> \
&gt; array to char **.<br> &gt;<br>
&gt; In this file:<br>
&gt; <a href="http://python-ldap.cvs.sourceforge.net/viewvc/python-ldap/python-ldap/Modules/LDAPObject.c?revision=1.91&amp;view=markup" \
rel="noreferrer" target="_blank">http://python-ldap.cvs.sourceforge.net/viewvc/python-ldap/python-ldap/Modules/LDAPObject.c?revision=1.91&amp;view=markup</a><br>
 &gt;<br>
&gt; in function attrs_from_List() there is this code (lines 289-290):<br>
&gt;<br>
&gt; 289:        attrs[i] = PyString_AsString(item);<br>
&gt; 290:         Py_DECREF(item);<br>
&gt;<br>
&gt; On line 289 the assigned string is correct, however after executing line<br>
&gt; 290, the string will be corrupted.<br>
&gt;<br>
&gt; I have noticed that under cpython, the refcount for &#39;item&#39; is larger \
then 1.<br> &gt; However under pypy it is always 1, and I guess after decreasing it, \
the<br> &gt; &#39;item&#39; is freed, and attrs[i] pointer becomes invalid.<br>
<br>
</span>Ok.   However the sentence &quot;under CPython the refcount for &#39;item&#39; \
is<br> larger than 1&quot; is not true in all cases.   It is true for simple \
lists<br> or tuples, but not for more complex types.   That means that you can<br>
probably get already-freed strings under CPython too.   Try for<br>
example:<br>
<br>
class CustomSeq(object):<br>
      def __getitem__(self, i):<br>
            return str(i)        # returns a refcount=1 result<br>
      def __len__(self):<br>
            return 2<br>
<span class=""><br>
res = l.search_s(BASE_DN,<br>
                          ldap.SCOPE_SUBTREE,<br>
                          FILTER,<br>
</span>                          CustomSeq())<br>
<br>
<br>
So it means it&#39;s really a bug of python-ldap, which just happens to<br>
crash more often on PyPy than on CPython.   It should be fixed \
there.<br></blockquote><div><br></div><div>Yepp, you are right. Following version of \
the code above clearly shows that it&#39;s broken under CPython as well:<br><br>class \
CustomSeq(object):<br>       def __getitem__(self, i):<br>               return \
str(i)         # returns a refcount=1 result<br>       def __len__(self):<br>         \
return 20<br><br></div><div>The resulting query send over network will be \
wrong.<br><br></div><div>Thanks for \
clarification.<br></div><div><br></div><div>/Elmir<br></div></div><br></div></div>



_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
https://mail.python.org/mailman/listinfo/pypy-dev


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic