Skip to content

Commit ee9ac1c

Browse files
mattst88tonycoz
authored andcommitted
Digest-MD5: Consolidate byte-swapping paths
The code guarded by #ifndef U32_ALIGNMENT_REQUIRED attempts to optimize byte-swapping by doing unaligned loads, but accessing data through unaligned pointers is undefined behavior in C. Moreover, compilers are more than capable of recognizing these open-coded byte-swap patterns and emitting a bswap instruction, or an unaligned load instruction, or a combined load, etc. There's no need for multiple paths to attain the desired result. See https://rt.perl.org/Ticket/Display.html?id=133495
1 parent 4f89f09 commit ee9ac1c

File tree

3 files changed

+3
-157
lines changed

3 files changed

+3
-157
lines changed

cpan/Digest-MD5/MD5.xs

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,6 @@ static MAGIC *THX_sv_magicext(pTHX_ SV *sv, SV *obj, int type,
106106
* values. The following macros (and functions) allow us to convert
107107
* between native integers and such values.
108108
*/
109-
#undef BYTESWAP
110-
#ifndef U32_ALIGNMENT_REQUIRED
111-
#if BYTEORDER == 0x1234 /* 32-bit little endian */
112-
#define BYTESWAP(x) (x) /* no-op */
113-
114-
#elif BYTEORDER == 0x4321 /* 32-bit big endian */
115-
#define BYTESWAP(x) ((((x)&0xFF)<<24) \
116-
|(((x)>>24)&0xFF) \
117-
|(((x)&0x0000FF00)<<8) \
118-
|(((x)&0x00FF0000)>>8) )
119-
#endif
120-
#endif
121-
122-
#ifndef BYTESWAP
123109
static void u2s(U32 u, U8* s)
124110
{
125111
*s++ = (U8)(u & 0xFF);
@@ -132,7 +118,6 @@ static void u2s(U32 u, U8* s)
132118
((U32)(*(s+1)) << 8) | \
133119
((U32)(*(s+2)) << 16) | \
134120
((U32)(*(s+3)) << 24))
135-
#endif
136121

137122
/* This structure keeps the current state of algorithm.
138123
*/
@@ -279,29 +264,16 @@ MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
279264
U32 C = ctx->C;
280265
U32 D = ctx->D;
281266

282-
#ifndef U32_ALIGNMENT_REQUIRED
283-
const U32 *x = (U32*)buf; /* really just type casting */
284-
#endif
285-
286267
do {
287268
U32 a = A;
288269
U32 b = B;
289270
U32 c = C;
290271
U32 d = D;
291272

292-
#if BYTEORDER == 0x1234 && !defined(U32_ALIGNMENT_REQUIRED)
293-
const U32 *X = x;
294-
#define NEXTx (*x++)
295-
#else
296-
U32 X[16]; /* converted values, used in round 2-4 */
273+
U32 X[16]; /* little-endian values, used in round 2-4 */
297274
U32 *uptr = X;
298275
U32 tmp;
299-
#ifdef BYTESWAP
300-
#define NEXTx (tmp=*x++, *uptr++ = BYTESWAP(tmp))
301-
#else
302276
#define NEXTx (s2u(buf,tmp), buf += 4, *uptr++ = tmp)
303-
#endif
304-
#endif
305277

306278
#ifdef MD5_DEBUG
307279
if (buf == ctx->buffer)
@@ -313,7 +285,7 @@ MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
313285
int i;
314286
fprintf(stderr,"[");
315287
for (i = 0; i < 16; i++) {
316-
fprintf(stderr,"%x,", x[i]);
288+
fprintf(stderr,"%x,", x[i]); /* FIXME */
317289
}
318290
fprintf(stderr,"]\n");
319291
}
@@ -468,30 +440,18 @@ MD5Final(U8* digest, MD5_CTX *ctx)
468440

469441
bits_low = ctx->bytes_low << 3;
470442
bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29);
471-
#ifdef BYTESWAP
472-
*(U32*)(ctx->buffer + fill) = BYTESWAP(bits_low); fill += 4;
473-
*(U32*)(ctx->buffer + fill) = BYTESWAP(bits_high); fill += 4;
474-
#else
475443
u2s(bits_low, ctx->buffer + fill); fill += 4;
476444
u2s(bits_high, ctx->buffer + fill); fill += 4;
477-
#endif
478445

479446
MD5Transform(ctx, ctx->buffer, fill >> 6);
480447
#ifdef MD5_DEBUG
481448
fprintf(stderr," Result: %s\n", ctx_dump(ctx));
482449
#endif
483450

484-
#ifdef BYTESWAP
485-
*(U32*)digest = BYTESWAP(ctx->A); digest += 4;
486-
*(U32*)digest = BYTESWAP(ctx->B); digest += 4;
487-
*(U32*)digest = BYTESWAP(ctx->C); digest += 4;
488-
*(U32*)digest = BYTESWAP(ctx->D);
489-
#else
490451
u2s(ctx->A, digest);
491452
u2s(ctx->B, digest+4);
492453
u2s(ctx->C, digest+8);
493454
u2s(ctx->D, digest+12);
494-
#endif
495455
}
496456

497457
#ifndef INT2PTR

cpan/Digest-MD5/Makefile.PL

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use Config qw(%Config);
55
use ExtUtils::MakeMaker;
66

77
my @extra;
8-
push(@extra, DEFINE => "-DU32_ALIGNMENT_REQUIRED") unless free_u32_alignment();
98
push(@extra, INSTALLDIRS => 'perl') if $] >= 5.008 && $] < 5.012;
109

1110
if ($^O eq 'VMS') {
@@ -39,119 +38,6 @@ WriteMakefile(
3938

4039

4140

42-
sub free_u32_alignment
43-
{
44-
$|=1;
45-
if (exists $Config{d_u32align}) {
46-
print "Perl's config says that U32 access must ";
47-
print "not " unless $Config{d_u32align};
48-
print "be aligned.\n";
49-
return !$Config{d_u32align};
50-
}
51-
52-
if ($^O eq 'VMS' || $^O eq 'MSWin32') {
53-
print "Assumes that $^O implies free alignment for U32 access.\n";
54-
return 1;
55-
}
56-
57-
if ($^O eq 'hpux' && $Config{osvers} < 11.0) {
58-
print "Will not test for free alignment on older HP-UX.\n";
59-
return 0;
60-
}
61-
62-
print "Testing alignment requirements for U32... ";
63-
open(ALIGN_TEST, ">u32align.c") or die "$!";
64-
print ALIGN_TEST <<'EOT'; close(ALIGN_TEST);
65-
/*--------------------------------------------------------------*/
66-
/* This program allocates a buffer of U8 (char) and then tries */
67-
/* to access it through a U32 pointer at every offset. The */
68-
/* program is expected to die with a bus error/seg fault for */
69-
/* machines that do not support unaligned integer read/write */
70-
/*--------------------------------------------------------------*/
71-
72-
#include <stdio.h>
73-
#include "EXTERN.h"
74-
#include "perl.h"
75-
76-
#ifdef printf
77-
#undef printf
78-
#endif
79-
80-
int main(int argc, char** argv, char** env)
81-
{
82-
#if BYTEORDER == 0x1234 || BYTEORDER == 0x4321
83-
volatile U8 buf[] = "\0\0\0\1\0\0\0\0";
84-
volatile U32 *up;
85-
int i;
86-
87-
if (sizeof(U32) != 4) {
88-
printf("sizeof(U32) is not 4, but %d\n", sizeof(U32));
89-
exit(1);
90-
}
91-
92-
fflush(stdout);
93-
94-
for (i = 0; i < 4; i++) {
95-
up = (U32*)(buf + i);
96-
if (! ((*up == 1 << (8*i)) || /* big-endian */
97-
(*up == 1 << (8*(3-i))) /* little-endian */
98-
)
99-
)
100-
{
101-
printf("read failed (%x)\n", *up);
102-
exit(2);
103-
}
104-
}
105-
106-
/* write test */
107-
for (i = 0; i < 4; i++) {
108-
up = (U32*)(buf + i);
109-
*up = 0xBeef;
110-
if (*up != 0xBeef) {
111-
printf("write failed (%x)\n", *up);
112-
exit(3);
113-
}
114-
}
115-
116-
printf("no restrictions\n");
117-
exit(0);
118-
#else
119-
printf("unusual byteorder, playing safe\n");
120-
exit(1);
121-
#endif
122-
return 0;
123-
}
124-
/*--------------------------------------------------------------*/
125-
EOT
126-
127-
my $cc_cmd = "$Config{cc} $Config{ccflags} -I$Config{archlibexp}/CORE";
128-
my $exe = "u32align$Config{exe_ext}";
129-
$cc_cmd .= " -o $exe";
130-
my $rc;
131-
$rc = system("$cc_cmd $Config{ldflags} u32align.c $Config{libs}");
132-
if ($rc) {
133-
print "Can't compile test program. Will ensure alignment to play safe.\n\n";
134-
unlink("u32align.c", $exe, "u32align$Config{obj_ext}");
135-
return 0;
136-
}
137-
138-
$rc = system("./$exe");
139-
unlink("u32align.c", $exe, "u32align$Config{obj_ext}");
140-
141-
return 1 unless $rc;
142-
143-
if ($rc > 0x80) {
144-
(my $cp = $rc) >>= 8;
145-
print "Test program exit status was $cp\n";
146-
}
147-
if ($rc & 0x80) {
148-
$rc &= ~0x80;
149-
unlink("core") && print "Core dump deleted\n";
150-
}
151-
print "signal $rc\n" if $rc && $rc < 0x80;
152-
return 0;
153-
}
154-
15541
BEGIN {
15642
# compatibility with older versions of MakeMaker
15743
my $developer = -d ".git";

cpan/Digest-MD5/t/files.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ EOT
2121
# This is the output of: 'md5sum README MD5.xs rfc1321.txt'
2222
$EXPECT = <<EOT;
2323
2f93400875dbb56f36691d5f69f3eba5 README
24-
9572832f3628e3bebcdd54f47c43dc5a MD5.xs
24+
5b8b4f96bc27a425501307c5461970db MD5.xs
2525
754b9db19f79dbc4992f7166eb0f37ce rfc1321.txt
2626
EOT
2727
}

0 commit comments

Comments
 (0)