[diffoscope] 01/02: comparators/haskell: Properly extract version from interface files

Mattia Rizzolo mattia at debian.org
Tue Jan 17 19:51:56 CET 2017


This is an automated email from the git hooks/post-receive script.

mattia pushed a commit to branch master
in repository diffoscope.

commit a5839153f3aeb62be625e09e38696456e3d8578e
Author: James Clarke <jrtc27 at debian.org>
Date:   Tue Jan 17 16:44:24 2017 +0000

    comparators/haskell: Properly extract version from interface files
    
    What the code did before was just totally wrong, and worked only by
    chance (and only on little endian systems), see below for an explenation.
    
    This also fixes the test suite when run on big endian systems.
    
    What it was being treated as:
    
    debian:git-src james% hexdump -C tests/data/test1.hi | head -n 10    [master *]
    00000000  01 fa ce 64 00 00 00 00  00 00 00 00 04 00 00 00  |...d............|
              ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~
               HI_MAGIC    zero padding (used to   Skipped over
                             be a field here)
    
    00000010  37 00 00 00 31 00 00 00  30 00 00 00 33 00 00 00  |7...1...0...3...|
              ~~~~~~~~~~~ ~~~~~~~~~~~  ~~~~~~~~~~~ ~~
                int('7')    int('1')     int('0')  ^^ byte('3')
    
    What it actually is:
    
    debian:git-src james% hexdump -C tests/data/test1.hi | head -n 10    [master *]
    00000000  01 fa ce 64 00 00 00 00  00 00 00 00 04 00 00 00  |...d............|
              ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~~ ~~~~~~~~~~
               HI_MAGIC    zero padding (used to  [0]  int('7')
                             be a field here)
    
               [0] version string length
    
    00000010  37 00 00 00 31 00 00 00  30 00 00 00 33 00 00 00  |7...1...0...3...|
            ~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~
                  int('1')     int('0')    int('3')
    
    Signed-off-by: Mattia Rizzolo <mattia at debian.org>
---
 diffoscope/comparators/haskell.py | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/diffoscope/comparators/haskell.py b/diffoscope/comparators/haskell.py
index 6a1ac6c..716c4a4 100644
--- a/diffoscope/comparators/haskell.py
+++ b/diffoscope/comparators/haskell.py
@@ -39,8 +39,8 @@ class ShowIface(Command):
         return ['ghc', '--show-iface', self.path]
 
 
-HI_MAGIC_32 = struct.pack('!I', 0x1face)
-HI_MAGIC_64 = struct.pack('!I', 0x1face64)
+HI_MAGIC_32 = struct.pack('>I', 0x1face)
+HI_MAGIC_64 = struct.pack('>I', 0x1face64)
 if platform.architecture()[0] == '32bit':
     HI_MAGIC = HI_MAGIC_32
 else:
@@ -77,11 +77,18 @@ class HiFile(File):
                 fp.read(4)
             elif buf == HI_MAGIC_64:
                 fp.read(8)
-            # skip way_descr
-            fp.read(4)
-            # now read version
-            buf = fp.read(16)
-            version_found = ''.join(map(chr, struct.unpack_from('=3IB', buf)))
+            # Read version, which is [Char]
+            buf = fp.read(1)
+            # Small list optimisation - anything less than 0xff has its length
+            # in a single byte; everything else is 0xff followed by the 32-bit
+            # length (big-endian).
+            if buf[0] == 0xff:
+                buf = fp.read(4)
+                length = struct.unpack('>I', buf)[0]
+            else:
+                length = buf[0]
+            # Now read characters; each is 32-bit big-endian.
+            version_found = ''.join([chr(struct.unpack('>I', fp.read(4))[0]) for _ in range(length)])
             if version_found != HiFile.hi_version:
                 logger.debug('Haskell version mismatch. Found %s instead of %s.',
                              version_found, HiFile.hi_version)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list