mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-09-11 23:23:27 +02:00
metadata: handle SHA-256 values that parse as decimal ints
https://gitlab.com/fdroid/fdroidserver/-/merge_requests/1350#note_1370665635
This commit is contained in:
parent
642e444cfa
commit
2aa0403208
@ -908,6 +908,11 @@ def _normalize_type_string(v):
|
|||||||
numbers. Like "versionName: 1.0" would be a YAML float, but
|
numbers. Like "versionName: 1.0" would be a YAML float, but
|
||||||
should be a string.
|
should be a string.
|
||||||
|
|
||||||
|
SHA-256 values are string values, but YAML 1.2 can interpret some
|
||||||
|
unquoted values as decimal ints. This converts those to a string
|
||||||
|
if they are over 50 digits. In the wild, the longest 0 padding on
|
||||||
|
a SHA-256 key fingerprint I found was 8 zeros.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
if v:
|
if v:
|
||||||
@ -921,6 +926,9 @@ def _normalize_type_string(v):
|
|||||||
if v > 0:
|
if v > 0:
|
||||||
return '.inf'
|
return '.inf'
|
||||||
return '-.inf'
|
return '-.inf'
|
||||||
|
if v and isinstance(v, int):
|
||||||
|
if math.log10(v) > 50: # only if the int has this many digits
|
||||||
|
return '%064d' % v
|
||||||
return str(v)
|
return str(v)
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,6 +343,13 @@ class MetadataTest(unittest.TestCase):
|
|||||||
self.assertEqual('false', metadata._normalize_type_string(False))
|
self.assertEqual('false', metadata._normalize_type_string(False))
|
||||||
self.assertEqual('true', metadata._normalize_type_string(True))
|
self.assertEqual('true', metadata._normalize_type_string(True))
|
||||||
|
|
||||||
|
def test_normalize_type_string_sha256(self):
|
||||||
|
"""SHA-256 values are TYPE_STRING, which YAML can parse as decimal ints."""
|
||||||
|
yaml = ruamel.yaml.YAML(typ='safe')
|
||||||
|
for v in range(1, 1000):
|
||||||
|
s = '%064d' % (v * (10**51))
|
||||||
|
self.assertEqual(s, metadata._normalize_type_string(yaml.load(s)))
|
||||||
|
|
||||||
def test_normalize_type_stringmap_none(self):
|
def test_normalize_type_stringmap_none(self):
|
||||||
self.assertEqual(dict(), metadata._normalize_type_stringmap('key', None))
|
self.assertEqual(dict(), metadata._normalize_type_stringmap('key', None))
|
||||||
|
|
||||||
@ -420,13 +427,13 @@ class MetadataTest(unittest.TestCase):
|
|||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
metadata.post_parse_yaml_metadata(yamldata)
|
metadata.post_parse_yaml_metadata(yamldata)
|
||||||
|
|
||||||
def test_post_parse_yaml_metadata_0padding_fails(self):
|
def test_post_parse_yaml_metadata_0padding_sha256(self):
|
||||||
"""Special case: ideally 0 padding would be kept in string, but it is not."""
|
"""SHA-256 values are strings, but YAML 1.2 will read some as decimal ints."""
|
||||||
v = '0027293472934293872934729834729834729834729834792837487293847926'
|
v = '0027293472934293872934729834729834729834729834792837487293847926'
|
||||||
yaml = ruamel.yaml.YAML(typ='safe')
|
yaml = ruamel.yaml.YAML(typ='safe')
|
||||||
yamldata = yaml.load('AllowedAPKSigningKeys: ' + v)
|
yamldata = yaml.load('AllowedAPKSigningKeys: ' + v)
|
||||||
metadata.post_parse_yaml_metadata(yamldata)
|
metadata.post_parse_yaml_metadata(yamldata)
|
||||||
self.assertNotEqual(yamldata['AllowedAPKSigningKeys'], v)
|
self.assertEqual(yamldata['AllowedAPKSigningKeys'], [v])
|
||||||
|
|
||||||
def test_post_parse_yaml_metadata_builds(self):
|
def test_post_parse_yaml_metadata_builds(self):
|
||||||
yamldata = OrderedDict()
|
yamldata = OrderedDict()
|
||||||
@ -543,28 +550,6 @@ class MetadataTest(unittest.TestCase):
|
|||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
metadata.parse_yaml_metadata(mf)
|
metadata.parse_yaml_metadata(mf)
|
||||||
|
|
||||||
def test_parse_yaml_metadata_0padding_fails(self):
|
|
||||||
"""Special case: ideally this would keep 0 padding in string, but it does not.
|
|
||||||
|
|
||||||
It seems the only option is to quote values like that, or add
|
|
||||||
quirks to the YAML parsing.
|
|
||||||
|
|
||||||
"""
|
|
||||||
v = '0027293472934293872934729834729834729834729834792837487293847926'
|
|
||||||
mf = io.StringIO('AllowedAPKSigningKeys: %s' % v)
|
|
||||||
mf.name = 'mock_filename.yaml'
|
|
||||||
self.assertNotEqual(
|
|
||||||
v,
|
|
||||||
metadata.parse_yaml_metadata(mf)['AllowedAPKSigningKeys'][0],
|
|
||||||
)
|
|
||||||
|
|
||||||
mf = io.StringIO('AllowedAPKSigningKeys: "%s"' % v)
|
|
||||||
mf.name = 'mock_filename.yaml'
|
|
||||||
self.assertEqual(
|
|
||||||
v,
|
|
||||||
metadata.parse_yaml_metadata(mf)['AllowedAPKSigningKeys'][0],
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_parse_yaml_metadata_unknown_app_field(self):
|
def test_parse_yaml_metadata_unknown_app_field(self):
|
||||||
mf = io.StringIO(
|
mf = io.StringIO(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
@ -2146,6 +2131,24 @@ class PostMetadataParseTest(unittest.TestCase):
|
|||||||
self.assertEqual(*self._post_metadata_parse_build_script(123456, ['123456']))
|
self.assertEqual(*self._post_metadata_parse_build_script(123456, ['123456']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(123456, '123456'))
|
self.assertEqual(*self._post_metadata_parse_build_string(123456, '123456'))
|
||||||
|
|
||||||
|
def test_post_metadata_parse_sha256(self):
|
||||||
|
"""Run a SHA-256 that YAML calls an int through the various types.
|
||||||
|
|
||||||
|
The current f-droid.org signer set has SHA-256 values with a
|
||||||
|
maximum of two leading zeros, but this will handle more.
|
||||||
|
|
||||||
|
"""
|
||||||
|
yaml = ruamel.yaml.YAML(typ='safe', pure=True)
|
||||||
|
str_sha256 = '0000000000000498456908409534729834729834729834792837487293847926'
|
||||||
|
sha256 = yaml.load('a: ' + str_sha256)['a']
|
||||||
|
self.assertEqual(*self._post_metadata_parse_app_list(sha256, [str_sha256]))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_app_string(sha256, str_sha256))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_bool(sha256, True))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_int(sha256, sha256))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_list(sha256, [str_sha256]))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_script(sha256, [str_sha256]))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_string(sha256, str_sha256))
|
||||||
|
|
||||||
def test_post_metadata_parse_int_0(self):
|
def test_post_metadata_parse_int_0(self):
|
||||||
"""Run the int 0 through the various field and flag types."""
|
"""Run the int 0 through the various field and flag types."""
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list(0, ['0']))
|
self.assertEqual(*self._post_metadata_parse_app_list(0, ['0']))
|
||||||
|
Loading…
Reference in New Issue
Block a user