# New Ticket Created by  Nick Glencross 
# Please include the string:  [perl #36052]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=36052 >


I've finally got access to a big endian platform, and have made the 
changes required to get correct checksums from the MD5 library.

All (MD5) tests pass, and are no longer skip on certain platforms.

[All being well, I should have a version can can do incremental hashes RSN!]

Regards,

Nick

p.s. A fair number of libraries have renamed .imc to .pir. I'd be 
grateful if someone would do the same for me. It should just be a case 
of 'svn rename' on the library file, a corresponding change in the 
MANIFEST, and a replacement of .imc with .pir (or should .pbc be 
better?) in t/library/md5.t
Index: runtime/parrot/library/Digest/MD5.imc
===================================================================
--- runtime/parrot/library/Digest/MD5.imc       (revision 8230)
+++ runtime/parrot/library/Digest/MD5.imc       (working copy)
@@ -6,7 +6,7 @@
 
 =head1 NAME
 
-MD5.imc - calculate MD5 checksums
+MD5.imc - calculates MD5 checksums
 
 =head1 SYNOPSIS
 
@@ -41,55 +41,25 @@
 
 =head1 BUGS
 
-This section provides a list of bugs.
+Still has some limitations on input buffer size, largely due to memory
+consumption which should be resolved soon.
 
-=over 4
-
-=item *
-
-By all accounts, doesn't seem to work on big endian systems, but I
-don't have access to investigate.
-
-=item *
-
-There is some scope to optimise things a little further, perhaps removing
-some of the 'and's (for 64-bit) which may be superflouous.
-
-=back
-
 =cut
 
 ###########################################################################
 # Export function entries to globals
 
 .sub onload @LOAD
-    .local pmc endian
-    endian = new Integer
-    endian = 0
 
-    $P0 = _config()
-
-    $I0 = $P0["bigendian"]
-    unless $I0 goto is_little_endian
-    endian = 1
-    printerr "This appears to be a big endian processor: "
-    printerr "Please verify the MD5 checksum\n"
-
-is_little_endian:
-
-    store_global "Digest", "_md5_swap_endian", endian
-
     .local pmc f
     f = find_global "Digest", "_md5sum"
-    global "_md5sum" = f
+    global "_md5sum"    = f
     f = find_global "Digest", "_md5_hex"
-    global "_md5_hex" = f
+    global "_md5_hex"   = f
     f = find_global "Digest", "_md5_print"
     global "_md5_print" = f
 .end
 
-.include "library/config.imc"
-
 ###########################################################################
 # Main backend entry point
 
@@ -98,85 +68,73 @@
 .sub _md5sum
     .param string str
 
-    .local pmc buffer, context
-    buffer = new FixedIntegerArray
-
+    .local pmc context
     context = new FixedIntegerArray
     context = 4
 
-    $P0 = find_global "Digest", "_md5_swap_endian"
-    $I0 = $P0
-    _md5_create_buffer (str, buffer, $I0)
+    .local pmc buffer
+    buffer = _md5_create_buffer (str)
 
     _md5_init (context)
     _md5_process_buffer (context, buffer)
 
-    .return(context)
-
+    .return (context)
 .end
 
 
 ###########################################################################
 # Low-level macros used in MD5
 
-# A parrot rol instruction might be good (as it can often be JIT'd)
-.macro rol (x,n,  out)
-    #.out  = .x << .n
-    #tmp2  = 32 - .n
-    #tmp2  = .x >>> tmp2
-    #.out |= tmp2
-    rot .out, .x, .n, 32
-.endm
-
 .macro FF (b,c,d)
-    tmp1 = .c ~ .d
-    tmp1 &= .b
-    tmp1 ~= .d
+    tmp  = .c ~ .d
+    tmp &= .b
+    tmp ~= .d
 .endm
 
 .macro FH (b,c,d)
-    tmp1 = .b   ~ .c
-    tmp1 ~= .d
+    tmp  = .b ~ .c
+    tmp ~= .d
 .endm
 
 .macro FI (b,c,d)
-    tmp1 = ~.d
-    tmp1 |= .b
-    tmp1 ~= .c
+    tmp  = ~.d
+    tmp |= .b
+    tmp ~= .c
 .endm
 
 ###########################################################################
 # Higher level MD5 operations
 
 .macro common (a, b, k, s, T)
-    .a += tmp1
+    .a += tmp
     .a += .T
-    tmp2 = .k + idx
-    tmp1 = buffer[tmp2]
-    .a += tmp1
+    tmp = .k + idx
+    tmp = buffer[tmp]
+    .a += tmp
     .a &= 0xffffffff
-    .rol (.a, .s, tmp1)
-    .a  = .b + tmp1
+    tmp = rot .a, .s, 32
+    .a  = .b + tmp
     .a &= 0xffffffff
 .endm
 
+
 .macro OP1 (aa,bb,cc,dd, kk, ss, TT)
-    .FF (.bb,.cc,.dd)
+    .FF     (.bb,.cc,.dd)
     .common (.aa, .bb, .kk, .ss, .TT)
 .endm
 
 .macro OP2 (aa,bb,cc,dd, kk, ss, TT)
-    .FF (.dd,.bb,.cc)
+    .FF     (.dd,.bb,.cc)
     .common (.aa, .bb, .kk, .ss, .TT)
 .endm
 
 .macro OP3 (aa,bb,cc,dd, kk, ss, TT)
-    .FH (.bb,.cc,.dd)
+    .FH     (.bb,.cc,.dd)
     .common (.aa, .bb, .kk, .ss, .TT)
 .endm
 
 .macro OP4 (aa,bb,cc,dd, kk, ss, TT)
-    .FI (.bb,.cc,.dd)
+    .FI     (.bb,.cc,.dd)
     .common (.aa, .bb, .kk, .ss, .TT)
 .endm
 
@@ -197,11 +155,10 @@
 
      $I10 |= $I11
      $I10 |= $I12
-     .w   =  $I10 | $I13
+     $I10 |= $I13
 
      # For 64-bit architectures
-     .w &= 0xffffffff
-
+     .w = $I10 & 0xffffffff
 .endm
 
 ###########################################################################
@@ -224,9 +181,10 @@
 
 .sub _md5_create_buffer
     .param string str
-    .param pmc    buffer
-    .param int    endian
 
+    .local pmc buffer
+    buffer = new FixedIntegerArray
+
     .local int counter
     .local int subcounter
     .local int slow_counter
@@ -239,7 +197,7 @@
 
      # Work out how many words to allocate
      .local int words
-     words = len + 8
+     words  = len + 8
      words |= 63
      inc words
      words /= 4
@@ -251,11 +209,11 @@
      subcounter   = 0
      slow_counter = 0
 
-md5_create_buffer_loop:
+create_buffer_loop:
 
      $I5 = counter + subcounter
 
-     if $I5 > len goto md5_create_buffer_break
+     if $I5 > len goto create_buffer_break
 
      # MD5 pad character, which goes last
      $I4 = 0x80
@@ -266,37 +224,32 @@
 string_char:
 
      word <<= 8
-     word |= $I4
+     word  |= $I4
 
      inc subcounter
-     if subcounter != 4 goto md5_create_buffer_loop
+     if subcounter != 4 goto create_buffer_loop
 
-     if endian goto endian_ok1
      .swap (word)
-endian_ok1:
 
      buffer[slow_counter] = word
 
-     word         = 0
-     counter      +=  4
-     subcounter   = 0
+     word       = 0
+     counter   += 4
+     subcounter = 0
      inc slow_counter
 
-     goto md5_create_buffer_loop
+     goto create_buffer_loop
 
-md5_create_buffer_break:
+create_buffer_break:
 
      # Check for a partial word
 
      if subcounter == 0 goto complete
      subcounter = 4 - subcounter
-     .local int shift
-     shift = 8*subcounter
-     word <<= shift
+     $I0    = 8*subcounter
+     word <<= $I0
 
-     if endian goto endian_ok2
      .swap (word)
-endian_ok2:
 
      buffer[slow_counter] = word
 
@@ -304,14 +257,16 @@
 
      # The number of bits in the string go into the last two words
 
-     $I1 = len >>> 29
+     $I0 = len >>> 29
      dec words
-     buffer[words] = $I1
+     buffer[words] = $I0
 
      $I0 = len << 3
      dec words
      buffer[words] = $I0
 
+     .return (buffer)
+
 .end
 
 ###########################################################################
@@ -323,7 +278,7 @@
     .local int A, B, C, D
     .local int A_save, B_save, C_save, D_save
 
-    .local int tmp1, tmp2, idx, len
+    .local int tmp, idx, len
 
     idx = 0
     len = elements buffer
@@ -333,7 +288,7 @@
     C = context[2]
     D = context[3]
 
-md5_loop:
+loop:
 
     A_save = A
     B_save = B
@@ -419,7 +374,7 @@
 
     idx += 16
 
-    if idx < len goto md5_loop
+    if idx < len goto loop
 
     context[0] = A
     context[1] = B
@@ -446,8 +401,8 @@
     $P0[2] = C
     $P0[3] = D
 
-    sprintf $S0, "%08lx%08lx%08lx%08lx", $P0
-    .return($S0)
+    $S0 = sprintf "%08lx%08lx%08lx%08lx", $P0
+    .return ($S0)
 .end
 
 ###########################################################################
@@ -464,80 +419,22 @@
     C = context[2]
     D = context[3]
 
-    $P0 = find_global "Digest", "_md5_swap_endian"
-    if $P0 goto dont_swap
-
     .swap (A)
     .swap (B)
     .swap (C)
     .swap (D)
 
-dont_swap:
-
     $S0 = _md5_format_vals (A,B,C,D)
-    .return($S0)
+    .return ($S0)
 .end
 
-# Convenience subroutine to print the MD5 string
+# Convenience subroutine to print the MD5 hash for a string
 
 .sub _md5_print
     .param pmc context
 
     $S0 = _md5_hex (context)
     print $S0
-.end
 
-###########################################################################
-
-# For debugging
-
-.sub _md5_print_buffer
-    .param pmc buffer
-    .param int word_size
-
-    .local int size
-
-    size = buffer
-
-    .local int counter
-    .local int value
-
-    counter = 0
-
-print_buffer_loop:
-    if counter >= size goto print_buffer_done
-    value = buffer[counter]
-    $S0 = _md5_number_as_hex (value, word_size)
-    print $S0
-    print " | "
-    counter = counter + 1
-    goto print_buffer_loop
-
-print_buffer_done:
-
-    print "\n"
-
+    .return ($S0)
 .end
-
-###########################################################################
-
-# Also for debugging
-
-.sub _md5_number_as_hex
-    .param int number
-    .param int word_size
-
-    $P0 = new FixedIntegerArray
-    $P0 = 1
-    $P0[0] = number
-
-    $S1 = "%0"
-    $S0 = word_size
-    concat $S1, $S0
-    concat $S1, "lx"
-
-    sprintf $S0, $S1, $P0
-
-    .return($S0)
-
-.end
Index: t/library/md5.t
===================================================================
--- t/library/md5.t     (revision 8230)
+++ t/library/md5.t     (working copy)
@@ -12,20 +12,9 @@
 use strict;
 use Parrot::Test tests => 6;
 
-use Parrot::Config;
 
-my $bigendian = $PConfig{bigendian};
-
-SKIP: {
-
-if ($bigendian)
-{
-    skip('MD5 only known to work on little endian bit processors', 6)
-}
-
-
 ##############################
-# Stress IMCC and parrot using MD5 library
+# Stress parrot using MD5 library
 
 pir_output_is(<<'CODE', <<'OUT', "Miscellaneous words");
 .sub _main
@@ -808,5 +797,3 @@
 8408bf5f0144309374e66278bec290b2
 982e0fde28cd2f62ef8db2d8dfd0f0d7
 OUT
-
-}

Reply via email to