mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
Issue #13589: Fix some serialization primitives in the aifc module.
Patch by Oleg Plakhotnyuk.
This commit is contained in:
parent
c77bb65deb
commit
03757ec4a5
4 changed files with 71 additions and 18 deletions
48
Lib/aifc.py
48
Lib/aifc.py
|
@ -162,6 +162,12 @@ def _read_short(file):
|
||||||
except struct.error:
|
except struct.error:
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
|
def _read_ushort(file):
|
||||||
|
try:
|
||||||
|
return struct.unpack('>H', file.read(2))[0]
|
||||||
|
except struct.error:
|
||||||
|
raise EOFError
|
||||||
|
|
||||||
def _read_string(file):
|
def _read_string(file):
|
||||||
length = ord(file.read(1))
|
length = ord(file.read(1))
|
||||||
if length == 0:
|
if length == 0:
|
||||||
|
@ -194,13 +200,19 @@ def _read_float(f): # 10 bytes
|
||||||
def _write_short(f, x):
|
def _write_short(f, x):
|
||||||
f.write(struct.pack('>h', x))
|
f.write(struct.pack('>h', x))
|
||||||
|
|
||||||
|
def _write_ushort(f, x):
|
||||||
|
f.write(struct.pack('>H', x))
|
||||||
|
|
||||||
def _write_long(f, x):
|
def _write_long(f, x):
|
||||||
|
f.write(struct.pack('>l', x))
|
||||||
|
|
||||||
|
def _write_ulong(f, x):
|
||||||
f.write(struct.pack('>L', x))
|
f.write(struct.pack('>L', x))
|
||||||
|
|
||||||
def _write_string(f, s):
|
def _write_string(f, s):
|
||||||
if len(s) > 255:
|
if len(s) > 255:
|
||||||
raise ValueError("string exceeds maximum pstring length")
|
raise ValueError("string exceeds maximum pstring length")
|
||||||
f.write(struct.pack('b', len(s)))
|
f.write(struct.pack('B', len(s)))
|
||||||
f.write(s)
|
f.write(s)
|
||||||
if len(s) & 1 == 0:
|
if len(s) & 1 == 0:
|
||||||
f.write(b'\x00')
|
f.write(b'\x00')
|
||||||
|
@ -218,7 +230,7 @@ def _write_float(f, x):
|
||||||
lomant = 0
|
lomant = 0
|
||||||
else:
|
else:
|
||||||
fmant, expon = math.frexp(x)
|
fmant, expon = math.frexp(x)
|
||||||
if expon > 16384 or fmant >= 1: # Infinity or NaN
|
if expon > 16384 or fmant >= 1 or fmant != fmant: # Infinity or NaN
|
||||||
expon = sign|0x7FFF
|
expon = sign|0x7FFF
|
||||||
himant = 0
|
himant = 0
|
||||||
lomant = 0
|
lomant = 0
|
||||||
|
@ -234,9 +246,9 @@ def _write_float(f, x):
|
||||||
fmant = math.ldexp(fmant - fsmant, 32)
|
fmant = math.ldexp(fmant - fsmant, 32)
|
||||||
fsmant = math.floor(fmant)
|
fsmant = math.floor(fmant)
|
||||||
lomant = int(fsmant)
|
lomant = int(fsmant)
|
||||||
_write_short(f, expon)
|
_write_ushort(f, expon)
|
||||||
_write_long(f, himant)
|
_write_ulong(f, himant)
|
||||||
_write_long(f, lomant)
|
_write_ulong(f, lomant)
|
||||||
|
|
||||||
from chunk import Chunk
|
from chunk import Chunk
|
||||||
|
|
||||||
|
@ -762,15 +774,15 @@ class Aifc_write:
|
||||||
if self._aifc:
|
if self._aifc:
|
||||||
self._file.write(b'AIFC')
|
self._file.write(b'AIFC')
|
||||||
self._file.write(b'FVER')
|
self._file.write(b'FVER')
|
||||||
_write_long(self._file, 4)
|
_write_ulong(self._file, 4)
|
||||||
_write_long(self._file, self._version)
|
_write_ulong(self._file, self._version)
|
||||||
else:
|
else:
|
||||||
self._file.write(b'AIFF')
|
self._file.write(b'AIFF')
|
||||||
self._file.write(b'COMM')
|
self._file.write(b'COMM')
|
||||||
_write_long(self._file, commlength)
|
_write_ulong(self._file, commlength)
|
||||||
_write_short(self._file, self._nchannels)
|
_write_short(self._file, self._nchannels)
|
||||||
self._nframes_pos = self._file.tell()
|
self._nframes_pos = self._file.tell()
|
||||||
_write_long(self._file, self._nframes)
|
_write_ulong(self._file, self._nframes)
|
||||||
_write_short(self._file, self._sampwidth * 8)
|
_write_short(self._file, self._sampwidth * 8)
|
||||||
_write_float(self._file, self._framerate)
|
_write_float(self._file, self._framerate)
|
||||||
if self._aifc:
|
if self._aifc:
|
||||||
|
@ -778,9 +790,9 @@ class Aifc_write:
|
||||||
_write_string(self._file, self._compname)
|
_write_string(self._file, self._compname)
|
||||||
self._file.write(b'SSND')
|
self._file.write(b'SSND')
|
||||||
self._ssnd_length_pos = self._file.tell()
|
self._ssnd_length_pos = self._file.tell()
|
||||||
_write_long(self._file, self._datalength + 8)
|
_write_ulong(self._file, self._datalength + 8)
|
||||||
_write_long(self._file, 0)
|
_write_ulong(self._file, 0)
|
||||||
_write_long(self._file, 0)
|
_write_ulong(self._file, 0)
|
||||||
|
|
||||||
def _write_form_length(self, datalength):
|
def _write_form_length(self, datalength):
|
||||||
if self._aifc:
|
if self._aifc:
|
||||||
|
@ -791,8 +803,8 @@ class Aifc_write:
|
||||||
else:
|
else:
|
||||||
commlength = 18
|
commlength = 18
|
||||||
verslength = 0
|
verslength = 0
|
||||||
_write_long(self._file, 4 + verslength + self._marklength + \
|
_write_ulong(self._file, 4 + verslength + self._marklength + \
|
||||||
8 + commlength + 16 + datalength)
|
8 + commlength + 16 + datalength)
|
||||||
return commlength
|
return commlength
|
||||||
|
|
||||||
def _patchheader(self):
|
def _patchheader(self):
|
||||||
|
@ -810,9 +822,9 @@ class Aifc_write:
|
||||||
self._file.seek(self._form_length_pos, 0)
|
self._file.seek(self._form_length_pos, 0)
|
||||||
dummy = self._write_form_length(datalength)
|
dummy = self._write_form_length(datalength)
|
||||||
self._file.seek(self._nframes_pos, 0)
|
self._file.seek(self._nframes_pos, 0)
|
||||||
_write_long(self._file, self._nframeswritten)
|
_write_ulong(self._file, self._nframeswritten)
|
||||||
self._file.seek(self._ssnd_length_pos, 0)
|
self._file.seek(self._ssnd_length_pos, 0)
|
||||||
_write_long(self._file, datalength + 8)
|
_write_ulong(self._file, datalength + 8)
|
||||||
self._file.seek(curpos, 0)
|
self._file.seek(curpos, 0)
|
||||||
self._nframes = self._nframeswritten
|
self._nframes = self._nframeswritten
|
||||||
self._datalength = datalength
|
self._datalength = datalength
|
||||||
|
@ -827,13 +839,13 @@ class Aifc_write:
|
||||||
length = length + len(name) + 1 + 6
|
length = length + len(name) + 1 + 6
|
||||||
if len(name) & 1 == 0:
|
if len(name) & 1 == 0:
|
||||||
length = length + 1
|
length = length + 1
|
||||||
_write_long(self._file, length)
|
_write_ulong(self._file, length)
|
||||||
self._marklength = length + 8
|
self._marklength = length + 8
|
||||||
_write_short(self._file, len(self._markers))
|
_write_short(self._file, len(self._markers))
|
||||||
for marker in self._markers:
|
for marker in self._markers:
|
||||||
id, pos, name = marker
|
id, pos, name = marker
|
||||||
_write_short(self._file, id)
|
_write_short(self._file, id)
|
||||||
_write_long(self._file, pos)
|
_write_ulong(self._file, pos)
|
||||||
_write_string(self._file, name)
|
_write_string(self._file, name)
|
||||||
|
|
||||||
def open(f, mode=None):
|
def open(f, mode=None):
|
||||||
|
|
|
@ -144,8 +144,45 @@ class AIFCTest(unittest.TestCase):
|
||||||
self.assertRaises(aifc.Error, f.getmark, 3)
|
self.assertRaises(aifc.Error, f.getmark, 3)
|
||||||
|
|
||||||
|
|
||||||
|
class AIFCLowLevelTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_read_written(self):
|
||||||
|
def read_written(self, what):
|
||||||
|
f = io.BytesIO()
|
||||||
|
getattr(aifc, '_write_' + what)(f, x)
|
||||||
|
f.seek(0)
|
||||||
|
return getattr(aifc, '_read_' + what)(f)
|
||||||
|
for x in (-1, 0, 0.1, 1):
|
||||||
|
self.assertEqual(read_written(x, 'float'), x)
|
||||||
|
for x in (float('NaN'), float('Inf')):
|
||||||
|
self.assertEqual(read_written(x, 'float'), aifc._HUGE_VAL)
|
||||||
|
for x in (b'', b'foo', b'a' * 255):
|
||||||
|
self.assertEqual(read_written(x, 'string'), x)
|
||||||
|
for x in (-0x7FFFFFFF, -1, 0, 1, 0x7FFFFFFF):
|
||||||
|
self.assertEqual(read_written(x, 'long'), x)
|
||||||
|
for x in (0, 1, 0xFFFFFFFF):
|
||||||
|
self.assertEqual(read_written(x, 'ulong'), x)
|
||||||
|
for x in (-0x7FFF, -1, 0, 1, 0x7FFF):
|
||||||
|
self.assertEqual(read_written(x, 'short'), x)
|
||||||
|
for x in (0, 1, 0xFFFF):
|
||||||
|
self.assertEqual(read_written(x, 'ushort'), x)
|
||||||
|
|
||||||
|
def test_read_raises(self):
|
||||||
|
f = io.BytesIO(b'\x00')
|
||||||
|
self.assertRaises(EOFError, aifc._read_ulong, f)
|
||||||
|
self.assertRaises(EOFError, aifc._read_long, f)
|
||||||
|
self.assertRaises(EOFError, aifc._read_ushort, f)
|
||||||
|
self.assertRaises(EOFError, aifc._read_short, f)
|
||||||
|
|
||||||
|
def test_write_long_string_raises(self):
|
||||||
|
f = io.BytesIO()
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
aifc._write_string(f, b'too long' * 255)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
run_unittest(AIFCTest)
|
run_unittest(AIFCTest)
|
||||||
|
run_unittest(AIFCLowLevelTest)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -719,6 +719,7 @@ Zach Pincus
|
||||||
Michael Piotrowski
|
Michael Piotrowski
|
||||||
Antoine Pitrou
|
Antoine Pitrou
|
||||||
Jean-François Piéronne
|
Jean-François Piéronne
|
||||||
|
Oleg Plakhotnyuk
|
||||||
Guilherme Polo
|
Guilherme Polo
|
||||||
Michael Pomraning
|
Michael Pomraning
|
||||||
Iustin Pop
|
Iustin Pop
|
||||||
|
|
|
@ -100,6 +100,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #13589: Fix some serialization primitives in the aifc module.
|
||||||
|
Patch by Oleg Plakhotnyuk.
|
||||||
|
|
||||||
- Issue #13642: Unquote before b64encoding user:password during Basic
|
- Issue #13642: Unquote before b64encoding user:password during Basic
|
||||||
Authentication. Patch contributed by Joonas Kuorilehto.
|
Authentication. Patch contributed by Joonas Kuorilehto.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue