Rev 3680: (jam) Fix bug #186014 by giving a proper exception if the dirstate in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Sep 2 20:46:20 BST 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3680
revision-id: pqm at pqm.ubuntu.com-20080902194610-1zzkeem0cm38snju
parent: pqm at pqm.ubuntu.com-20080902184447-n1nsxw1wcaumxwkb
parent: john at arbash-meinel.com-20080902191557-s88j283bmnnnlvhr
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2008-09-02 20:46:10 +0100
message:
(jam) Fix bug #186014 by giving a proper exception if the dirstate
cannot be parsed.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
bzrlib/_dirstate_helpers_py.py _dirstate_helpers_py-20070710145033-90nz6cqglsk150jy-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test__dirstate_helpers.py test_dirstate_helper-20070504035751-jsbn00xodv0y1eve-2
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
------------------------------------------------------------
revno: 3640.2.6
revision-id: john at arbash-meinel.com-20080902191557-s88j283bmnnnlvhr
parent: john at arbash-meinel.com-20080902185103-camvrjyw7a9efpno
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_segv_186014
timestamp: Tue 2008-09-02 14:15:57 -0500
message:
PQM's pyrex needs a Py_ssize_t typedef.
modified:
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
------------------------------------------------------------
revno: 3640.2.5
revision-id: john at arbash-meinel.com-20080902185103-camvrjyw7a9efpno
parent: john at arbash-meinel.com-20080902183801-1u7pk8k03hx8aw1o
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_segv_186014
timestamp: Tue 2008-09-02 13:51:03 -0500
message:
Change from using AssertionError to using DirstateCorrupt in a few places
modified:
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
bzrlib/_dirstate_helpers_py.py _dirstate_helpers_py-20070710145033-90nz6cqglsk150jy-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test__dirstate_helpers.py test_dirstate_helper-20070504035751-jsbn00xodv0y1eve-2
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
------------------------------------------------------------
revno: 3640.2.4
revision-id: john at arbash-meinel.com-20080902183801-1u7pk8k03hx8aw1o
parent: john at arbash-meinel.com-20080902183702-16cpowcusfvo7rpv
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_segv_186014
timestamp: Tue 2008-09-02 13:38:01 -0500
message:
Copyright updates
modified:
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
bzrlib/_dirstate_helpers_py.py _dirstate_helpers_py-20070710145033-90nz6cqglsk150jy-1
bzrlib/tests/test__dirstate_helpers.py test_dirstate_helper-20070504035751-jsbn00xodv0y1eve-2
------------------------------------------------------------
revno: 3640.2.3
revision-id: john at arbash-meinel.com-20080902183702-16cpowcusfvo7rpv
parent: john at arbash-meinel.com-20080819155235-2ozozhpuyzdfu23c
parent: pqm at pqm.ubuntu.com-20080902152844-dext0kmx4m0u5szy
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_segv_186014
timestamp: Tue 2008-09-02 13:37:02 -0500
message:
Merge bzr.dev 3678, resolve NEWS
added:
bzrlib/_btree_serializer_c.pyx _parse_btree_c.pyx-20080703034413-3q25bklkenti3p8p-2
bzrlib/_btree_serializer_py.py _parse_btree_py.py-20080703034413-3q25bklkenti3p8p-3
bzrlib/btree_index.py index.py-20080624222253-p0x5f92uyh5hw734-7
bzrlib/chunk_writer.py chunk_writer.py-20080630234519-6ggn4id17nipovny-1
bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
bzrlib/tests/test_chunk_writer.py test_chunk_writer.py-20080630234519-6ggn4id17nipovny-2
bzrlib/transport/ftp/ ftp-20080611185801-3vm145h8dmnfgh25-1
bzrlib/transport/ftp/_gssapi.py _gssapi.py-20080611190840-7ejrtp884bk5eu72-2
tools/packaging/ packaging-20080825202834-3j433iaawnt72wqa-1
tools/packaging/build-packages.sh buildpackages.sh-20080821102059-fzlodktas65qmo1k-1
tools/packaging/update-changelogs.sh updatechangelogs.sh-20080821102059-fzlodktas65qmo1k-2
tools/packaging/update-packaging-branches.sh updatepackagingbranc-20080825210254-6is8ciit1yzyd3a2-1
renamed:
bzrlib/transport/ftp.py => bzrlib/transport/ftp/__init__.py ftp.py-20051116161804-58dc9506548c2a53
doc/en/developer-guide/testing.txt => doc/developers/testing.txt testing.txt-20080812140359-i70zzh6v2z7grqex-1
modified:
.bzrignore bzrignore-20050311232317-81f7b71efa2db11a
Makefile Makefile-20050805140406-d96e3498bb61c5bb
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/_patiencediff_c.c _patiencediff_c.c-20070721205602-q3imkipwlgagp3cy-1
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/config.py config.py-20051011043216-070c74f4e9e338e8
bzrlib/diff.py diff.py-20050309040759-26944fbbf2ebbf36
bzrlib/fetch.py fetch.py-20050818234941-26fea6105696365d
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/mail_client.py mail_client.py-20070809192806-vuxt3t19srtpjpdn-1
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/option.py option.py-20051014052914-661fb36e76e7362f
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/push.py push.py-20080606021927-5fe39050e8xne9un-1
bzrlib/reconcile.py reweave_inventory.py-20051108164726-1e5e0934febac06e
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/smart/protocol.py protocol.py-20061108035435-ot0lstk2590yqhzr-1
bzrlib/smart/repository.py repository.py-20061128022038-vr5wy5bubyb8xttk-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_cat_revision.py test_cat_revision.py-20070410204634-fq8mnld5l5aza9e2-1
bzrlib/tests/blackbox/test_info.py test_info.py-20060215045507-bbdd2d34efab9e0a
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
bzrlib/tests/blackbox/test_merge.py test_merge.py-20060323225809-9bc0459c19917f41
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
bzrlib/tests/blackbox/test_non_ascii.py test_non_ascii.py-20060105214030-68010be784a5d854
bzrlib/tests/blackbox/test_outside_wt.py test_outside_wt.py-20060116200058-98edd33e7db8bdde
bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
bzrlib/tests/blackbox/test_selftest.py test_selftest.py-20060123024542-01c5f1bbcb596d78
bzrlib/tests/blackbox/test_send.py test_bundle.py-20060616222707-c21c8b7ea5ef57b1
bzrlib/tests/blackbox/test_status.py teststatus.py-20050712014354-508855eb9f29f7dc
bzrlib/tests/branch_implementations/test_permissions.py test_permissions.py-20060210110243-245c01403bf0fde6
bzrlib/tests/bzrdir_implementations/test_bzrdir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
bzrlib/tests/test_bundle.py test.py-20050630184834-092aa401ab9f039c
bzrlib/tests/test_bzrdir.py test_bzrdir.py-20060131065654-deba40eef51cf220
bzrlib/tests/test_diff.py testdiff.py-20050727164403-d1a3496ebb12e339
bzrlib/tests/test_fetch.py testfetch.py-20050825090644-f73e07e7dfb1765a
bzrlib/tests/test_info.py test_info.py-20070320150933-m0xxm1g7xi9v6noe-1
bzrlib/tests/test_log.py testlog.py-20050728115707-1a514809d7d49309
bzrlib/tests/test_merge.py testmerge.py-20050905070950-c1b5aa49ff911024
bzrlib/tests/test_options.py testoptions.py-20051014093702-96457cfc86319a8f
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
bzrlib/tests/test_permissions.py test_permissions.py-20051215004520-ccf475789c80e80c
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
bzrlib/tests/test_setup.py test_setup.py-20051208073730-4a59a6368c4efa04
bzrlib/tests/test_smart_transport.py test_ssh_transport.py-20060608202016-c25gvf1ob7ypbus6-2
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/tests/test_upgrade_stacked.py test_upgrade_stacked-20080804072225-jd13yami19nskns5-1
bzrlib/tests/test_whitebox.py whitebox.py-20050530064534-a063aafb4a0a3a04
bzrlib/tests/tree_implementations/__init__.py __init__.py-20060717075546-420s7b0bj9hzeowi-2
bzrlib/tests/tree_implementations/test_walkdirs.py test_walkdirs.py-20060729160421-gmjnkotqgxdh98ce-1
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
bzrlib/transport/remote.py ssh.py-20060608202016-c25gvf1ob7ypbus6-1
bzrlib/workingtree.py workingtree.py-20050511021032-29b6ec0a681e02e3
doc/developers/development-repo.txt developmentrepo.txt-20080102200205-raj42k61dch8pjmj-1
doc/developers/index.txt index.txt-20070508041241-qznziunkg0nffhiw-1
doc/developers/ppa.txt ppa.txt-20080722055539-606u7t2z32t3ae4w-1
doc/en/mini-tutorial/index.txt index.txt-20070813141352-2u64ooqzo0or4hss-2
doc/es/mini-tutorial/index.txt index.txt-20080504182136-wmoc35u2t6kom8ca-1
setup.py setup.py-20050314065409-02f8a0a6e3f9bc70
------------------------------------------------------------
revno: 3640.2.2
revision-id: john at arbash-meinel.com-20080819155235-2ozozhpuyzdfu23c
parent: john at arbash-meinel.com-20080819154150-78ta5hv2oorz0mpl
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_segv_259350
timestamp: Tue 2008-08-19 10:52:35 -0500
message:
NEWS entry for fixing bug #186014
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 3640.2.1
revision-id: john at arbash-meinel.com-20080819154150-78ta5hv2oorz0mpl
parent: pqm at pqm.ubuntu.com-20080819034437-8cr7y59abr4wemaz
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_segv_259350
timestamp: Tue 2008-08-19 10:41:50 -0500
message:
More safety checks around PyString_FromStringAndSize,
also make sure we have proper handling of trailing garbage in the
C dirblock parser.
modified:
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
bzrlib/tests/test__dirstate_helpers.py test_dirstate_helper-20070504035751-jsbn00xodv0y1eve-2
=== modified file 'NEWS'
--- a/NEWS 2008-09-02 18:44:47 +0000
+++ b/NEWS 2008-09-02 19:46:10 +0000
@@ -81,6 +81,11 @@
* Show proper error rather than traceback when an unknown revision
id is specified to ``bzr cat-revision``. (Jelmer Vernooij, #175569)
+ * Trailing text in the dirstate file could cause the C dirstate parser
+ to try to allocate an invalid amount of memory. We now properly
+ check and test for parsing a dirstate with invalid trailing data.
+ (John Arbash Meinel, #186014)
+
* ``WorkingTree4`` trees will now correctly report missing-and-new
paths in the output of ``iter_changes``. (Robert Collins)
=== modified file 'bzrlib/_dirstate_helpers_c.pyx'
--- a/bzrlib/_dirstate_helpers_c.pyx 2007-10-10 21:18:06 +0000
+++ b/bzrlib/_dirstate_helpers_c.pyx 2008-09-02 19:15:57 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007, 2008 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
This is the python implementation for DirState functions.
"""
+from bzrlib import errors
from bzrlib.dirstate import DirState
@@ -50,6 +51,7 @@
# inner loops, we don't need to do that at all, as the reference only lasts for
# a very short time.
cdef extern from "Python.h":
+ ctypedef int Py_ssize_t
int PyList_Append(object lst, object item) except -1
void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index)
int PyList_CheckExact(object)
@@ -59,7 +61,7 @@
char *PyString_AsString(object p)
char *PyString_AS_STRING_void "PyString_AS_STRING" (void *p)
object PyString_FromString(char *)
- object PyString_FromStringAndSize(char *, int)
+ object PyString_FromStringAndSize(char *, Py_ssize_t)
int PyString_Size(object p)
int PyString_GET_SIZE_void "PyString_GET_SIZE" (void *p)
int PyString_CheckExact(object p)
@@ -110,6 +112,13 @@
return None
return <char*>found - <char*>_s
+cdef object safe_string_from_size(char *s, Py_ssize_t size):
+ if size < 0:
+ raise AssertionError(
+ 'tried to create a string with an invalid size: %d @0x%x'
+ % (size, <int>s))
+ return PyString_FromStringAndSize(s, size)
+
cdef int _is_aligned(void *ptr):
"""Is this pointer aligned to an integer size offset?
@@ -470,6 +479,7 @@
cdef class Reader:
"""Maintain the current location, and return fields as you parse them."""
+ cdef object state # The DirState object
cdef object text # The overall string object
cdef char *text_cstr # Pointer to the beginning of text
cdef int text_size # Length of text
@@ -478,18 +488,32 @@
cdef char *cur_cstr # Pointer to the current record
cdef char *next # Pointer to the end of this record
- def __init__(self, text):
+ def __init__(self, text, state):
+ self.state = state
self.text = text
self.text_cstr = PyString_AsString(text)
self.text_size = PyString_Size(text)
self.end_cstr = self.text_cstr + self.text_size
self.cur_cstr = self.text_cstr
- cdef char *get_next(self, int *size):
+ cdef char *get_next(self, int *size) except NULL:
"""Return a pointer to the start of the next field."""
cdef char *next
+ cdef Py_ssize_t extra_len
+
+ if self.cur_cstr == NULL:
+ raise AssertionError('get_next() called when cur_str is NULL')
+ elif self.cur_cstr >= self.end_cstr:
+ raise AssertionError('get_next() called when there are no chars'
+ ' left')
next = self.cur_cstr
- self.cur_cstr = <char*>memchr(next, c'\0', self.end_cstr-next)
+ self.cur_cstr = <char*>memchr(next, c'\0', self.end_cstr - next)
+ if self.cur_cstr == NULL:
+ extra_len = self.end_cstr - next
+ raise errors.DirstateCorrupt(self.state,
+ 'failed to find trailing NULL (\\0).'
+ ' Trailing garbage: %r'
+ % safe_string_from_size(next, extra_len))
size[0] = self.cur_cstr - next
self.cur_cstr = self.cur_cstr + 1
return next
@@ -499,7 +523,7 @@
cdef int size
cdef char *next
next = self.get_next(&size)
- return PyString_FromStringAndSize(next, size)
+ return safe_string_from_size(next, size)
cdef int _init(self) except -1:
"""Get the pointer ready.
@@ -570,7 +594,7 @@
# <object>
PyString_AS_STRING_void(p_current_dirname[0]),
cur_size+1) != 0):
- dirname = PyString_FromStringAndSize(dirname_cstr, cur_size)
+ dirname = safe_string_from_size(dirname_cstr, cur_size)
p_current_dirname[0] = <void*>dirname
new_block[0] = 1
else:
@@ -621,13 +645,13 @@
# marker.
trailing = self.get_next(&cur_size)
if cur_size != 1 or trailing[0] != c'\n':
- raise AssertionError(
+ raise errors.DirstateCorrupt(self.state,
'Bad parse, we expected to end on \\n, not: %d %s: %s'
- % (cur_size, PyString_FromStringAndSize(trailing, cur_size),
+ % (cur_size, safe_string_from_size(trailing, cur_size),
ret))
return ret
- def _parse_dirblocks(self, state):
+ def _parse_dirblocks(self):
"""Parse all dirblocks in the state file."""
cdef int num_trees
cdef object current_block
@@ -637,14 +661,15 @@
cdef int expected_entry_count
cdef int entry_count
- num_trees = state._num_present_parents() + 1
- expected_entry_count = state._num_entries
+ num_trees = self.state._num_present_parents() + 1
+ expected_entry_count = self.state._num_entries
# Ignore the first record
self._init()
current_block = []
- state._dirblocks = [('', current_block), ('', [])]
+ dirblocks = [('', current_block), ('', [])]
+ self.state._dirblocks = dirblocks
obj = ''
current_dirname = <void*>obj
new_block = 0
@@ -662,15 +687,16 @@
if new_block:
# new block - different dirname
current_block = []
- PyList_Append(state._dirblocks,
+ PyList_Append(dirblocks,
(<object>current_dirname, current_block))
PyList_Append(current_block, entry)
entry_count = entry_count + 1
if entry_count != expected_entry_count:
- raise AssertionError('We read the wrong number of entries.'
+ raise errors.DirstateCorrupt(self.state,
+ 'We read the wrong number of entries.'
' We expected to read %s, but read %s'
% (expected_entry_count, entry_count))
- state._split_root_dirblock_into_contents()
+ self.state._split_root_dirblock_into_contents()
def _read_dirblocks_c(state):
@@ -689,7 +715,7 @@
text = state._state_file.read()
# TODO: check the crc checksums. crc_measured = zlib.crc32(text)
- reader = Reader(text)
+ reader = Reader(text, state)
- reader._parse_dirblocks(state)
+ reader._parse_dirblocks()
state._dirblock_state = DirState.IN_MEMORY_UNMODIFIED
=== modified file 'bzrlib/_dirstate_helpers_py.py'
--- a/bzrlib/_dirstate_helpers_py.py 2008-07-28 07:17:25 +0000
+++ b/bzrlib/_dirstate_helpers_py.py 2008-09-02 18:51:03 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007, 2008 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
# We cannot import the dirstate module, because it loads this module
# All we really need is the IN_MEMORY_MODIFIED constant
+from bzrlib import errors
from bzrlib.dirstate import DirState
@@ -201,8 +202,8 @@
# Remove the last blank entry
trailing = fields.pop()
if trailing != '':
- raise AssertionError("dirstate file has trailing garbage: %r"
- % (trailing,))
+ raise errors.DirstateCorrupt(state,
+ 'trailing garbage: %r' % (trailing,))
# consider turning fields into a tuple.
# skip the first field which is the trailing null from the header.
@@ -220,7 +221,7 @@
field_count = len(fields)
# this checks our adjustment, and also catches file too short.
if field_count - cur != expected_field_count:
- raise AssertionError(
+ raise errors.DirstateCorrupt(state,
'field count incorrect %s != %s, entry_size=%s, '\
'num_entries=%s fields=%r' % (
field_count - cur, expected_field_count, entry_size,
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py 2008-08-03 00:36:46 +0000
+++ b/bzrlib/errors.py 2008-09-02 18:51:03 +0000
@@ -224,6 +224,16 @@
self.message = message
+class DirstateCorrupt(BzrError):
+
+ _fmt = "The dirstate file (%(state)s) appears to be corrupt: %(msg)s"
+
+ def __init__(self, state, msg):
+ BzrError.__init__(self)
+ self.state = state
+ self.msg = msg
+
+
class DisabledMethod(InternalBzrError):
_fmt = "The smart server method '%(class_name)s' is disabled."
=== modified file 'bzrlib/tests/test__dirstate_helpers.py'
--- a/bzrlib/tests/test__dirstate_helpers.py 2007-07-18 20:30:14 +0000
+++ b/bzrlib/tests/test__dirstate_helpers.py 2008-09-02 18:51:03 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007, 2008 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
from bzrlib import (
dirstate,
+ errors,
tests,
)
from bzrlib.tests import test_dirstate
@@ -691,6 +692,20 @@
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
state._dirblock_state)
+ def test_trailing_garbage(self):
+ tree, state, expected = self.create_basic_dirstate()
+ # We can modify the file as long as it hasn't been read yet.
+ f = open('dirstate', 'ab')
+ try:
+ # Add bogus trailing garbage
+ f.write('bogus\n')
+ finally:
+ f.close()
+ e = self.assertRaises(errors.DirstateCorrupt,
+ state._read_dirblocks_if_needed)
+ # Make sure we mention the bogus characters in the error
+ self.assertContainsRe(str(e), 'bogus')
+
class TestCompiledReadDirblocks(TestReadDirblocks):
"""Test the pyrex implementation of _read_dirblocks"""
=== modified file 'bzrlib/tests/test_errors.py'
--- a/bzrlib/tests/test_errors.py 2008-07-30 04:34:59 +0000
+++ b/bzrlib/tests/test_errors.py 2008-09-02 18:51:03 +0000
@@ -45,6 +45,13 @@
"Error: the reason why",
str(error))
+ def test_dirstate_corrupt(self):
+ error = errors.DirstateCorrupt('.bzr/checkout/dirstate',
+ 'trailing garbage: "x"')
+ self.assertEqualDiff("The dirstate file (.bzr/checkout/dirstate)"
+ " appears to be corrupt: trailing garbage: \"x\"",
+ str(error))
+
def test_disabled_method(self):
error = errors.DisabledMethod("class name")
self.assertEqualDiff(
More information about the bazaar-commits
mailing list