Edgewall Software
Modify

Opened 13 years ago

Closed 13 years ago

#10111 closed defect (fixed)

OverflowError: __len__() should return 0 <= outcome < 2**31

Reported by: jneff Owned by: Remy Blank
Priority: normal Milestone: 0.12.3
Component: ticket system Version: 0.12dev
Severity: normal Keywords:
Cc: jjneff@…, Thijs Triemstra Branch:
Release Notes:
API Changes:
Internal Changes:

Description (last modified by Thijs Triemstra)

How to Reproduce

While doing a GET operation on /ticket/66, Trac issued an internal error.

(please provide additional details here)

Python Traceback
Most recent call last:

    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/ticket/templates/ticket_change.html", line 61, in <Expression u'wiki_to_html(context, change.comment, escape_newlines=preserve_newlines)'>
      Code fragment:
      Line	
      56	${wiki_to_html(context, text, escape_newlines=preserve_newlines)}
      57	</div>
      58	<div py:otherwise="" py:choose="" class="comment searchable" xml:space="preserve">
      59	<py:when test="show_history">${wiki_to_html(context, change.comment_history[int(cversion)].comment,
      60	escape_newlines=preserve_newlines)}</py:when>
      61	<py:otherwise>${wiki_to_html(context, change.comment, escape_newlines=preserve_newlines)}</py:otherwise>
      62	</div>
      63	</py:choose>
      64	</html>
      Local variables:
      Name	Value
      __data__ 	[{'show_editor': False}, {'comment_version': 0, 'show_editor': False, ...
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/util/compat.py", line 83, in newfunc
      Code fragment:
      Line	
      78	try:
      79	from functools import partial
      80	except ImportError:
      81	def partial(func_, *args, **kwargs):
      82	def newfunc(*fargs, **fkwargs):
      83	return func_(*(args + fargs), **dict(kwargs, **fkwargs))
      84	newfunc.func = func_
      85	newfunc.args = args
      86	newfunc.keywords = kwargs
      87	try:
      88	newfunc.__name__ = func_.__name__
      Local variables:
      Name	Value
      args 	(<trac.env.Environment object at 0x2b8daf26b410>,)
      fargs 	(<Context <Resource u'ticket:66'>>, u'SR #3-3217719731: system performance ...
      fkwargs 	{'escape_newlines': True}
      func_ 	<function format_to_html at 0x2b8dae3ddb18>
      kwargs 	{}
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1498, in format_to_html
      Code fragment:
      Line	
      1493	def format_to_html(env, context, wikidom, escape_newlines=None):
      1494	if not wikidom:
      1495	return Markup()
      1496	if escape_newlines is None:
      1497	escape_newlines = context.get_hint('preserve_newlines', False)
      1498	return HtmlFormatter(env, context, wikidom).generate(escape_newlines)
      1499	 
      1500	def format_to_oneliner(env, context, wikidom, shorten=None):
      1501	if not wikidom:
      1502	return Markup()
      1503	if shorten is None:
      Local variables:
      Name	Value
      context 	<Context <Resource u'ticket:66'>>
      env 	<trac.env.Environment object at 0x2b8daf26b410>
      escape_newlines 	True
      wikidom 	u'SR #3-3217719731: system performance case was opend with SUN and ...
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1453, in generate
      Code fragment:
      Line	
      1448	newlines in the wikidom will be preserved if `escape_newlines` is set.
      1449	"""
      1450	# FIXME: compatibility code only for now
      1451	out = StringIO()
      1452	Formatter(self.env, self.context).format(self.wikidom, out,
      1453	escape_newlines)
      1454	return Markup(out.getvalue())
      1455	 
      1456	 
      1457	class InlineHtmlFormatter(object):
      1458	"""Format parsed wiki text to inline elements HTML.
      Local variables:
      Name	Value
      escape_newlines 	True
      out 	<StringIO.StringIO instance at 0x2b8daf5260e0>
      self 	<trac.wiki.formatter.HtmlFormatter object at 0x2b8daf522210>
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1240, in format
      Code fragment:
      Line	
      1235	 
      1236	self.in_list_item = False
      1237	self.in_quote = False
      1238	# Throw a bunch of regexps on the problem
      1239	self.line = line
      1240	result = re.sub(self.wikiparser.rules, self.replace, line)
      1241	 
      1242	if not self.in_list_item:
      1243	self.close_list()
      1244	 
      1245	if not self.in_quote:
      Local variables:
      Name	Value
      block_start_match 	None
      escape_newlines 	True
      line 	u'SR #3-3217719731: system performance case was opend with SUN and ...
      out 	<StringIO.StringIO instance at 0x2b8daf5260e0>
      self 	<trac.wiki.formatter.Formatter object at 0x2b8daf5220d0>
      text 	[u'SR #3-3217719731: system performance case was opend with SUN and ...
    * File "/usr/lib64/python2.4/sre.py", line 142, in sub
      Code fragment:
      Line	
      137	"""Return the string obtained by replacing the leftmost
      138	non-overlapping occurrences of the pattern in string by the
      139	replacement repl. repl can be either a string or a callable;
      140	if a callable, it's passed the match object and must return
      141	a replacement string to be used."""
      142	return _compile(pattern, 0).sub(repl, string, count)
      143	 
      144	def subn(pattern, repl, string, count=0):
      145	"""Return a 2-tuple containing (new_string, number).
      146	new_string is the string obtained by replacing the leftmost
      147	non-overlapping occurrences of the pattern in the source
      Local variables:
      Name	Value
      count 	0
      pattern 	<_sre.SRE_Pattern object at 0x2b8daf2c3740>
      repl 	<bound method Formatter.replace of <trac.wiki.formatter.Formatter object ...
      string 	u'SR #3-3217719731: system performance case was opend with SUN and ...
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1158, in replace
      Code fragment:
      Line	
      1153	internal_handler = getattr(self, '_%s_formatter' % itype)
      1154	return internal_handler(match, fullmatch)
      1155	 
      1156	def replace(self, fullmatch):
      1157	"""Replace one match with its corresponding expansion"""
      1158	replacement = self.handle_match(fullmatch)
      1159	if replacement:
      1160	return _markup_to_unicode(replacement)
      1161	 
      1162	_normalize_re = re.compile(r'[\v\f]', re.UNICODE)
      1163	 
      Local variables:
      Name	Value
      fullmatch 	<_sre.SRE_Match object at 0x2b8daf569630>
      self 	<trac.wiki.formatter.Formatter object at 0x2b8daf5220d0>
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1151, in handle_match
      Code fragment:
      Line	
      1146	# Check for preceding escape character '!'
      1147	if match[0] == '!':
      1148	return escape(match[1:])
      1149	if itype in self.wikiparser.external_handlers:
      1150	external_handler = self.wikiparser.external_handlers[itype]
      1151	return external_handler(self, match, fullmatch)
      1152	else:
      1153	internal_handler = getattr(self, '_%s_formatter' % itype)
      1154	return internal_handler(match, fullmatch)
      1155	 
      1156	def replace(self, fullmatch):
      Local variables:
      Name	Value
      external_handler 	<function <lambda> at 0x2b8daf4dab18>
      fullmatch 	<_sre.SRE_Match object at 0x2b8daf569630>
      itype 	u'i3'
      match 	u'#3-3217719731'
      self 	<trac.wiki.formatter.Formatter object at 0x2b8daf5220d0>
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/ticket/api.py", line 436, in <lambda>
      Code fragment:
      Line	
      431	# matches #... but not &#... (HTML entity)
      432	r"!?(?<!&)#"
      433	# optional intertrac shorthand #T... + digits
      434	r"(?P<it_ticket>%s)%s" % (WikiParser.INTERTRAC_SCHEME,
      435	Ranges.RE_STR),
      436	lambda x, y, z: self._format_link(x, 'ticket', y[1:], y, z))
      437	 
      438	def _format_link(self, formatter, ns, target, label, fullmatch=None):
      439	intertrac = formatter.shorthand_intertrac_helper(ns, target, label,
      440	fullmatch)
      441	if intertrac:
      Local variables:
      Name	Value
      self 	<trac.ticket.api.TicketSystem object at 0x2b8daf1fa990>
      x 	<trac.wiki.formatter.Formatter object at 0x2b8daf5220d0>
      y 	u'#3-3217719731'
      z 	<_sre.SRE_Match object at 0x2b8daf569630>
    * File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/ticket/api.py", line 446, in _format_link
      Code fragment:
      Line	
      441	if intertrac:
      442	return intertrac
      443	try:
      444	link, params, fragment = formatter.split_link(target)
      445	r = Ranges(link)
      446	if len(r) == 1:
      447	num = r.a
      448	ticket = formatter.resource('ticket', num)
      449	from trac.ticket.model import Ticket
      450	if Ticket.id_is_valid(num) and \
      451	'TICKET_VIEW' in formatter.perm(ticket):
      Local variables:
      Name	Value
      formatter 	<trac.wiki.formatter.Formatter object at 0x2b8daf5220d0>
      fragment 	''
      fullmatch 	<_sre.SRE_Match object at 0x2b8daf569630>
      intertrac 	None
      label 	u'#3-3217719731'
      link 	u'3-3217719731'
      ns 	'ticket'
      params 	''
      r 	<trac.util.Ranges object at 0x2b8daf522110>
      self 	<trac.ticket.api.TicketSystem object at 0x2b8daf1fa990>
      target 	u'3-3217719731'

File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/ticket/templates/ticket_change.html", line 61, in <Expression u'wiki_to_html(context, change.comment, escape_newlines=preserve_newlines)'>
  <py:otherwise>${wiki_to_html(context, change.comment, escape_newlines=preserve_newlines)}</py:otherwise>
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/util/compat.py", line 83, in newfunc
  return func_(*(args + fargs), **dict(kwargs, **fkwargs))
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1498, in format_to_html
  return HtmlFormatter(env, context, wikidom).generate(escape_newlines)
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1453, in generate
  escape_newlines)
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1240, in format
  result = re.sub(self.wikiparser.rules, self.replace, line)
File "/usr/lib64/python2.4/sre.py", line 142, in sub
  return _compile(pattern, 0).sub(repl, string, count)
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1158, in replace
  replacement = self.handle_match(fullmatch)
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/wiki/formatter.py", line 1151, in handle_match
  return external_handler(self, match, fullmatch)
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/ticket/api.py", line 436, in <lambda>
  lambda x, y, z: self._format_link(x, 'ticket', y[1:], y, z))
File "/usr/lib/python2.4/site-packages/Trac-0.12.3dev_r10609-py2.4.egg/trac/ticket/api.py", line 446, in _format_link
  if len(r) == 1:

Request parameters:

{'id': u'66'}

User agent: #USER_AGENT#

System Information

Trac 0.12.3dev-r10609
Babel 0.9.5
CustomFieldAdmin 0.2.5
Genshi 0.6
mod_wsgi 3.2 (WSGIProcessGroup WSGIApplicationGroup %{GLOBAL})
MySQL server: "5.0.77", client: "5.0.77", thread-safe: 1
MySQLdb 1.2.3
Pygments 0.9
Python 2.4.3 (#1, Jun 11 2009, 14:09:37)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)]
pytz 2006p
setuptools 0.6c12
Subversion 1.4.2 (r22196)
jQuery #JQUERY#

Enabled Plugins

AutocompleteUsers 0.4.1
BasicThemeEditorPlugin 0.1-r163
BlackMagicTicketTweaks 0.12r1
siteupload 0.11dev
TracCustomFieldAdmin 0.2.5
TracDateField 1.0.1
TracDynamicFields 1.2.1
TracIniAdminPanel 0.8beta-r534

Attachments (0)

Change History (22)

comment:1 by Thijs Triemstra, 13 years ago

Cc: Thijs Triemstra added
Description: modified (diff)

comment:2 by Remy Blank, 13 years ago

Milestone: 0.12.3
Owner: set to Remy Blank

This rings a bell. I'm pretty sure we had something similar already… Yes, but with revision ranges, in #9955. The second patch in that comment would have avoided this issue, so I'll probably apply it.

OT: We really, really need #7145 :)

comment:3 by jneff, 13 years ago

I'm new to this - should I apply the second patch in #9955 myself and then the ticket should open?

comment:4 by anonymous, 13 years ago

I made the second change as noted in #9955: ]# diff init.py init.py.ORIG

801,802d800
<           #Result must fit an int
<           return  min(self.b - self.a + 1, sys.maxint)

the first change is already present

I recycled httpd and tried to open ticket but same error…

in reply to:  3 comment:5 by Remy Blank, 13 years ago

Replying to jneff:

I'm new to this - should I apply the second patch in #9955 myself and then the ticket should open?

Not necessarily, I was just recording my initial thoughts. It's strange though that the patch doesn't seem to fix the issue for you. I will try to reproduce the issue.

comment:6 by Remy Blank, 13 years ago

Resolution: fixed
Status: newclosed

The patch does fix the issue for me, and was applied in [10670].

comment:7 by Christian Boos, 13 years ago

I wonder if we shouldn't rather fail creating a Range, when given invalid input?

in reply to:  7 ; comment:8 by Remy Blank, 13 years ago

Replying to cboos:

I wonder if we shouldn't rather fail creating a Range, when given invalid input?

Those are really pathological cases, so it doesn't really matter if len() returns the wrong answer (especially considering it already returns an "approximation", i.e. the range from lowest to highest value, and not the number of items in the range). The input is actually valid, and the fact that __len__() must return an int is a Python implementation detail, one that may even be lifted one day.

in reply to:  8 comment:9 by Christian Boos, 13 years ago

Well, not valid as far as ticket ids are concerned. But right, Ranges is not about tickets (only). We could pass Ticket.id_is_valid as a "validator" callback for Ranges?

comment:10 by Remy Blank, 13 years ago

Is it really worth the trouble? The input used here (#3-3217719731) is most probably a mistake (or a text that was unintentionally interpreted as a ticket range), so the goal is only not to throw a 500 and allow fixing the error.

And even though the upper limit of that range is technically invalid for tickets (why do we have that limit on ticket IDs anyway?), the resulting query works fine. Let's leave it at that.

comment:11 by Christian Boos, 13 years ago

I got the impression we were fixing a symptom rather than the cause, and that being consistent with ticket id validation (see r6832) could have been better.

But you're right, it would have helped but only "by accident" ;-) If we had a larger ticket max value, we would still have hit the len must return an int limitation.

comment:12 by jneff, 13 years ago

Should I just reinstall 12.3dev in order to get your latest updates. I made the changes to my init.py but still am getting the same error noted above.

comment:13 by jneff, 13 years ago

diff __init__.py __init__.py.ORIG
799,802c799,801
<         #if self.a is not None and self.b is not None:
<         #    return self.b - self.a + 1
<         #else:
<       if self.a is None or self.b is None:
---
>         if self.a is not None and self.b is not None:
>             return self.b - self.a + 1
>         else:
804,805d802
<       #Result must fit an int
<       return  min(self.b - self.a + 1, sys.maxint)

No change to the error in ticket #66 :-(

comment:14 by jneff, 13 years ago

Ahh I see what happened:

SR #3-3217719731: system performance case was opened with SUN and...

The admin pasted the ticket from SUN for documenting the work - Trac is seeing the # as a ticket # it can't reference. How can I edit the Details to wrap the '#' in a block of ? Is it merely editing the details in the DB via SQL? And the changes mentioend above should have marked the # at the max range of an int right?

in reply to:  12 ; comment:15 by Remy Blank, 13 years ago

Replying to jneff:

Should I just reinstall 12.3dev in order to get your latest updates.

That would be easiest, yes. And don't forget to restart your web server. After that, you should be able to edit the page again.

Trac is seeing the # as a ticket # it can't reference.

Not quite. It's seeing a reference to a range of tickets, where one end of the range doesn't fit an int.

And the changes mentioend above should have marked the # at the max range of an int right?

No, the link remains a link to a range of tickets. If you don't want that, wrap the reference in backquotes:

`SR #3-3217719731`: system performance case was opened with SUN and...

in reply to:  15 ; comment:16 by anonymous, 13 years ago

Replying to rblank:

Replying to jneff:

Should I just reinstall 12.3dev in order to get your latest updates.

That would be easiest, yes. And don't forget to restart your web server. After that, you should be able to edit the page again.

Trac is seeing the # as a ticket # it can't reference.

Not quite. It's seeing a reference to a range of tickets, where one end of the range doesn't fit an int.

And the changes mentioend above should have marked the # at the max range of an int right?

No, the link remains a link to a range of tickets. If you don't want that, wrap the reference in backquotes:

`SR #3-3217719731`: system performance case was opened with SUN and...

That makes much more sense about the Range of tickets - however I'm still confused about the change you posted above - the change to the util.py is supposed to take the second number and if it is outside the range of an INT then it should return the MAX of an int?

SO instead of 3-3217719731 it would return 3-999999 ( assuming 999999 is the max of an int on my system?)

Thanks!

in reply to:  16 comment:17 by Remy Blank, 13 years ago

Replying to anonymous:

however I'm still confused about the change you posted above - the change to the util.py is supposed to take the second number and if it is outside the range of an INT then it should return the MAX of an int?

No, the second number is truncated to sys.maxint only in the __len__() method, which means that len(range) gives a wrong answer. However, that expression is only used in a check len(range) > 1, so it won't change the representation of the link.

comment:18 by thomas.moschny@…, 13 years ago

Resolution: fixed
Status: closedreopened

The patch is wrong.

The (inclusive) upper bound for len() is 2**31-1 for Python 2.4 (all platforms), and sys.maxsize for Python 2.5 and later, and not sys.maxint. That holds especially on 64bit platforms (but also on 32bit platforms the test is off by one.)

So correct would be:

try:
  return min(self.b - self.a + 1, sys.maxsize)
except AttributeError:
  return min(self.b - self.a + 1, 2**31-1)

Also, would be cool if sb could apply the patch then on the 0.11-stable branch.

comment:19 by Remy Blank, 13 years ago

Mmh… On my system, sys.maxsize == sys.maxint == 2**31-1 (Python 2.6, WinXP 32-bit), so this wouldn't make a difference (and there's no off-by-one error). Also, sys.maxsize seems to be defined since Python 2.6, not 2.5. Finally, returning sys.maxint on a 64-bit system and Python 2.5 works.

So the only difference would be that the limit should be 2**31-1 even for 64-bit systems with Python 2.4. We could define a maxlen value in trac.util.compat, and set it to 2**31-1 on Python 2.4, sys.maxsize if available or else sys.maxint.

comment:20 by thomas.moschny@…, 13 years ago

So, as the patch basically is a workaround anyway, wouldn't it be ok to always use 2**31-1?

in reply to:  20 comment:21 by Remy Blank, 13 years ago

Replying to thomas.moschny@…:

So, as the patch basically is a workaround anyway, wouldn't it be ok to always use 2**31-1?

Yes, that's probably the simplest solution.

comment:22 by Remy Blank, 13 years ago

Resolution: fixed
Status: reopenedclosed

Fixed in [10679]. I won't merge this to trunk, as 2.4 isn't supported anymore.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Remy Blank.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Remy Blank to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.