1from collections import abc 2import array 3import math 4import operator 5import unittest 6import struct 7import sys 8 9from test import support 10 11ISBIGENDIAN = sys.byteorder == "big" 12 13integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N' 14byteorders = '', '@', '=', '<', '>', '!' 15 16def iter_integer_formats(byteorders=byteorders): 17 for code in integer_codes: 18 for byteorder in byteorders: 19 if (byteorder not in ('', '@') and code in ('n', 'N')): 20 continue 21 yield code, byteorder 22 23def string_reverse(s): 24 return s[::-1] 25 26def bigendian_to_native(value): 27 if ISBIGENDIAN: 28 return value 29 else: 30 return string_reverse(value) 31 32class StructTest(unittest.TestCase): 33 def test_isbigendian(self): 34 self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN) 35 36 def test_consistence(self): 37 self.assertRaises(struct.error, struct.calcsize, 'Z') 38 39 sz = struct.calcsize('i') 40 self.assertEqual(sz * 3, struct.calcsize('iii')) 41 42 fmt = 'cbxxxxxxhhhhiillffd?' 43 fmt3 = '3c3b18x12h6i6l6f3d3?' 44 sz = struct.calcsize(fmt) 45 sz3 = struct.calcsize(fmt3) 46 self.assertEqual(sz * 3, sz3) 47 48 self.assertRaises(struct.error, struct.pack, 'iii', 3) 49 self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3) 50 self.assertRaises((TypeError, struct.error), struct.pack, 'i', 'foo') 51 self.assertRaises((TypeError, struct.error), struct.pack, 'P', 'foo') 52 self.assertRaises(struct.error, struct.unpack, 'd', b'flap') 53 s = struct.pack('ii', 1, 2) 54 self.assertRaises(struct.error, struct.unpack, 'iii', s) 55 self.assertRaises(struct.error, struct.unpack, 'i', s) 56 57 def test_transitiveness(self): 58 c = b'a' 59 b = 1 60 h = 255 61 i = 65535 62 l = 65536 63 f = 3.1415 64 d = 3.1415 65 t = True 66 67 for prefix in ('', '@', '<', '>', '=', '!'): 68 for format in ('xcbhilfd?', 'xcBHILfd?'): 69 format = prefix + format 70 s = struct.pack(format, c, b, h, i, l, f, d, t) 71 cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s) 72 self.assertEqual(cp, c) 73 self.assertEqual(bp, b) 74 self.assertEqual(hp, h) 75 self.assertEqual(ip, i) 76 self.assertEqual(lp, l) 77 self.assertEqual(int(100 * fp), int(100 * f)) 78 self.assertEqual(int(100 * dp), int(100 * d)) 79 self.assertEqual(tp, t) 80 81 def test_new_features(self): 82 # Test some of the new features in detail 83 # (format, argument, big-endian result, little-endian result, asymmetric) 84 tests = [ 85 ('c', b'a', b'a', b'a', 0), 86 ('xc', b'a', b'\0a', b'\0a', 0), 87 ('cx', b'a', b'a\0', b'a\0', 0), 88 ('s', b'a', b'a', b'a', 0), 89 ('0s', b'helloworld', b'', b'', 1), 90 ('1s', b'helloworld', b'h', b'h', 1), 91 ('9s', b'helloworld', b'helloworl', b'helloworl', 1), 92 ('10s', b'helloworld', b'helloworld', b'helloworld', 0), 93 ('11s', b'helloworld', b'helloworld\0', b'helloworld\0', 1), 94 ('20s', b'helloworld', b'helloworld'+10*b'\0', b'helloworld'+10*b'\0', 1), 95 ('b', 7, b'\7', b'\7', 0), 96 ('b', -7, b'\371', b'\371', 0), 97 ('B', 7, b'\7', b'\7', 0), 98 ('B', 249, b'\371', b'\371', 0), 99 ('h', 700, b'\002\274', b'\274\002', 0), 100 ('h', -700, b'\375D', b'D\375', 0), 101 ('H', 700, b'\002\274', b'\274\002', 0), 102 ('H', 0x10000-700, b'\375D', b'D\375', 0), 103 ('i', 70000000, b'\004,\035\200', b'\200\035,\004', 0), 104 ('i', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0), 105 ('I', 70000000, b'\004,\035\200', b'\200\035,\004', 0), 106 ('I', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0), 107 ('l', 70000000, b'\004,\035\200', b'\200\035,\004', 0), 108 ('l', -70000000, b'\373\323\342\200', b'\200\342\323\373', 0), 109 ('L', 70000000, b'\004,\035\200', b'\200\035,\004', 0), 110 ('L', 0x100000000-70000000, b'\373\323\342\200', b'\200\342\323\373', 0), 111 ('f', 2.0, b'@\000\000\000', b'\000\000\000@', 0), 112 ('d', 2.0, b'@\000\000\000\000\000\000\000', 113 b'\000\000\000\000\000\000\000@', 0), 114 ('f', -2.0, b'\300\000\000\000', b'\000\000\000\300', 0), 115 ('d', -2.0, b'\300\000\000\000\000\000\000\000', 116 b'\000\000\000\000\000\000\000\300', 0), 117 ('?', 0, b'\0', b'\0', 0), 118 ('?', 3, b'\1', b'\1', 1), 119 ('?', True, b'\1', b'\1', 0), 120 ('?', [], b'\0', b'\0', 1), 121 ('?', (1,), b'\1', b'\1', 1), 122 ] 123 124 for fmt, arg, big, lil, asy in tests: 125 for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil), 126 ('='+fmt, ISBIGENDIAN and big or lil)]: 127 res = struct.pack(xfmt, arg) 128 self.assertEqual(res, exp) 129 self.assertEqual(struct.calcsize(xfmt), len(res)) 130 rev = struct.unpack(xfmt, res)[0] 131 if rev != arg: 132 self.assertTrue(asy) 133 134 def test_calcsize(self): 135 expected_size = { 136 'b': 1, 'B': 1, 137 'h': 2, 'H': 2, 138 'i': 4, 'I': 4, 139 'l': 4, 'L': 4, 140 'q': 8, 'Q': 8, 141 } 142 143 # standard integer sizes 144 for code, byteorder in iter_integer_formats(('=', '<', '>', '!')): 145 format = byteorder+code 146 size = struct.calcsize(format) 147 self.assertEqual(size, expected_size[code]) 148 149 # native integer sizes 150 native_pairs = 'bB', 'hH', 'iI', 'lL', 'nN', 'qQ' 151 for format_pair in native_pairs: 152 for byteorder in '', '@': 153 signed_size = struct.calcsize(byteorder + format_pair[0]) 154 unsigned_size = struct.calcsize(byteorder + format_pair[1]) 155 self.assertEqual(signed_size, unsigned_size) 156 157 # bounds for native integer sizes 158 self.assertEqual(struct.calcsize('b'), 1) 159 self.assertLessEqual(2, struct.calcsize('h')) 160 self.assertLessEqual(4, struct.calcsize('l')) 161 self.assertLessEqual(struct.calcsize('h'), struct.calcsize('i')) 162 self.assertLessEqual(struct.calcsize('i'), struct.calcsize('l')) 163 self.assertLessEqual(8, struct.calcsize('q')) 164 self.assertLessEqual(struct.calcsize('l'), struct.calcsize('q')) 165 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('i')) 166 self.assertGreaterEqual(struct.calcsize('n'), struct.calcsize('P')) 167 168 def test_integers(self): 169 # Integer tests (bBhHiIlLqQnN). 170 import binascii 171 172 class IntTester(unittest.TestCase): 173 def __init__(self, format): 174 super(IntTester, self).__init__(methodName='test_one') 175 self.format = format 176 self.code = format[-1] 177 self.byteorder = format[:-1] 178 if not self.byteorder in byteorders: 179 raise ValueError("unrecognized packing byteorder: %s" % 180 self.byteorder) 181 self.bytesize = struct.calcsize(format) 182 self.bitsize = self.bytesize * 8 183 if self.code in tuple('bhilqn'): 184 self.signed = True 185 self.min_value = -(2**(self.bitsize-1)) 186 self.max_value = 2**(self.bitsize-1) - 1 187 elif self.code in tuple('BHILQN'): 188 self.signed = False 189 self.min_value = 0 190 self.max_value = 2**self.bitsize - 1 191 else: 192 raise ValueError("unrecognized format code: %s" % 193 self.code) 194 195 def test_one(self, x, pack=struct.pack, 196 unpack=struct.unpack, 197 unhexlify=binascii.unhexlify): 198 199 format = self.format 200 if self.min_value <= x <= self.max_value: 201 expected = x 202 if self.signed and x < 0: 203 expected += 1 << self.bitsize 204 self.assertGreaterEqual(expected, 0) 205 expected = '%x' % expected 206 if len(expected) & 1: 207 expected = "0" + expected 208 expected = expected.encode('ascii') 209 expected = unhexlify(expected) 210 expected = (b"\x00" * (self.bytesize - len(expected)) + 211 expected) 212 if (self.byteorder == '<' or 213 self.byteorder in ('', '@', '=') and not ISBIGENDIAN): 214 expected = string_reverse(expected) 215 self.assertEqual(len(expected), self.bytesize) 216 217 # Pack work? 218 got = pack(format, x) 219 self.assertEqual(got, expected) 220 221 # Unpack work? 222 retrieved = unpack(format, got)[0] 223 self.assertEqual(x, retrieved) 224 225 # Adding any byte should cause a "too big" error. 226 self.assertRaises((struct.error, TypeError), unpack, format, 227 b'\x01' + got) 228 else: 229 # x is out of range -- verify pack realizes that. 230 self.assertRaises((OverflowError, ValueError, struct.error), 231 pack, format, x) 232 233 def run(self): 234 from random import randrange 235 236 # Create all interesting powers of 2. 237 values = [] 238 for exp in range(self.bitsize + 3): 239 values.append(1 << exp) 240 241 # Add some random values. 242 for i in range(self.bitsize): 243 val = 0 244 for j in range(self.bytesize): 245 val = (val << 8) | randrange(256) 246 values.append(val) 247 248 # Values absorbed from other tests 249 values.extend([300, 700000, sys.maxsize*4]) 250 251 # Try all those, and their negations, and +-1 from 252 # them. Note that this tests all power-of-2 253 # boundaries in range, and a few out of range, plus 254 # +-(2**n +- 1). 255 for base in values: 256 for val in -base, base: 257 for incr in -1, 0, 1: 258 x = val + incr 259 self.test_one(x) 260 261 # Some error cases. 262 class NotAnInt: 263 def __int__(self): 264 return 42 265 266 # Objects with an '__index__' method should be allowed 267 # to pack as integers. That is assuming the implemented 268 # '__index__' method returns an 'int'. 269 class Indexable(object): 270 def __init__(self, value): 271 self._value = value 272 273 def __index__(self): 274 return self._value 275 276 # If the '__index__' method raises a type error, then 277 # '__int__' should be used with a deprecation warning. 278 class BadIndex(object): 279 def __index__(self): 280 raise TypeError 281 282 def __int__(self): 283 return 42 284 285 self.assertRaises((TypeError, struct.error), 286 struct.pack, self.format, 287 "a string") 288 self.assertRaises((TypeError, struct.error), 289 struct.pack, self.format, 290 randrange) 291 self.assertRaises((TypeError, struct.error), 292 struct.pack, self.format, 293 3+42j) 294 self.assertRaises((TypeError, struct.error), 295 struct.pack, self.format, 296 NotAnInt()) 297 self.assertRaises((TypeError, struct.error), 298 struct.pack, self.format, 299 BadIndex()) 300 301 # Check for legitimate values from '__index__'. 302 for obj in (Indexable(0), Indexable(10), Indexable(17), 303 Indexable(42), Indexable(100), Indexable(127)): 304 try: 305 struct.pack(format, obj) 306 except: 307 self.fail("integer code pack failed on object " 308 "with '__index__' method") 309 310 # Check for bogus values from '__index__'. 311 for obj in (Indexable(b'a'), Indexable('b'), Indexable(None), 312 Indexable({'a': 1}), Indexable([1, 2, 3])): 313 self.assertRaises((TypeError, struct.error), 314 struct.pack, self.format, 315 obj) 316 317 for code, byteorder in iter_integer_formats(): 318 format = byteorder+code 319 t = IntTester(format) 320 t.run() 321 322 def test_nN_code(self): 323 # n and N don't exist in standard sizes 324 def assertStructError(func, *args, **kwargs): 325 with self.assertRaises(struct.error) as cm: 326 func(*args, **kwargs) 327 self.assertIn("bad char in struct format", str(cm.exception)) 328 for code in 'nN': 329 for byteorder in ('=', '<', '>', '!'): 330 format = byteorder+code 331 assertStructError(struct.calcsize, format) 332 assertStructError(struct.pack, format, 0) 333 assertStructError(struct.unpack, format, b"") 334 335 def test_p_code(self): 336 # Test p ("Pascal string") code. 337 for code, input, expected, expectedback in [ 338 ('p', b'abc', b'\x00', b''), 339 ('1p', b'abc', b'\x00', b''), 340 ('2p', b'abc', b'\x01a', b'a'), 341 ('3p', b'abc', b'\x02ab', b'ab'), 342 ('4p', b'abc', b'\x03abc', b'abc'), 343 ('5p', b'abc', b'\x03abc\x00', b'abc'), 344 ('6p', b'abc', b'\x03abc\x00\x00', b'abc'), 345 ('1000p', b'x'*1000, b'\xff' + b'x'*999, b'x'*255)]: 346 got = struct.pack(code, input) 347 self.assertEqual(got, expected) 348 (got,) = struct.unpack(code, got) 349 self.assertEqual(got, expectedback) 350 351 def test_705836(self): 352 # SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry 353 # from the low-order discarded bits could propagate into the exponent 354 # field, causing the result to be wrong by a factor of 2. 355 for base in range(1, 33): 356 # smaller <- largest representable float less than base. 357 delta = 0.5 358 while base - delta / 2.0 != base: 359 delta /= 2.0 360 smaller = base - delta 361 # Packing this rounds away a solid string of trailing 1 bits. 362 packed = struct.pack("<f", smaller) 363 unpacked = struct.unpack("<f", packed)[0] 364 # This failed at base = 2, 4, and 32, with unpacked = 1, 2, and 365 # 16, respectively. 366 self.assertEqual(base, unpacked) 367 bigpacked = struct.pack(">f", smaller) 368 self.assertEqual(bigpacked, string_reverse(packed)) 369 unpacked = struct.unpack(">f", bigpacked)[0] 370 self.assertEqual(base, unpacked) 371 372 # Largest finite IEEE single. 373 big = (1 << 24) - 1 374 big = math.ldexp(big, 127 - 23) 375 packed = struct.pack(">f", big) 376 unpacked = struct.unpack(">f", packed)[0] 377 self.assertEqual(big, unpacked) 378 379 # The same, but tack on a 1 bit so it rounds up to infinity. 380 big = (1 << 25) - 1 381 big = math.ldexp(big, 127 - 24) 382 self.assertRaises(OverflowError, struct.pack, ">f", big) 383 384 def test_1530559(self): 385 for code, byteorder in iter_integer_formats(): 386 format = byteorder + code 387 self.assertRaises(struct.error, struct.pack, format, 1.0) 388 self.assertRaises(struct.error, struct.pack, format, 1.5) 389 self.assertRaises(struct.error, struct.pack, 'P', 1.0) 390 self.assertRaises(struct.error, struct.pack, 'P', 1.5) 391 392 def test_unpack_from(self): 393 test_string = b'abcd01234' 394 fmt = '4s' 395 s = struct.Struct(fmt) 396 for cls in (bytes, bytearray): 397 data = cls(test_string) 398 self.assertEqual(s.unpack_from(data), (b'abcd',)) 399 self.assertEqual(s.unpack_from(data, 2), (b'cd01',)) 400 self.assertEqual(s.unpack_from(data, 4), (b'0123',)) 401 for i in range(6): 402 self.assertEqual(s.unpack_from(data, i), (data[i:i+4],)) 403 for i in range(6, len(test_string) + 1): 404 self.assertRaises(struct.error, s.unpack_from, data, i) 405 for cls in (bytes, bytearray): 406 data = cls(test_string) 407 self.assertEqual(struct.unpack_from(fmt, data), (b'abcd',)) 408 self.assertEqual(struct.unpack_from(fmt, data, 2), (b'cd01',)) 409 self.assertEqual(struct.unpack_from(fmt, data, 4), (b'0123',)) 410 for i in range(6): 411 self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],)) 412 for i in range(6, len(test_string) + 1): 413 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i) 414 415 # keyword arguments 416 self.assertEqual(s.unpack_from(buffer=test_string, offset=2), 417 (b'cd01',)) 418 419 def test_pack_into(self): 420 test_string = b'Reykjavik rocks, eow!' 421 writable_buf = array.array('b', b' '*100) 422 fmt = '21s' 423 s = struct.Struct(fmt) 424 425 # Test without offset 426 s.pack_into(writable_buf, 0, test_string) 427 from_buf = writable_buf.tobytes()[:len(test_string)] 428 self.assertEqual(from_buf, test_string) 429 430 # Test with offset. 431 s.pack_into(writable_buf, 10, test_string) 432 from_buf = writable_buf.tobytes()[:len(test_string)+10] 433 self.assertEqual(from_buf, test_string[:10] + test_string) 434 435 # Go beyond boundaries. 436 small_buf = array.array('b', b' '*10) 437 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0, 438 test_string) 439 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2, 440 test_string) 441 442 # Test bogus offset (issue 3694) 443 sb = small_buf 444 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb, 445 None) 446 447 def test_pack_into_fn(self): 448 test_string = b'Reykjavik rocks, eow!' 449 writable_buf = array.array('b', b' '*100) 450 fmt = '21s' 451 pack_into = lambda *args: struct.pack_into(fmt, *args) 452 453 # Test without offset. 454 pack_into(writable_buf, 0, test_string) 455 from_buf = writable_buf.tobytes()[:len(test_string)] 456 self.assertEqual(from_buf, test_string) 457 458 # Test with offset. 459 pack_into(writable_buf, 10, test_string) 460 from_buf = writable_buf.tobytes()[:len(test_string)+10] 461 self.assertEqual(from_buf, test_string[:10] + test_string) 462 463 # Go beyond boundaries. 464 small_buf = array.array('b', b' '*10) 465 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0, 466 test_string) 467 self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2, 468 test_string) 469 470 def test_unpack_with_buffer(self): 471 # SF bug 1563759: struct.unpack doesn't support buffer protocol objects 472 data1 = array.array('B', b'\x12\x34\x56\x78') 473 data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4 474 for data in [data1, data2]: 475 value, = struct.unpack('>I', data) 476 self.assertEqual(value, 0x12345678) 477 478 def test_bool(self): 479 class ExplodingBool(object): 480 def __bool__(self): 481 raise OSError 482 for prefix in tuple("<>!=")+('',): 483 false = (), [], [], '', 0 484 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2 485 486 falseFormat = prefix + '?' * len(false) 487 packedFalse = struct.pack(falseFormat, *false) 488 unpackedFalse = struct.unpack(falseFormat, packedFalse) 489 490 trueFormat = prefix + '?' * len(true) 491 packedTrue = struct.pack(trueFormat, *true) 492 unpackedTrue = struct.unpack(trueFormat, packedTrue) 493 494 self.assertEqual(len(true), len(unpackedTrue)) 495 self.assertEqual(len(false), len(unpackedFalse)) 496 497 for t in unpackedFalse: 498 self.assertFalse(t) 499 for t in unpackedTrue: 500 self.assertTrue(t) 501 502 packed = struct.pack(prefix+'?', 1) 503 504 self.assertEqual(len(packed), struct.calcsize(prefix+'?')) 505 506 if len(packed) != 1: 507 self.assertFalse(prefix, msg='encoded bool is not one byte: %r' 508 %packed) 509 510 try: 511 struct.pack(prefix + '?', ExplodingBool()) 512 except OSError: 513 pass 514 else: 515 self.fail("Expected OSError: struct.pack(%r, " 516 "ExplodingBool())" % (prefix + '?')) 517 518 for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: 519 self.assertTrue(struct.unpack('>?', c)[0]) 520 521 def test_count_overflow(self): 522 hugecount = '{}b'.format(sys.maxsize+1) 523 self.assertRaises(struct.error, struct.calcsize, hugecount) 524 525 hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2) 526 self.assertRaises(struct.error, struct.calcsize, hugecount2) 527 528 def test_trailing_counter(self): 529 store = array.array('b', b' '*100) 530 531 # format lists containing only count spec should result in an error 532 self.assertRaises(struct.error, struct.pack, '12345') 533 self.assertRaises(struct.error, struct.unpack, '12345', b'') 534 self.assertRaises(struct.error, struct.pack_into, '12345', store, 0) 535 self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0) 536 537 # Format lists with trailing count spec should result in an error 538 self.assertRaises(struct.error, struct.pack, 'c12345', 'x') 539 self.assertRaises(struct.error, struct.unpack, 'c12345', b'x') 540 self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0, 541 'x') 542 self.assertRaises(struct.error, struct.unpack_from, 'c12345', store, 543 0) 544 545 # Mixed format tests 546 self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs') 547 self.assertRaises(struct.error, struct.unpack, '14s42', 548 b'spam and eggs') 549 self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0, 550 'spam and eggs') 551 self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0) 552 553 def test_Struct_reinitialization(self): 554 # Issue 9422: there was a memory leak when reinitializing a 555 # Struct instance. This test can be used to detect the leak 556 # when running with regrtest -L. 557 s = struct.Struct('i') 558 s.__init__('ii') 559 560 def check_sizeof(self, format_str, number_of_codes): 561 # The size of 'PyStructObject' 562 totalsize = support.calcobjsize('2n3P') 563 # The size taken up by the 'formatcode' dynamic array 564 totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1) 565 support.check_sizeof(self, struct.Struct(format_str), totalsize) 566 567 @support.cpython_only 568 def test__sizeof__(self): 569 for code in integer_codes: 570 self.check_sizeof(code, 1) 571 self.check_sizeof('BHILfdspP', 9) 572 self.check_sizeof('B' * 1234, 1234) 573 self.check_sizeof('fd', 2) 574 self.check_sizeof('xxxxxxxxxxxxxx', 0) 575 self.check_sizeof('100H', 1) 576 self.check_sizeof('187s', 1) 577 self.check_sizeof('20p', 1) 578 self.check_sizeof('0s', 1) 579 self.check_sizeof('0c', 0) 580 581 def test_boundary_error_message(self): 582 regex1 = ( 583 r'pack_into requires a buffer of at least 6 ' 584 r'bytes for packing 1 bytes at offset 5 ' 585 r'\(actual buffer size is 1\)' 586 ) 587 with self.assertRaisesRegex(struct.error, regex1): 588 struct.pack_into('b', bytearray(1), 5, 1) 589 590 regex2 = ( 591 r'unpack_from requires a buffer of at least 6 ' 592 r'bytes for unpacking 1 bytes at offset 5 ' 593 r'\(actual buffer size is 1\)' 594 ) 595 with self.assertRaisesRegex(struct.error, regex2): 596 struct.unpack_from('b', bytearray(1), 5) 597 598 def test_boundary_error_message_with_negative_offset(self): 599 byte_list = bytearray(10) 600 with self.assertRaisesRegex( 601 struct.error, 602 r'no space to pack 4 bytes at offset -2'): 603 struct.pack_into('<I', byte_list, -2, 123) 604 605 with self.assertRaisesRegex( 606 struct.error, 607 'offset -11 out of range for 10-byte buffer'): 608 struct.pack_into('<B', byte_list, -11, 123) 609 610 with self.assertRaisesRegex( 611 struct.error, 612 r'not enough data to unpack 4 bytes at offset -2'): 613 struct.unpack_from('<I', byte_list, -2) 614 615 with self.assertRaisesRegex( 616 struct.error, 617 "offset -11 out of range for 10-byte buffer"): 618 struct.unpack_from('<B', byte_list, -11) 619 620 def test_boundary_error_message_with_large_offset(self): 621 # Test overflows cause by large offset and value size (issue 30245) 622 regex1 = ( 623 r'pack_into requires a buffer of at least ' + str(sys.maxsize + 4) + 624 r' bytes for packing 4 bytes at offset ' + str(sys.maxsize) + 625 r' \(actual buffer size is 10\)' 626 ) 627 with self.assertRaisesRegex(struct.error, regex1): 628 struct.pack_into('<I', bytearray(10), sys.maxsize, 1) 629 630 regex2 = ( 631 r'unpack_from requires a buffer of at least ' + str(sys.maxsize + 4) + 632 r' bytes for unpacking 4 bytes at offset ' + str(sys.maxsize) + 633 r' \(actual buffer size is 10\)' 634 ) 635 with self.assertRaisesRegex(struct.error, regex2): 636 struct.unpack_from('<I', bytearray(10), sys.maxsize) 637 638 def test_issue29802(self): 639 # When the second argument of struct.unpack() was of wrong type 640 # the Struct object was decrefed twice and the reference to 641 # deallocated object was left in a cache. 642 with self.assertRaises(TypeError): 643 struct.unpack('b', 0) 644 # Shouldn't crash. 645 self.assertEqual(struct.unpack('b', b'a'), (b'a'[0],)) 646 647 def test_format_attr(self): 648 s = struct.Struct('=i2H') 649 self.assertEqual(s.format, '=i2H') 650 651 # use a bytes string 652 s2 = struct.Struct(s.format.encode()) 653 self.assertEqual(s2.format, s.format) 654 655 def test_issue35714(self): 656 # Embedded null characters should not be allowed in format strings. 657 for s in '\0', '2\0i', b'\0': 658 with self.assertRaisesRegex(struct.error, 659 'embedded null character'): 660 struct.calcsize(s) 661 662 663class UnpackIteratorTest(unittest.TestCase): 664 """ 665 Tests for iterative unpacking (struct.Struct.iter_unpack). 666 """ 667 668 def test_construct(self): 669 def _check_iterator(it): 670 self.assertIsInstance(it, abc.Iterator) 671 self.assertIsInstance(it, abc.Iterable) 672 s = struct.Struct('>ibcp') 673 it = s.iter_unpack(b"") 674 _check_iterator(it) 675 it = s.iter_unpack(b"1234567") 676 _check_iterator(it) 677 # Wrong bytes length 678 with self.assertRaises(struct.error): 679 s.iter_unpack(b"123456") 680 with self.assertRaises(struct.error): 681 s.iter_unpack(b"12345678") 682 # Zero-length struct 683 s = struct.Struct('>') 684 with self.assertRaises(struct.error): 685 s.iter_unpack(b"") 686 with self.assertRaises(struct.error): 687 s.iter_unpack(b"12") 688 689 def test_iterate(self): 690 s = struct.Struct('>IB') 691 b = bytes(range(1, 16)) 692 it = s.iter_unpack(b) 693 self.assertEqual(next(it), (0x01020304, 5)) 694 self.assertEqual(next(it), (0x06070809, 10)) 695 self.assertEqual(next(it), (0x0b0c0d0e, 15)) 696 self.assertRaises(StopIteration, next, it) 697 self.assertRaises(StopIteration, next, it) 698 699 def test_arbitrary_buffer(self): 700 s = struct.Struct('>IB') 701 b = bytes(range(1, 11)) 702 it = s.iter_unpack(memoryview(b)) 703 self.assertEqual(next(it), (0x01020304, 5)) 704 self.assertEqual(next(it), (0x06070809, 10)) 705 self.assertRaises(StopIteration, next, it) 706 self.assertRaises(StopIteration, next, it) 707 708 def test_length_hint(self): 709 lh = operator.length_hint 710 s = struct.Struct('>IB') 711 b = bytes(range(1, 16)) 712 it = s.iter_unpack(b) 713 self.assertEqual(lh(it), 3) 714 next(it) 715 self.assertEqual(lh(it), 2) 716 next(it) 717 self.assertEqual(lh(it), 1) 718 next(it) 719 self.assertEqual(lh(it), 0) 720 self.assertRaises(StopIteration, next, it) 721 self.assertEqual(lh(it), 0) 722 723 def test_module_func(self): 724 # Sanity check for the global struct.iter_unpack() 725 it = struct.iter_unpack('>IB', bytes(range(1, 11))) 726 self.assertEqual(next(it), (0x01020304, 5)) 727 self.assertEqual(next(it), (0x06070809, 10)) 728 self.assertRaises(StopIteration, next, it) 729 self.assertRaises(StopIteration, next, it) 730 731 def test_half_float(self): 732 # Little-endian examples from: 733 # http://en.wikipedia.org/wiki/Half_precision_floating-point_format 734 format_bits_float__cleanRoundtrip_list = [ 735 (b'\x00\x3c', 1.0), 736 (b'\x00\xc0', -2.0), 737 (b'\xff\x7b', 65504.0), # (max half precision) 738 (b'\x00\x04', 2**-14), # ~= 6.10352 * 10**-5 (min pos normal) 739 (b'\x01\x00', 2**-24), # ~= 5.96046 * 10**-8 (min pos subnormal) 740 (b'\x00\x00', 0.0), 741 (b'\x00\x80', -0.0), 742 (b'\x00\x7c', float('+inf')), 743 (b'\x00\xfc', float('-inf')), 744 (b'\x55\x35', 0.333251953125), # ~= 1/3 745 ] 746 747 for le_bits, f in format_bits_float__cleanRoundtrip_list: 748 be_bits = le_bits[::-1] 749 self.assertEqual(f, struct.unpack('<e', le_bits)[0]) 750 self.assertEqual(le_bits, struct.pack('<e', f)) 751 self.assertEqual(f, struct.unpack('>e', be_bits)[0]) 752 self.assertEqual(be_bits, struct.pack('>e', f)) 753 if sys.byteorder == 'little': 754 self.assertEqual(f, struct.unpack('e', le_bits)[0]) 755 self.assertEqual(le_bits, struct.pack('e', f)) 756 else: 757 self.assertEqual(f, struct.unpack('e', be_bits)[0]) 758 self.assertEqual(be_bits, struct.pack('e', f)) 759 760 # Check for NaN handling: 761 format_bits__nan_list = [ 762 ('<e', b'\x01\xfc'), 763 ('<e', b'\x00\xfe'), 764 ('<e', b'\xff\xff'), 765 ('<e', b'\x01\x7c'), 766 ('<e', b'\x00\x7e'), 767 ('<e', b'\xff\x7f'), 768 ] 769 770 for formatcode, bits in format_bits__nan_list: 771 self.assertTrue(math.isnan(struct.unpack('<e', bits)[0])) 772 self.assertTrue(math.isnan(struct.unpack('>e', bits[::-1])[0])) 773 774 # Check that packing produces a bit pattern representing a quiet NaN: 775 # all exponent bits and the msb of the fraction should all be 1. 776 packed = struct.pack('<e', math.nan) 777 self.assertEqual(packed[1] & 0x7e, 0x7e) 778 packed = struct.pack('<e', -math.nan) 779 self.assertEqual(packed[1] & 0x7e, 0x7e) 780 781 # Checks for round-to-even behavior 782 format_bits_float__rounding_list = [ 783 ('>e', b'\x00\x01', 2.0**-25 + 2.0**-35), # Rounds to minimum subnormal 784 ('>e', b'\x00\x00', 2.0**-25), # Underflows to zero (nearest even mode) 785 ('>e', b'\x00\x00', 2.0**-26), # Underflows to zero 786 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-24), # Largest subnormal. 787 ('>e', b'\x03\xff', 2.0**-14 - 2.0**-25 - 2.0**-65), 788 ('>e', b'\x04\x00', 2.0**-14 - 2.0**-25), 789 ('>e', b'\x04\x00', 2.0**-14), # Smallest normal. 790 ('>e', b'\x3c\x01', 1.0+2.0**-11 + 2.0**-16), # rounds to 1.0+2**(-10) 791 ('>e', b'\x3c\x00', 1.0+2.0**-11), # rounds to 1.0 (nearest even mode) 792 ('>e', b'\x3c\x00', 1.0+2.0**-12), # rounds to 1.0 793 ('>e', b'\x7b\xff', 65504), # largest normal 794 ('>e', b'\x7b\xff', 65519), # rounds to 65504 795 ('>e', b'\x80\x01', -2.0**-25 - 2.0**-35), # Rounds to minimum subnormal 796 ('>e', b'\x80\x00', -2.0**-25), # Underflows to zero (nearest even mode) 797 ('>e', b'\x80\x00', -2.0**-26), # Underflows to zero 798 ('>e', b'\xbc\x01', -1.0-2.0**-11 - 2.0**-16), # rounds to 1.0+2**(-10) 799 ('>e', b'\xbc\x00', -1.0-2.0**-11), # rounds to 1.0 (nearest even mode) 800 ('>e', b'\xbc\x00', -1.0-2.0**-12), # rounds to 1.0 801 ('>e', b'\xfb\xff', -65519), # rounds to 65504 802 ] 803 804 for formatcode, bits, f in format_bits_float__rounding_list: 805 self.assertEqual(bits, struct.pack(formatcode, f)) 806 807 # This overflows, and so raises an error 808 format_bits_float__roundingError_list = [ 809 # Values that round to infinity. 810 ('>e', 65520.0), 811 ('>e', 65536.0), 812 ('>e', 1e300), 813 ('>e', -65520.0), 814 ('>e', -65536.0), 815 ('>e', -1e300), 816 ('<e', 65520.0), 817 ('<e', 65536.0), 818 ('<e', 1e300), 819 ('<e', -65520.0), 820 ('<e', -65536.0), 821 ('<e', -1e300), 822 ] 823 824 for formatcode, f in format_bits_float__roundingError_list: 825 self.assertRaises(OverflowError, struct.pack, formatcode, f) 826 827 # Double rounding 828 format_bits_float__doubleRoundingError_list = [ 829 ('>e', b'\x67\xff', 0x1ffdffffff * 2**-26), # should be 2047, if double-rounded 64>32>16, becomes 2048 830 ] 831 832 for formatcode, bits, f in format_bits_float__doubleRoundingError_list: 833 self.assertEqual(bits, struct.pack(formatcode, f)) 834 835 836if __name__ == '__main__': 837 unittest.main() 838