Browse Source

Merge pull request #1197 from octodns/chunked-text-escape-handling

Fix handling of chunked values (TXT) when escapes land on boundaries
pull/1201/head
Ross McFarland 1 year ago
committed by GitHub
parent
commit
abb8eb4808
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 5 deletions
  1. +2
    -0
      CHANGELOG.md
  2. +14
    -4
      octodns/record/chunked.py
  3. +49
    -1
      tests/test_octodns_record_chunked.py

+ 2
- 0
CHANGELOG.md View File

@ -3,6 +3,8 @@
* MetaProcessor.include_extra to add support for arbitrary extra values to be
set on the meta record.
* Correctly handled quoted svcparams when parsing SVCB/HTTPS rdata text
* Fix handling of chunked values (TXT, SPF) when escaped characters land at the
split boundaries, don't split escapes from their following chars
## v1.9.1 - 2024-06-21 - What's in a name


+ 14
- 4
octodns/record/chunked.py View File

@ -13,10 +13,20 @@ class _ChunkedValuesMixin(ValuesMixin):
def chunked_value(self, value):
value = value.replace('"', '\\"')
vs = [
value[i : i + self.CHUNK_SIZE]
for i in range(0, len(value), self.CHUNK_SIZE)
]
vs = []
i = 0
n = len(value)
# until we've processed the whole string
while i < n:
# start with a full chunk size
c = min(self.CHUNK_SIZE, n - i)
# make sure that we don't break on escape chars
while value[i + c - 1] == '\\':
c -= 1
# we have our chunk now
vs.append(value[i : i + c])
# and can step over if
i += c
vs = '" "'.join(vs)
return self._value_type(f'"{vs}"')


+ 49
- 1
tests/test_octodns_record_chunked.py View File

@ -4,8 +4,9 @@
from unittest import TestCase
from octodns.record.chunked import _ChunkedValue
from octodns.record.chunked import _ChunkedValue, _ChunkedValuesMixin
from octodns.record.spf import SpfRecord
from octodns.record.txt import TxtValue
from octodns.zone import Zone
@ -67,3 +68,50 @@ class TestChunkedValue(TestCase):
['non ASCII character in "Déjà vu"'],
_ChunkedValue.validate('Déjà vu', 'TXT'),
)
zone = Zone('unit.tests.', [])
# some hacks to let us work with smaller sizes
class Base:
def __init__(self, *args, **kwargs):
pass
class SmallerChunkedMixin(_ChunkedValuesMixin, Base):
CHUNK_SIZE = 8
_type = 'TXT'
_value_type = TxtValue
def __init__(self, values):
super().__init__(None, None, {'values': values})
def test_splitting(self):
for value, expected in (
# shorter
('0123', '"0123"'),
# exact
('01234567', '"01234567"'),
# simple
('0123456789', '"01234567" "89"'),
# 1 extra
('012345678', '"01234567" "8"'),
# escape in the middle
('01234\\;56789', '"01234\\;5" "6789"'),
# escape before the boundary
('012345\\;6789', '"012345\\;" "6789"'),
# escape after the boundary
('01234567\\;89', '"01234567" "\\;89"'),
# escape spanning the boundary
('0123456\\;789', '"0123456" "\\;789"'),
# multiple escapes at the boundary
('012345\\\\;6789', '"012345" "\\\\;6789"'),
# exact size escape
('012345\\;', '"012345\\;"'),
# spanning ending
('0123456\\;', '"0123456" "\\;"'),
):
sc = self.SmallerChunkedMixin(value)
self.assertEqual([expected], sc.chunked_values)
sc = self.SmallerChunkedMixin(['0123456789'])
self.assertEqual(['"01234567" "89"'], sc.chunked_values)

Loading…
Cancel
Save