Re: [Python-Dev] buglet in long("123\0", 10)
Added a check in test_long.LongTest.test_misc() that long("123\0", 10)
fails properly and adapted the patch to int_new to long_new. I get
this weird feeling that if its impossible for the function
(PyLong_FromString) to know if its being given bad data, having know
way to know if the string is supposed to continue past the zero-byte,
then doesn't it make sense to say that the function by design is
broken? Anyway, here is the patch.
Index: Objects/longobject.c
===================================================================
--- Objects/longobject.c (revision 53406)
+++ Objects/longobject.c (working copy)
@@ -3287,10 +3287,27 @@
return PyLong_FromLong(0L);
if (base == -909)
return PyNumber_Long(x);
- else if (PyString_Check(x))
+ if (PyString_Check(x)) {
+ /* Since PyLong_FromString doesn't have a length parameter,
+ * check here for possible NULs in the string. */
+ char *string = PyString_AS_STRING(x);
+ if (strlen(string) != PyString_Size(x)) {
+ /* create a repr() of the input string,
+ * just like PyLong_FromString does. */
+ PyObject *srepr;
+ srepr = PyObject_Repr(x);
+ if (srepr == NULL)
+ return NULL;
+ PyErr_Format(PyExc_ValueError,
+ "Invalid literal for long() with base %d: %s",
+ base, PyString_AS_STRING(srepr));
+ Py_DECREF(srepr);
+ return NULL;
+ }
return PyLong_FromString(PyString_AS_STRING(x), NULL, base);
+ }
#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(x))
+ if (PyUnicode_Check(x))
return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x),
PyUnicode_GET_SIZE(x),
base);
@@ -3439,3 +3456,4 @@
long_new, /* tp_new */
PyObject_Del, /* tp_free */
};
+
Index: Lib/test/test_long.py
===================================================================
--- Lib/test/test_long.py (revision 53406)
+++ Lib/test/test_long.py (working copy)
@@ -299,6 +299,8 @@
slicemin, slicemax = X()[-2L**100:2L**100]
self.assertEqual(X()[slicemin:slicemax], (slicemin, slicemax))
+ self.assertRaises(ValueError, long, "123\0", 10)
+
# ----------------------------------- tests of auto int->long conversion
def test_auto_overflow(self):
### END PATCH
On 1/15/07, Neal Norwitz
Calvin,
Was Guido's answer enough or did you want some more? If you take a look at the svn rev I sent, I think it should be pretty easy to come up with a patch for long too.
Getting the size won't help (exactly), since the problem is the diff between strlen() and the size. You can see this in the int() fix.
Let me know if you have any questions. It would be great if you could produce a patch.
Cheers, n -- On 1/14/07, Calvin Spealman
wrote: Is it a more general problem that null-terminated strings are used with data from strings we specifically allow to contain null bytes? Perhaps a migration of *FromString() to *FromStringAndSize() functions, or taking Python string object pointers, would be a more general solution to set as a goal, so this sort of thing can't crop up down the road, again.
I know I'm still very uninitiated in the internals of CPython, so anyone please correct me if my thoughts here are against any on-going policy or reasoning.
On 1/14/07, Neal Norwitz
wrote: SVN rev 52305 resolved Bug #1545497: when given an explicit base, int() did ignore NULs embedded in the string to convert.
However, the same fix wasn't applied for long().
n
On 1/13/07, Guido van Rossum
wrote: What's wrong with this session? :-)
Python 2.6a0 (trunk:53416, Jan 13 2007, 15:24:17) [GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin Type "help", "copyright", "credits" or "license" for more information.
> int('123\0') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: null byte in argument for int() > int('123\0', 10) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: '123\x00' > long('123\0') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: null byte in argument for long() > long('123\0', 10) 123L >
-- --Guido van Rossum (home page: http://www.python.org/~guido/) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/nnorwitz%40gmail.com
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ironfroggy%40gmail.com
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://ironfroggy-code.blogspot.com/ _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/nnorwitz%40gmail.com
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://ironfroggy-code.blogspot.com/
Calvin Spealman wrote:
Added a check in test_long.LongTest.test_misc() that long("123\0", 10) fails properly and adapted the patch to int_new to long_new. I get this weird feeling that if its impossible for the function (PyLong_FromString) to know if its being given bad data, having know way to know if the string is supposed to continue past the zero-byte, then doesn't it make sense to say that the function by design is broken?
It makes sense to say the function is being misused in this case - it's designed to convert *C* strings to PyLong objects, so the assumption that there are no embedded NULs is a valid one. That said, I think a better patch for 2.6 would be to provide a separate PyLong_FromPyString function which did the embedded NULL check (and update abstract.c to use that instead of its own internal function). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org
On 1/18/07, Nick Coghlan
Calvin Spealman wrote:
Added a check in test_long.LongTest.test_misc() that long("123\0", 10) fails properly and adapted the patch to int_new to long_new. I get this weird feeling that if its impossible for the function (PyLong_FromString) to know if its being given bad data, having know way to know if the string is supposed to continue past the zero-byte, then doesn't it make sense to say that the function by design is broken?
It makes sense to say the function is being misused in this case - it's designed to convert *C* strings to PyLong objects, so the assumption that there are no embedded NULs is a valid one. That said, I think a better patch for 2.6 would be to provide a separate PyLong_FromPyString function which did the embedded NULL check (and update abstract.c to use that instead of its own internal function).
Thats more or less the route that would make sense to me! If they would be accepted I would gladly provide patches for both int and long types (and float? anything else?). Is there often a usecase that anyone wants to use PyLong_FromString() where the c-string is not the contents of PyString? I suppose when used from extensions creating them.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://ironfroggy-code.blogspot.com/
participants (2)
-
Calvin Spealman
-
Nick Coghlan