From 82457288ea5b8f689caa0f0fb6f31ac0f5bb6820 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Wed, 19 Apr 2023 20:00:26 +0000 Subject: [PATCH 1/4] Added a test demonstrating an issue with very deeply nested llsd maps. --- tests/llsd_test.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/llsd_test.py b/tests/llsd_test.py index 6691c1c..46f64fe 100644 --- a/tests/llsd_test.py +++ b/tests/llsd_test.py @@ -1345,6 +1345,20 @@ def testMap(self): map_within_map_xml) self.assertXMLRoundtrip({}, blank_map_xml) + def testDeepMap(self): + """ + Test that formatting a deeply nested map does not cause a RecursionError + """ + + test_map = {"foo":"bar", "depth":0, "next":None} + max_depth = 200 + for depth in range(max_depth): + test_map = {"foo":"bar", "depth":depth, "next":test_map} + + # this should not throw an exception. + test_xml = self.llsd.as_xml(test_map) + + def testBinary(self): """ Test the parse and serialization of input type : binary. From ed393fde08e3669bbc9d2d9214aa10e1022b2563 Mon Sep 17 00:00:00 2001 From: Signal Linden Date: Fri, 21 Apr 2023 10:39:22 -0700 Subject: [PATCH 2/4] Add PyPI trusted publication (#12) Add PyPI trusted publication Publish llsd with PyPI's new [trusted publisher](https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/) functionality rather than an access token. --- .github/workflows/ci.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 538106e..0cfb27a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -60,6 +60,8 @@ jobs: name: Publish to PyPI needs: build runs-on: [ubuntu-latest] + permissions: + id-token: write if: github.event_name != 'pull_request' steps: - uses: actions/download-artifact@v3 @@ -73,11 +75,8 @@ jobs: - name: Test Publish package uses: pypa/gh-action-pypi-publish@release/v1 with: - password: ${{ secrets.SHARED_PYPI_TEST_TOKEN }} repository_url: https://test.pypi.org/legacy/ - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1 if: startsWith(github.event.ref, 'refs/tags/v') - with: - password: ${{ secrets.SHARED_PYPI_TOKEN }} From eb3b4168c5340e7053e508971550c6afbfc0ff15 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 4 May 2023 15:07:09 -0400 Subject: [PATCH 3/4] SL-18330: In XML formatter, avoid adding call stack depth. Making LLSDXMLFormatter._elt() accept a lambda was a tricky way to minimize source changes to existing _elt() calls in _ARRAY() and _MAP(). The trouble is that that added function entries for each level of a deeply-nested LLSD structure -- and with our users, we unfortunately do encounter deeply-nested large inventories. Log observed RecursionError failures in AIS. Explicitly write out the individual sequence of calls in _ARRAY(), _MAP() and the top-level _write(), the only callers to pass lambdas to _elt(). --- llsd/serde_xml.py | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/llsd/serde_xml.py b/llsd/serde_xml.py index 99d39b8..7dfeaa2 100644 --- a/llsd/serde_xml.py +++ b/llsd/serde_xml.py @@ -44,17 +44,13 @@ def _elt(self, name, contents=None): If 'contents' is omitted, write . If 'contents' is bytes, write contents. If 'contents' is str, write contents.encode('utf8'). - If 'contents' is callable, write , call contents(), write . """ if not contents: self.stream.writelines([b"<", name, b" />"]) else: - self.stream.writelines([b"<", name, b">"]) - if callable(contents): - contents() - else: - self.stream.write(_str_to_bytes(contents)) - self.stream.writelines([b""]) + self.stream.writelines([b"<", name, b">", + _str_to_bytes(contents), + b""]) def xml_esc(self, v): "Escape string or unicode object v for xml output" @@ -100,15 +96,16 @@ def _URI(self, v): def _DATE(self, v): return self._elt(b'date', _format_datestr(v)) def _ARRAY(self, v): - return self._elt( - b'array', - lambda: [self._generate(item) for item in v]) + self.stream.write(b'') + for item in v: + self._generate(item) + self.stream.write(b'') def _MAP(self, v): - return self._elt( - b'map', - lambda: [(self._elt(b'key', self.xml_esc(UnicodeType(key))), - self._generate(value)) - for key, value in v.items()]) + self.stream.write(b'') + for key, value in v.items(): + self._elt(b'key', self.xml_esc(UnicodeType(key))) + self._generate(value) + self.stream.write(b'') def _generate(self, something): "Generate xml from a single python object." @@ -127,8 +124,10 @@ def _write(self, something): :param something: A python object (typically a dict) to be serialized. """ - self.stream.write(b'') - self._elt(b"llsd", lambda: self._generate(something)) + self.stream.write(b'' + b'') + self._generate(something) + self.stream.write(b'') class LLSDXMLPrettyFormatter(LLSDXMLFormatter): From 46fdce0be06eb90cc2bf0bb4d1736cd81844b890 Mon Sep 17 00:00:00 2001 From: Signal Linden Date: Thu, 4 May 2023 12:36:02 -0700 Subject: [PATCH 4/4] Switch PyPI action param case to kebab Fixes deprecation warning about repository_url. --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0cfb27a..8ad9b57 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -75,7 +75,7 @@ jobs: - name: Test Publish package uses: pypa/gh-action-pypi-publish@release/v1 with: - repository_url: https://test.pypi.org/legacy/ + repository-url: https://test.pypi.org/legacy/ - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1