mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
manifest_xml: ban use of newlines in paths
There should be no valid use of these anywhere, so just ban them to make things easier for people. Bug: https://crbug.com/gerrit/14156 Bug: https://crbug.com/gerrit/14200 Change-Id: I8d2cf988c510c98194c43a329a2b9bf313a3f0a8 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/304662 Reviewed-by: Raman Tenneti <rtenneti@google.com> Tested-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
parent
aabf79d3f0
commit
f69c7ee318
@ -1199,6 +1199,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
if '~' in path:
|
if '~' in path:
|
||||||
return '~ not allowed (due to 8.3 filenames on Windows filesystems)'
|
return '~ not allowed (due to 8.3 filenames on Windows filesystems)'
|
||||||
|
|
||||||
|
path_codepoints = set(path)
|
||||||
|
|
||||||
# Some filesystems (like Apple's HFS+) try to normalize Unicode codepoints
|
# Some filesystems (like Apple's HFS+) try to normalize Unicode codepoints
|
||||||
# which means there are alternative names for ".git". Reject paths with
|
# which means there are alternative names for ".git". Reject paths with
|
||||||
# these in it as there shouldn't be any reasonable need for them here.
|
# these in it as there shouldn't be any reasonable need for them here.
|
||||||
@ -1222,10 +1224,17 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
u'\u206F', # NOMINAL DIGIT SHAPES
|
u'\u206F', # NOMINAL DIGIT SHAPES
|
||||||
u'\uFEFF', # ZERO WIDTH NO-BREAK SPACE
|
u'\uFEFF', # ZERO WIDTH NO-BREAK SPACE
|
||||||
}
|
}
|
||||||
if BAD_CODEPOINTS & set(path):
|
if BAD_CODEPOINTS & path_codepoints:
|
||||||
# This message is more expansive than reality, but should be fine.
|
# This message is more expansive than reality, but should be fine.
|
||||||
return 'Unicode combining characters not allowed'
|
return 'Unicode combining characters not allowed'
|
||||||
|
|
||||||
|
# Reject newlines as there shouldn't be any legitmate use for them, they'll
|
||||||
|
# be confusing to users, and they can easily break tools that expect to be
|
||||||
|
# able to iterate over newline delimited lists. This even applies to our
|
||||||
|
# own code like .repo/project.list.
|
||||||
|
if {'\r', '\n'} & path_codepoints:
|
||||||
|
return 'Newlines not allowed'
|
||||||
|
|
||||||
# Assume paths might be used on case-insensitive filesystems.
|
# Assume paths might be used on case-insensitive filesystems.
|
||||||
path = path.lower()
|
path = path.lower()
|
||||||
|
|
||||||
|
@ -52,6 +52,9 @@ INVALID_FS_PATHS = (
|
|||||||
'blah/foo~',
|
'blah/foo~',
|
||||||
# Block Unicode characters that get normalized out by filesystems.
|
# Block Unicode characters that get normalized out by filesystems.
|
||||||
u'foo\u200Cbar',
|
u'foo\u200Cbar',
|
||||||
|
# Block newlines.
|
||||||
|
'f\n/bar',
|
||||||
|
'f\r/bar',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Make sure platforms that use path separators (e.g. Windows) are also
|
# Make sure platforms that use path separators (e.g. Windows) are also
|
||||||
@ -91,6 +94,11 @@ class ManifestParseTestCase(unittest.TestCase):
|
|||||||
fp.write(data)
|
fp.write(data)
|
||||||
return manifest_xml.XmlManifest(self.repodir, self.manifest_file)
|
return manifest_xml.XmlManifest(self.repodir, self.manifest_file)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def encodeXmlAttr(attr):
|
||||||
|
"""Encode |attr| using XML escape rules."""
|
||||||
|
return attr.replace('\r', '
').replace('\n', '
')
|
||||||
|
|
||||||
|
|
||||||
class ManifestValidateFilePaths(unittest.TestCase):
|
class ManifestValidateFilePaths(unittest.TestCase):
|
||||||
"""Check _ValidateFilePaths helper.
|
"""Check _ValidateFilePaths helper.
|
||||||
@ -303,6 +311,7 @@ class IncludeElementTests(ManifestParseTestCase):
|
|||||||
def test_allow_bad_name_from_user(self):
|
def test_allow_bad_name_from_user(self):
|
||||||
"""Check handling of bad name attribute from the user's input."""
|
"""Check handling of bad name attribute from the user's input."""
|
||||||
def parse(name):
|
def parse(name):
|
||||||
|
name = self.encodeXmlAttr(name)
|
||||||
manifest = self.getXmlManifest(f"""
|
manifest = self.getXmlManifest(f"""
|
||||||
<manifest>
|
<manifest>
|
||||||
<remote name="default-remote" fetch="http://localhost" />
|
<remote name="default-remote" fetch="http://localhost" />
|
||||||
@ -327,6 +336,7 @@ class IncludeElementTests(ManifestParseTestCase):
|
|||||||
def test_bad_name_checks(self):
|
def test_bad_name_checks(self):
|
||||||
"""Check handling of bad name attribute."""
|
"""Check handling of bad name attribute."""
|
||||||
def parse(name):
|
def parse(name):
|
||||||
|
name = self.encodeXmlAttr(name)
|
||||||
# Setup target of the include.
|
# Setup target of the include.
|
||||||
with open(os.path.join(self.manifest_dir, 'target.xml'), 'w') as fp:
|
with open(os.path.join(self.manifest_dir, 'target.xml'), 'w') as fp:
|
||||||
fp.write(f'<manifest><include name="{name}"/></manifest>')
|
fp.write(f'<manifest><include name="{name}"/></manifest>')
|
||||||
@ -408,6 +418,8 @@ class ProjectElementTests(ManifestParseTestCase):
|
|||||||
def test_trailing_slash(self):
|
def test_trailing_slash(self):
|
||||||
"""Check handling of trailing slashes in attributes."""
|
"""Check handling of trailing slashes in attributes."""
|
||||||
def parse(name, path):
|
def parse(name, path):
|
||||||
|
name = self.encodeXmlAttr(name)
|
||||||
|
path = self.encodeXmlAttr(path)
|
||||||
return self.getXmlManifest(f"""
|
return self.getXmlManifest(f"""
|
||||||
<manifest>
|
<manifest>
|
||||||
<remote name="default-remote" fetch="http://localhost" />
|
<remote name="default-remote" fetch="http://localhost" />
|
||||||
@ -437,6 +449,8 @@ class ProjectElementTests(ManifestParseTestCase):
|
|||||||
def test_toplevel_path(self):
|
def test_toplevel_path(self):
|
||||||
"""Check handling of path=. specially."""
|
"""Check handling of path=. specially."""
|
||||||
def parse(name, path):
|
def parse(name, path):
|
||||||
|
name = self.encodeXmlAttr(name)
|
||||||
|
path = self.encodeXmlAttr(path)
|
||||||
return self.getXmlManifest(f"""
|
return self.getXmlManifest(f"""
|
||||||
<manifest>
|
<manifest>
|
||||||
<remote name="default-remote" fetch="http://localhost" />
|
<remote name="default-remote" fetch="http://localhost" />
|
||||||
@ -453,6 +467,8 @@ class ProjectElementTests(ManifestParseTestCase):
|
|||||||
def test_bad_path_name_checks(self):
|
def test_bad_path_name_checks(self):
|
||||||
"""Check handling of bad path & name attributes."""
|
"""Check handling of bad path & name attributes."""
|
||||||
def parse(name, path):
|
def parse(name, path):
|
||||||
|
name = self.encodeXmlAttr(name)
|
||||||
|
path = self.encodeXmlAttr(path)
|
||||||
manifest = self.getXmlManifest(f"""
|
manifest = self.getXmlManifest(f"""
|
||||||
<manifest>
|
<manifest>
|
||||||
<remote name="default-remote" fetch="http://localhost" />
|
<remote name="default-remote" fetch="http://localhost" />
|
||||||
|
Loading…
Reference in New Issue
Block a user