[ python-Bugs-966618 ] float_subtype_new() bug

SourceForge.net noreply at sourceforge.net
Fri Jun 18 18:07:54 EDT 2004


Bugs item #966618, was opened at 2004-06-04 15:39
Message generated for change (Comment added) made by nascheme
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=966618&group_id=5470

Category: Python Interpreter Core
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Armin Rigo (arigo)
Assigned to: Neil Schemenauer (nascheme)
Summary: float_subtype_new() bug

Initial Comment:
A rather obsure bug in the subclassing code:

>>> class A:
...   def __float__(self): return 'hello'
...
>>> float(A())
'hello'

>>> class f(float): pass
...
>>> f(A())
-5.7590155905901735e-56

In debug mode, the assert() in float_subtype_new() fails instead.  In non-debug mode, the value we get is the result of typecasting the PyStringObject* to a PyFloatObject*.

----------------------------------------------------------------------

>Comment By: Neil Schemenauer (nascheme)
Date: 2004-06-18 22:07

Message:
Logged In: YES 
user_id=35752

My patch allows nb_int and nb_long to return either long or
int objects.  That means callers of PyNumber_Long need to be
careful too.  I'm uploading a new version of the patch that
adds a test for int/long interchangeability.

----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2004-06-17 17:02

Message:
Logged In: YES 
user_id=6380

(BTW, shouldn't it be "convertible"?)

I'm torn. For practical reasons, I'm for the minimal patch
originally proposed. Also because I want to allow __int__
returning a long (and vice versa!).

But according to my post this morning to python-dev, I would
like to ensure that the return type of int(), float(), etc.
can be relied upon by type inferencing engines. It would be
a shame to have to assume that after x = int(y) the type of
x could be anything...

Neil, can you rework your patch to be lenient about int/long
but otherwise be strict? It means callers of PyNumber_Int()
should still be careful, but that's the way of the future
anyway.

----------------------------------------------------------------------

Comment By: Armin Rigo (arigo)
Date: 2004-06-16 22:23

Message:
Logged In: YES 
user_id=4771

Let's be careful here.  I can imagine that some __int__() implementations in user code would return a long instead, as it is the behavior of int(something_too_big) already.

As far as I know, the original bug this tracker is for is the only place where it was blindly assumed that a specific conversion method returned an object of a specific type.  I'm fine with just fixing that case.

----------------------------------------------------------------------

Comment By: Neil Schemenauer (nascheme)
Date: 2004-06-08 02:54

Message:
Logged In: YES 
user_id=35752

Attaching patch.  One outstanding issue is that it may make
sense to search for and remove unnecessary type checks (e.g.
PyNumber_Int followed by PyInt_Check).  Also, this change
only broke one test case but I have no idea how much user
code this might break.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-06-07 15:37

Message:
Logged In: YES 
user_id=31435

Assigned to Neil, as a reminder to attach his patch.

----------------------------------------------------------------------

Comment By: Neil Schemenauer (nascheme)
Date: 2004-06-05 21:00

Message:
Logged In: YES 
user_id=35752

I've got an alternative patch.  SF cvs is down at the moment
so I'll have to generate a patch later.  My change makes
CPython match the behavior of Jython.

----------------------------------------------------------------------

Comment By: Neil Schemenauer (nascheme)
Date: 2004-06-05 19:46

Message:
Logged In: YES 
user_id=35752

I think the right fix is to have PyNumber_Int,
PyNumber_Float, and PyNumber_Long check the return value of
slot function (i.e. nb_int, nb_float).  That matches the
behavior of PyObject_Str and PyObject_Repr.

----------------------------------------------------------------------

Comment By: Aaron Brady (insomnike)
Date: 2004-06-05 13:13

Message:
Logged In: YES 
user_id=1057404

(ack, spelling error copied from intobject.c)

###
--- floatobject.c-      Sat Jun  5 13:21:07 2004
+++ floatobject.c       Sat Jun  5 13:23:00 2004
@@ -765,7 +765,13 @@
        tmp = float_new(&PyFloat_Type, args, kwds);
        if (tmp == NULL)
                return NULL;
-       assert(PyFloat_CheckExact(tmp));
+       if(!PyFloat_CheckExact(tmp)) {
+               PyErr_SetString(PyExc_ValueError,
+                               "value must be convertable
to a float");
+               Py_DECREF(tmp);
+               return NULL;
+       }
+
        new = type->tp_alloc(type, 0);
        if (new == NULL) {
                Py_DECREF(tmp);
###

----------------------------------------------------------------------

Comment By: Aaron Brady (insomnike)
Date: 2004-06-05 13:11

Message:
Logged In: YES 
user_id=1057404

(Inline, I can't seem to attach things)

###
--- floatobject.c-      Sat Jun  5 13:21:07 2004
+++ floatobject.c       Sat Jun  5 13:23:00 2004
@@ -765,7 +765,13 @@
        tmp = float_new(&PyFloat_Type, args, kwds);
        if (tmp == NULL)
                return NULL;
-       assert(PyFloat_CheckExact(tmp));
+       if(!PyFloat_CheckExact(tmp)) {
+               PyErr_SetString(PyExc_ValueError,
+                               "value must convertable to a
float");
+               Py_DECREF(tmp);
+               return NULL;
+       }
+
        new = type->tp_alloc(type, 0);
        if (new == NULL) {
                Py_DECREF(tmp);
###

----------------------------------------------------------------------

Comment By: Aaron Brady (insomnike)
Date: 2004-06-05 13:01

Message:
Logged In: YES 
user_id=1057404

floatobject.c contains an assertion that the value can be
coerced into a float, but not a runtime if. I've changed it
to be in line with what int_subtype_new() does.

This may not be 100% correct, however, as they both allow a
string to be returned from __int__() and __float__(),
respectively. complex() does not allow this, however, and it
throws TypeError (while int_subtype_new() and
float_subtype_new() throw ValueError).

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=966618&group_id=5470



More information about the Python-bugs-list mailing list