[pypy-svn] r75201 - in pypy/branch/fast-forward/pypy/objspace/std: . test
benjamin at codespeak.net
benjamin at codespeak.net
Tue Jun 8 17:49:23 CEST 2010
Author: benjamin
Date: Tue Jun 8 17:49:22 2010
New Revision: 75201
Modified:
pypy/branch/fast-forward/pypy/objspace/std/newformat.py
pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py
Log:
catch integer overflows in format specifiers
Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/newformat.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py Tue Jun 8 17:49:22 2010
@@ -3,10 +3,32 @@
import string
from pypy.interpreter.error import OperationError
-from pypy.rlib import rstring, runicode, rlocale
+from pypy.rlib import rstring, runicode, rlocale, rarithmetic
from pypy.rlib.objectmodel import specialize
+ at specialize.argtype(1)
+def _parse_int(space, s, start, end):
+ """Parse a number and check for overflows"""
+ result = 0
+ i = start
+ while i < end:
+ c = ord(s[i])
+ if ord("0") <= c <= ord("9"):
+ try:
+ result = rarithmetic.ovfcheck(result * 10)
+ except OverflowError:
+ msg = "too many decimal digits in format string"
+ raise OperationError(space.w_ValueError, space.wrap(msg))
+ result += c - ord("0")
+ else:
+ break
+ i += 1
+ if i == start:
+ result = -1
+ return result, i
+
+
# Auto number state
ANS_INIT = 1
ANS_AUTO = 2
@@ -121,12 +143,11 @@
if c == "[" or c == ".":
break
i += 1
- arg_ref = name[:i]
- try:
- index = int(arg_ref)
- except ValueError:
- index = -1
empty = not i
+ if empty:
+ index = -1
+ else:
+ index = _parse_int(self.space, name, 0, i)[0]
use_numeric = empty or index != -1
if self.auto_numbering_state == ANS_INIT and use_numeric:
if empty:
@@ -147,10 +168,11 @@
index = self.auto_numbering
self.auto_numbering += 1
if index == -1:
+ arg_key = name[:i]
try:
- w_arg = self.kwargs[arg_ref]
+ w_arg = self.kwargs[arg_key]
except KeyError:
- raise OperationError(space.w_KeyError, space.wrap(arg_ref))
+ raise OperationError(space.w_KeyError, space.wrap(arg_key))
else:
try:
w_arg = self.args[index]
@@ -184,14 +206,12 @@
if not got_bracket:
raise OperationError(space.w_ValueError,
space.wrap("Missing ']'"))
- item = name[start:i]
- i += 1 # Skip "]"
- try:
- index = int(item)
- except ValueError:
- w_item = space.wrap(item)
- else:
+ index, reached = _parse_int(self.space, name, start, i)
+ if index != -1 and reached == i:
w_item = space.wrap(index)
+ else:
+ w_item = space.wrap(name[start:i])
+ i += 1 # Skip "]"
w_obj = space.getitem(w_obj, w_item)
else:
msg = "Only '[' and '.' may follow ']'"
@@ -270,16 +290,6 @@
c == "+" or
c == "-")
- def _get_integer(self, spec, i, length):
- start_width = i
- while i < length:
- char_index = ord(spec[i])
- if char_index < ord("0") or ord("9") < char_index:
- break
- i += 1
- num = int(spec[start_width:i]) if start_width != i else -1
- return num, i
-
def _parse_spec(self, default_type, default_align):
space = self.space
self._fill_char = "\0"
@@ -315,13 +325,14 @@
if not got_align:
self._align = "="
i += 1
- self._width, i = self._get_integer(spec, i, length)
+ start_i = i
+ self._width, i = _parse_int(self.space, spec, i, length)
if length - i and spec[i] == ",":
self._thousands_sep = True
i += 1
if length - i and spec[i] == ".":
i += 1
- self._precision, i = self._get_integer(spec, i, length)
+ self._precision, i = _parse_int(self.space, spec, i, length)
if self._precision == -1:
raise OperationError(space.w_ValueError,
space.wrap("no precision given"))
Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py Tue Jun 8 17:49:22 2010
@@ -32,6 +32,8 @@
def test_positional_args(self):
assert self.s("{1}{0}").format(2, 3) == self.s("32")
raises(IndexError, self.s("{2}").format, 2)
+ big = self.s("{123476028570192873049182730984172039840712934}")
+ raises(ValueError, big.format)
def test_kwargs(self):
assert self.s("{what}").format(what=42) == self.s("42")
@@ -45,6 +47,8 @@
def test_index(self):
seq = (1, 42)
assert self.s("{[1]}").format(seq) == self.s("42")
+ big = self.s("{[1092837041982035981720398471029384012937412]}")
+ raises(ValueError, big.format, [0])
def test_getitem(self):
d = {"hi" : 32}
@@ -177,6 +181,10 @@
assert format(self.i(6), "=+3") == "+ 6"
assert format(self.i(6), "a^3") == "a6a"
+ def test_width_overflow(self):
+ big = "92387405982730948052983740958230948524"
+ raises(ValueError, format, self.i(2), big)
+
def test_sign(self):
assert format(self.i(-6)) == "-6"
assert format(self.i(-6), "-") == "-6"
More information about the Pypy-commit
mailing list