timknip / pyswf

A Python library to read and write SWF files
https://github.com/timknip/pyswf/wiki
MIT License
157 stars 65 forks source link

error parsing DEFINEFONT3 Tag #18

Open zhzhzoo opened 10 years ago

zhzhzoo commented 10 years ago

I'm parsing some swf when I encountered this error. The file does't seem to conform to the swf file spec, however, Adobe Flash Player can play it.

Traceback (most recent call last):
  File "c.py", line 4, in <module>
    swf = SWF(f)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/movie.py", line 87, in __init__
    self.parse(self._data)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/movie.py", line 143, in parse
    self.parse_tags(data)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/tag.py", line 112, in parse_tags
    tag = self.parse_tag(data)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/tag.py", line 131, in parse_tag
    tag.parse(data, raw_tag.header.content_length, tag.version)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/tag.py", line 1314, in parse
    self.glyphShapeTable.append(data.readSHAPE(self.unitDivisor))
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/stream.py", line 200, in readSHAPE
    return SWFShape(self, 1, unit_divisor)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 50, in __init__
    self.parse(data, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 57, in parse
    self.read_shape_records(data, fillbits, linebits, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 93, in read_shape_records
    style_change_record = data.readSTYLECHANGERECORD(states, fill_bits, line_bits, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/stream.py", line 216, in readSTYLECHANGERECORD
    return SWFShapeRecordStyleChange(self, states, fill_bits, line_bits, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 607, in __init__
    super(SWFShapeRecordStyleChange, self).__init__(data, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 522, in __init__
    self.parse(data, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 622, in parse
    self.fill_styles.append(data.readFILLSTYLE(level))
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/stream.py", line 220, in readFILLSTYLE
    return SWFFillStyle(self, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 760, in __init__
    self.parse(data, level)
  File "/Library/Python/2.7/site-packages/pyswf-1.4-py2.7.egg/swf/data.py", line 773, in parse
    raise Exception("Unknown fill style type: 0x%x" % self.type, level)
Exception: ('Unknown fill style type: 0xf', 1)

Here is the file: https://www.dropbox.com/s/n02lbplm77exmhp/page003.swf

zhzhzoo commented 10 years ago

Solved. Adobe Flash Player reads the offsetTable first, then look up the glyphShapeTable for a given character when encountered. So some SWF may have glyphShapeTable not immediately following codeTableOffset or vacancies between glyphShape entries, however, as the SWF provided correct offsetTable, it can be recognised by Adobe Flash Player.

demurgos commented 6 years ago

The dropbox link is no longer available. Could you provide the example again?

zhzhzoo commented 6 years ago

https://drive.google.com/file/d/1WSwud0Zx6xN8aijzatG8Sg2cFRsgmiXJ/view?usp=sharing

demurgos commented 6 years ago

I did not fully understand your explanations, but I tested it against my own parsers and it seem to work.

Here are the relevant functions, I hope it may help to fix it here:

I am effectively reading the offset table first and then using it to parse the glyphs.

(Your example also helped me find out that my implementation does not discard the terminating null-byte of the font name, thanks.)