summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Hastings <larry@hastings.org>2013-08-03 20:01:39 (GMT)
committerLarry Hastings <larry@hastings.org>2013-08-03 20:01:39 (GMT)
commit436151e2ca31d49288bf0d4a86fc5b318a73b851 (patch)
tree1848d089ad1483f2f2527b1279c38f44468645c2
parent70a892b5819c9961ad006b77bdab7c9233574870 (diff)
parent7e53793023516f93efbc501ac0dd7d5f4e44a643 (diff)
downloadcpython-436151e2ca31d49288bf0d4a86fc5b318a73b851.zip
cpython-436151e2ca31d49288bf0d4a86fc5b318a73b851.tar.gz
cpython-436151e2ca31d49288bf0d4a86fc5b318a73b851.tar.bz2
Merge from v3.4.0a1 head.
-rw-r--r--Include/longobject.h1
-rw-r--r--Lib/test/test_int.py47
-rw-r--r--Lib/test/test_re.py10
-rw-r--r--Misc/NEWS7
-rw-r--r--Modules/_sre.c12
-rw-r--r--Modules/sre.h2
-rw-r--r--Objects/abstract.c29
-rw-r--r--Objects/longobject.c87
-rw-r--r--Tools/msi/msi.py5
9 files changed, 124 insertions, 76 deletions
diff --git a/Include/longobject.h b/Include/longobject.h
index 886bc63..24cf401 100644
--- a/Include/longobject.h
+++ b/Include/longobject.h
@@ -97,6 +97,7 @@ PyAPI_FUNC(PyObject *) PyLong_FromString(char *, char **, int);
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) PyLong_FromUnicode(Py_UNICODE*, Py_ssize_t, int);
PyAPI_FUNC(PyObject *) PyLong_FromUnicodeObject(PyObject *u, int base);
+PyAPI_FUNC(PyObject *) _PyLong_FromBytes(const char *, Py_ssize_t, int);
#endif
#ifndef Py_LIMITED_API
diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py
index 4921230..4e00622 100644
--- a/Lib/test/test_int.py
+++ b/Lib/test/test_int.py
@@ -73,14 +73,6 @@ class IntTestCases(unittest.TestCase):
x = -1-sys.maxsize
self.assertEqual(x >> 1, x//2)
- self.assertRaises(ValueError, int, '123\0')
- self.assertRaises(ValueError, int, '53', 40)
-
- # SF bug 1545497: embedded NULs were not detected with
- # explicit base
- self.assertRaises(ValueError, int, '123\0', 10)
- self.assertRaises(ValueError, int, '123\x00 245', 20)
-
x = int('1' * 600)
self.assertIsInstance(x, int)
@@ -401,14 +393,37 @@ class IntTestCases(unittest.TestCase):
int(TruncReturnsBadInt())
def test_error_message(self):
- testlist = ('\xbd', '123\xbd', ' 123 456 ')
- for s in testlist:
- try:
- int(s)
- except ValueError as e:
- self.assertIn(s.strip(), e.args[0])
- else:
- self.fail("Expected int(%r) to raise a ValueError", s)
+ def check(s, base=None):
+ with self.assertRaises(ValueError,
+ msg="int(%r, %r)" % (s, base)) as cm:
+ if base is None:
+ int(s)
+ else:
+ int(s, base)
+ self.assertEqual(cm.exception.args[0],
+ "invalid literal for int() with base %d: %r" %
+ (10 if base is None else base, s))
+
+ check('\xbd')
+ check('123\xbd')
+ check(' 123 456 ')
+
+ check('123\x00')
+ # SF bug 1545497: embedded NULs were not detected with explicit base
+ check('123\x00', 10)
+ check('123\x00 245', 20)
+ check('123\x00 245', 16)
+ check('123\x00245', 20)
+ check('123\x00245', 16)
+ # byte string with embedded NUL
+ check(b'123\x00')
+ check(b'123\x00', 10)
+ # non-UTF-8 byte string
+ check(b'123\xbd')
+ check(b'123\xbd', 10)
+ # lone surrogate in Unicode string
+ check('123\ud800')
+ check('123\ud800', 10)
def test_main():
support.run_unittest(IntTestCases)
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index 8bc74a2..c84d4ed 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -1040,6 +1040,16 @@ class ReTests(unittest.TestCase):
with self.assertRaisesRegex(sre_constants.error, '\?foo'):
re.compile('(?P<?foo>)')
+ def test_issue17998(self):
+ for reps in '*', '+', '?', '{1}':
+ for mod in '', '?':
+ pattern = '.' + reps + mod + 'yz'
+ self.assertEqual(re.compile(pattern, re.S).findall('xyz'),
+ ['xyz'], msg=pattern)
+ pattern = pattern.encode()
+ self.assertEqual(re.compile(pattern, re.S).findall(b'xyz'),
+ [b'xyz'], msg=pattern)
+
def run_re_tests():
from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR
diff --git a/Misc/NEWS b/Misc/NEWS
index 9e7949e..f942ef2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ Release date: 2013-08-03
Core and Builtins
-----------------
+- Issue #16741: Fix an error reporting in int().
+
- Issue #17899: Fix rare file descriptor leak in os.listdir().
- Issue #9035: ismount now recognises volumes mounted below a drive root
@@ -181,6 +183,8 @@ Core and Builtins
Library
-------
+- Issue #17998: Fix an internal error in regular expression engine.
+
- Issue #17557: Fix os.getgroups() to work with the modified behavior of
getgroups(2) on OS X 10.8. Original patch by Mateusz Lenik.
@@ -761,6 +765,9 @@ Windows
Build
-----
+- Issue #16067: Add description into MSI file to replace installer's
+ temporary name.
+
- Issue #18257: Fix readlink usage in python-config. Install the python
version again on Darwin.
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 9b49951..a6933e8 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -997,7 +997,7 @@ entrance:
TRACE(("|%p|%p|REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
ctx->pattern[1], ctx->pattern[2]));
- if (ctx->pattern[1] > (end - ctx->ptr) / state->charsize)
+ if ((Py_ssize_t) ctx->pattern[1] > (end - ctx->ptr) / state->charsize)
RETURN_FAILURE; /* cannot match */
state->ptr = ctx->ptr;
@@ -1081,7 +1081,7 @@ entrance:
TRACE(("|%p|%p|MIN_REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
ctx->pattern[1], ctx->pattern[2]));
- if (ctx->pattern[1] > (end - ctx->ptr) / state->charsize)
+ if ((Py_ssize_t) ctx->pattern[1] > (end - ctx->ptr) / state->charsize)
RETURN_FAILURE; /* cannot match */
state->ptr = ctx->ptr;
@@ -1180,7 +1180,7 @@ entrance:
TRACE(("|%p|%p|MAX_UNTIL %d\n", ctx->pattern,
ctx->ptr, ctx->count));
- if (ctx->count < ctx->u.rep->pattern[1]) {
+ if (ctx->count < (Py_ssize_t) ctx->u.rep->pattern[1]) {
/* not enough matches */
ctx->u.rep->count = ctx->count;
DO_JUMP(JUMP_MAX_UNTIL_1, jump_max_until_1,
@@ -1194,7 +1194,7 @@ entrance:
RETURN_FAILURE;
}
- if ((ctx->count < ctx->u.rep->pattern[2] ||
+ if ((ctx->count < (Py_ssize_t) ctx->u.rep->pattern[2] ||
ctx->u.rep->pattern[2] == SRE_MAXREPEAT) &&
state->ptr != ctx->u.rep->last_ptr) {
/* we may have enough matches, but if we can
@@ -1243,7 +1243,7 @@ entrance:
TRACE(("|%p|%p|MIN_UNTIL %d %p\n", ctx->pattern,
ctx->ptr, ctx->count, ctx->u.rep->pattern));
- if (ctx->count < ctx->u.rep->pattern[1]) {
+ if (ctx->count < (Py_ssize_t) ctx->u.rep->pattern[1]) {
/* not enough matches */
ctx->u.rep->count = ctx->count;
DO_JUMP(JUMP_MIN_UNTIL_1, jump_min_until_1,
@@ -1272,7 +1272,7 @@ entrance:
LASTMARK_RESTORE();
- if ((ctx->count >= ctx->u.rep->pattern[2]
+ if ((ctx->count >= (Py_ssize_t) ctx->u.rep->pattern[2]
&& ctx->u.rep->pattern[2] != SRE_MAXREPEAT) ||
state->ptr == ctx->u.rep->last_ptr)
RETURN_FAILURE;
diff --git a/Modules/sre.h b/Modules/sre.h
index 1a6cd56..0a8f0cf 100644
--- a/Modules/sre.h
+++ b/Modules/sre.h
@@ -19,7 +19,7 @@
#if SIZEOF_SIZE_T > 4
# define SRE_MAXREPEAT (~(SRE_CODE)0)
#else
-# define SRE_MAXREPEAT ((SRE_CODE)PY_SSIZE_T_MAX + 1u)
+# define SRE_MAXREPEAT ((SRE_CODE)PY_SSIZE_T_MAX)
#endif
typedef struct {
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 6c8c561..5f11c3d 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1261,25 +1261,6 @@ convert_integral_to_int(PyObject *integral, const char *error_format)
}
-/* Add a check for embedded NULL-bytes in the argument. */
-static PyObject *
-long_from_string(const char *s, Py_ssize_t len)
-{
- char *end;
- PyObject *x;
-
- x = PyLong_FromString((char*)s, &end, 10);
- if (x == NULL)
- return NULL;
- if (end != s + len) {
- PyErr_SetString(PyExc_ValueError,
- "null byte in argument for int()");
- Py_DECREF(x);
- return NULL;
- }
- return x;
-}
-
PyObject *
PyNumber_Long(PyObject *o)
{
@@ -1327,16 +1308,16 @@ PyNumber_Long(PyObject *o)
if (PyBytes_Check(o))
/* need to do extra error checking that PyLong_FromString()
- * doesn't do. In particular int('9.5') must raise an
- * exception, not truncate the float.
+ * doesn't do. In particular int('9\x005') must raise an
+ * exception, not truncate at the null.
*/
- return long_from_string(PyBytes_AS_STRING(o),
- PyBytes_GET_SIZE(o));
+ return _PyLong_FromBytes(PyBytes_AS_STRING(o),
+ PyBytes_GET_SIZE(o), 10);
if (PyUnicode_Check(o))
/* The above check is done in PyLong_FromUnicode(). */
return PyLong_FromUnicodeObject(o, 10);
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
- return long_from_string(buffer, buffer_len);
+ return _PyLong_FromBytes(buffer, buffer_len, 10);
return type_error("int() argument must be a string or a "
"number, not '%.200s'", o);
diff --git a/Objects/longobject.c b/Objects/longobject.c
index b47be40..e0d641a0 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -2000,6 +2000,14 @@ long_from_binary_base(char **str, int base)
return long_normalize(z);
}
+/* Parses a long from a bytestring. Leading and trailing whitespace will be
+ * ignored.
+ *
+ * If successful, a PyLong object will be returned and 'pend' will be pointing
+ * to the first unused byte unless it's NULL.
+ *
+ * If unsuccessful, NULL will be returned.
+ */
PyObject *
PyLong_FromString(char *str, char **pend, int base)
{
@@ -2262,24 +2270,54 @@ digit beyond the first.
str++;
if (*str != '\0')
goto onError;
- if (pend)
- *pend = str;
long_normalize(z);
- return (PyObject *) maybe_small_long(z);
+ z = maybe_small_long(z);
+ if (z == NULL)
+ return NULL;
+ if (pend != NULL)
+ *pend = str;
+ return (PyObject *) z;
onError:
+ if (pend != NULL)
+ *pend = str;
Py_XDECREF(z);
slen = strlen(orig_str) < 200 ? strlen(orig_str) : 200;
strobj = PyUnicode_FromStringAndSize(orig_str, slen);
if (strobj == NULL)
return NULL;
PyErr_Format(PyExc_ValueError,
- "invalid literal for int() with base %d: %R",
+ "invalid literal for int() with base %d: %.200R",
base, strobj);
Py_DECREF(strobj);
return NULL;
}
+/* Since PyLong_FromString doesn't have a length parameter,
+ * check here for possible NULs in the string.
+ *
+ * Reports an invalid literal as a bytes object.
+ */
+PyObject *
+_PyLong_FromBytes(const char *s, Py_ssize_t len, int base)
+{
+ PyObject *result, *strobj;
+ char *end = NULL;
+
+ result = PyLong_FromString((char*)s, &end, base);
+ if (end == NULL || (result != NULL && end == s + len))
+ return result;
+ Py_XDECREF(result);
+ strobj = PyBytes_FromStringAndSize(s, Py_MIN(len, 200));
+ if (strobj != NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "invalid literal for int() with base %d: %.200R",
+ base, strobj);
+ Py_DECREF(strobj);
+ }
+ return NULL;
+}
+
PyObject *
PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
{
@@ -2294,9 +2332,8 @@ PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
PyObject *
PyLong_FromUnicodeObject(PyObject *u, int base)
{
- PyObject *result;
- PyObject *asciidig;
- char *buffer, *end;
+ PyObject *result, *asciidig;
+ char *buffer, *end = NULL;
Py_ssize_t buflen;
asciidig = _PyUnicode_TransformDecimalAndSpaceToASCII(u);
@@ -2305,17 +2342,22 @@ PyLong_FromUnicodeObject(PyObject *u, int base)
buffer = PyUnicode_AsUTF8AndSize(asciidig, &buflen);
if (buffer == NULL) {
Py_DECREF(asciidig);
- return NULL;
+ if (!PyErr_ExceptionMatches(PyExc_UnicodeEncodeError))
+ return NULL;
}
- result = PyLong_FromString(buffer, &end, base);
- if (result != NULL && end != buffer + buflen) {
- PyErr_SetString(PyExc_ValueError,
- "null byte in argument for int()");
- Py_DECREF(result);
- result = NULL;
+ else {
+ result = PyLong_FromString(buffer, &end, base);
+ if (end == NULL || (result != NULL && end == buffer + buflen)) {
+ Py_DECREF(asciidig);
+ return result;
+ }
+ Py_DECREF(asciidig);
+ Py_XDECREF(result);
}
- Py_DECREF(asciidig);
- return result;
+ PyErr_Format(PyExc_ValueError,
+ "invalid literal for int() with base %d: %.200R",
+ base, u);
+ return NULL;
}
/* forward */
@@ -4319,23 +4361,12 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (PyUnicode_Check(x))
return PyLong_FromUnicodeObject(x, (int)base);
else if (PyByteArray_Check(x) || PyBytes_Check(x)) {
- /* Since PyLong_FromString doesn't have a length parameter,
- * check here for possible NULs in the string. */
char *string;
- Py_ssize_t size = Py_SIZE(x);
if (PyByteArray_Check(x))
string = PyByteArray_AS_STRING(x);
else
string = PyBytes_AS_STRING(x);
- if (strlen(string) != (size_t)size || !size) {
- /* We only see this if there's a null byte in x or x is empty,
- x is a bytes or buffer, *and* a base is given. */
- PyErr_Format(PyExc_ValueError,
- "invalid literal for int() with base %d: %R",
- (int)base, x);
- return NULL;
- }
- return PyLong_FromString(string, NULL, (int)base);
+ return _PyLong_FromBytes(string, Py_SIZE(x), (int)base);
}
else {
PyErr_SetString(PyExc_TypeError,
diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py
index 3e3cef1..73f1c83 100644
--- a/Tools/msi/msi.py
+++ b/Tools/msi/msi.py
@@ -1415,7 +1415,10 @@ merge(msiname, "SharedCRT", "TARGETDIR", modules)
# certname (from config.py) should be (a substring of)
# the certificate subject, e.g. "Python Software Foundation"
if certname:
- os.system('signtool sign /n "%s" /t http://timestamp.verisign.com/scripts/timestamp.dll %s' % (certname, msiname))
+ os.system('signtool sign /n "%s" '
+ '/t http://timestamp.verisign.com/scripts/timestamp.dll '
+ '/d "Python %s" '
+ '%s' % (certname, full_current_version, msiname))
if pdbzip:
build_pdbzip()