Skip to content

Commit f1d9bc9

Browse files
committed
New version for skipPos, major fix to Python redundancy check
1 parent ae68084 commit f1d9bc9

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name='universalmutator',
8-
version='1.1.8',
8+
version='1.1.9',
99
description='Universal regexp-based mutation tool',
1010
long_description_content_type="text/markdown",
1111
long_description=open('README.md').read(),

universalmutator/python_handler.py

+26-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import sys
44
import py_compile
5+
import uuid
56

67

78
def buildCode(c):
@@ -28,19 +29,33 @@ def buildCode(c):
2829

2930

3031
def getPythonCode(fname):
31-
# Courtesy of Ned Batchelder, just get the code object from the .pyc file
32+
# from https://stackoverflow.com/questions/32562163/how-can-i-understand-a-pyc-file-content
33+
header_sizes = [
34+
# (size, first version this applies to)
35+
# pyc files were introduced in 0.9.2 way, way back in June 1991.
36+
(8, (0, 9, 2)), # 2 bytes magic number, \r\n, 4 bytes UNIX timestamp
37+
(12, (3, 6)), # added 4 bytes file size
38+
# bytes 4-8 are flags, meaning of 9-16 depends on what flags are set
39+
# bit 0 not set: 9-12 timestamp, 13-16 file size
40+
# bit 0 set: 9-16 file hash (SipHash-2-4, k0 = 4 bytes of the file, k1 = 0)
41+
(16, (3, 7)), # inserted 4 bytes bit flag field at 4-8
42+
# future version may add more bytes still, at which point we can extend
43+
# this table. It is correct for Python versions up to 3.9
44+
]
45+
header_size = next(s for s, v in reversed(header_sizes) if sys.version_info >= v)
46+
3247
with open(fname, "rb") as f:
33-
f.read(4)
34-
f.read(4)
35-
if sys.version_info >= (3, 3):
36-
f.read(4)
48+
metadata = f.read(header_size) # first header_size bytes are metadata
3749
try:
38-
code = marshal.load(f)
39-
except (EOFError, TypeError, ValueError):
40-
with open(fname, "rb") as fRetry:
41-
fRetry.read(16)
42-
code = marshal.load(fRetry)
43-
return buildCode(code)
50+
code = marshal.load(f) # rest is a marshalled code object
51+
except:
52+
print("WARNING: UNABLE TO MARSHAL CODE FROM PYC FILE!")
53+
return(uuid.uuid4())
54+
if ("code" not in str(type(code))):
55+
print("WARNING: INVALID CODE OBJECT READ FROM PYC FILE!")
56+
return(uuid.uuid4())
57+
b = buildCode(code)
58+
return b
4459

4560

4661
def handler(tmpMutantName, mutant, sourceFile, uniqueMutants):

universalmutator/static/python.rules

+2
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,5 @@ True ==> False
3939
'.+' ==> ''
4040

4141
@.* ==>
42+
43+
# ==> SKIP_MUTATING_REST

0 commit comments

Comments
 (0)