The base64-decoder doesn't work on 64-bit big-endian architectures:
[mmh] / uip / mhparse.c
index 8035113..91cc411 100644 (file)
@@ -1737,10 +1737,15 @@ openBase64 (CT ct, char **file)
     CE ce;
     MD5_CTX mdContext;
 
+    /* the decoder works on the least-significant three bytes of the bits integer,
+       but their position in memory depend on both endian-ness and size of 
+       long int... for little-endian architectures the size is irrelevant, for
+       big-endian archs it's crucial... ideally we'd adopt posix and use a64l instead
+       of this mess. */
     b  = (unsigned char *) &bits;
-    b1 = &b[endian > 0 ? 1 : 2];
-    b2 = &b[endian > 0 ? 2 : 1];
-    b3 = &b[endian > 0 ? 3 : 0];
+    b1 = &b[endian > 0 ? sizeof(bits)==8?5:1 : 2];
+    b2 = &b[endian > 0 ? sizeof(bits)==8?6:2 : 1];
+    b3 = &b[endian > 0 ? sizeof(bits)==8?7:3 : 0];
 
     ce = ct->c_cefile;
     if (ce->ce_fp) {
@@ -1776,8 +1781,8 @@ openBase64 (CT ct, char **file)
     }
     if (cp != NULL && *cp != '\0') {
         if (ce->ce_unlink) {
-            // Temporary file already exists, so we rename to
-            // version with extension.
+            /* Temporary file already exists, so we rename to
+               version with extension. */
             char *file_org = strdup(ce->ce_file);
             ce->ce_file = add (cp, ce->ce_file);
             if (rename(file_org, ce->ce_file)) {
@@ -2008,8 +2013,8 @@ openQuoted (CT ct, char **file)
     }
     if (cp != NULL && *cp != '\0') {
         if (ce->ce_unlink) {
-            // Temporary file already exists, so we rename to
-            // version with extension.
+            /* Temporary file already exists, so we rename to
+               version with extension. */
             char *file_org = strdup(ce->ce_file);
             ce->ce_file = add (cp, ce->ce_file);
             if (rename(file_org, ce->ce_file)) {
@@ -2232,8 +2237,8 @@ open7Bit (CT ct, char **file)
     }
     if (cp != NULL && *cp != '\0') {
         if (ce->ce_unlink) {
-            // Temporary file already exists, so we rename to
-            // version with extension.
+            /* Temporary file already exists, so we rename to
+               version with extension. */
             char *file_org = strdup(ce->ce_file);
             ce->ce_file = add (cp, ce->ce_file);
             if (rename(file_org, ce->ce_file)) {
@@ -2825,10 +2830,16 @@ readDigest (CT ct, char *cp)
     unsigned char *dp, value, *ep;
     unsigned char *b, *b1, *b2, *b3;
 
-    b  = (unsigned char *) &bits,
-    b1 = &b[endian > 0 ? 1 : 2],
-    b2 = &b[endian > 0 ? 2 : 1],
-    b3 = &b[endian > 0 ? 3 : 0];
+    /* the decoder works on the least-significant three bytes of the bits integer,
+       but their position in memory depend on both endian-ness and size of 
+       long int... for little-endian architectures the size is irrelevant, for
+       big-endian archs it's crucial... ideally we'd adopt posix and use a64l instead
+       of this mess. */
+    b  = (unsigned char *) &bits;
+    b1 = &b[endian > 0 ? sizeof(bits)==8?5:1 : 2];
+    b2 = &b[endian > 0 ? sizeof(bits)==8?6:2 : 1];
+    b3 = &b[endian > 0 ? sizeof(bits)==8?7:3 : 0];
+
     bitno = 18;
     bits = 0L;
     skip = 0;