On Thu, Sep 16, 2010 at 09:14:28PM +0200, Jelmer Vernooij wrote: > Package: python-debian > Version: 0.1.17~bzr184~launchpad1 > Severity: normal > > > The Changes() object (but probably other deb822-style objects as well) > don't handle the situation very well when a field that contains empty > lines is followed by another field: > > #!/usr/bin/python > from debian.deb822 import Changes > x = Changes() > x["Changes"] = """Foo > > Bar > """ > x["Format"] = "1.8" > y = Changes(x.dump()) > print y["Format"] > > It would be nice if an exception was raised instead of an invalid changes file > being written.
I actually had a patch out for review about a year ago that would have fixed this problem at __setitem__ time (it wouldn't have let you set x["Changes"] to that value). The patch was part of a cleanup series I never got around to pushing... I've reattached it here, but it probably doesn't quite apply anymore. I'll work on it over the weekend. -- John Wright <[email protected]>
>From bf321ad6fbdd0541d3b972ab8ec090f4d54d50ef Mon Sep 17 00:00:00 2001 From: John Wright <[email protected]> Date: Wed, 29 Jul 2009 15:17:27 +0200 Subject: [PATCH] deb822: Validate input in Deb822.__setitem__ Try to catch input that would result in multiple stanzas or unparseable data when dumping the Deb822 object. This patch also clarifies a comment related to this, and removes an XXX comment that it addreses. --- debian_bundle/deb822.py | 35 ++++++++++++++++++++++++++++++++--- 1 files changed, 32 insertions(+), 3 deletions(-) diff --git a/debian_bundle/deb822.py b/debian_bundle/deb822.py index dd1d201..ca35668 100644 --- a/debian_bundle/deb822.py +++ b/debian_bundle/deb822.py @@ -358,10 +358,12 @@ class Deb822(Deb822Dict): else: return_string = False for key, value in self.iteritems(): + # We want one space between the "Field:" and value, unless + # value starts with a newline (i.e. the value itself started on + # the line *after* the field name in the control file), or is + # empty. In that case, we avoid trailing whitespace by by not + # including a space after the colon. if not value or value[0] == '\n': - # Avoid trailing whitespace after "Field:" if it's on its own - # line or the value is empty - # XXX Uh, really print value if value == '\n'? fd.write('%s:%s\n' % (key, value)) else: fd.write('%s: %s\n' % (key, value)) @@ -538,6 +540,33 @@ class Deb822(Deb822Dict): return self.gpg_info + def validate_input(self, key, value): + """Raise ValueError if value is not a valid value for key + + Subclasses that do interesting things for different keys may wish to + override this method. + """ + + strvalue = str(value) + + # The value cannot end in a newline (if it did, dumping the object + # would result in multiple stanzas) + if strvalue.endswith('\n'): + raise ValueError("value must not end in '\\n'") + + # Make sure there are no blank lines (actually, the first one is + # allowed to be blank, but no others), and each subsequent line starts + # with whitespace + for line in strvalue.splitlines()[1:]: + if not line: + raise ValueError("value must not have blank lines") + if not line[0] in string.whitespace: + raise ValueError("each line must start with whitespace") + + def __setitem__(self, key, value): + self.validate_input(key, value) + Deb822Dict.__setitem__(self, key, value) + ### # XXX check what happens if input contains more that one signature -- 1.6.3.3

