From 49c7681c58dd6dbd85afcdb9884a5dc8ed766192 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 11 Mar 2013 12:34:31 -0400 Subject: [PATCH] Windows install: check DLL type When copying dlls, make sure to only consider DLLs whose type matches the type of what is loading them. --- ChangeLog | 7 +++++++ TODO | 6 ------ copy_dlls | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f4c71a4..c00f7a18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-03-11 Jay Berkenbilt + + * When creating Windows binary distributions, make sure to only + copy DLLs of the correct type. The ensures that the 32-bit + distributions contain 32-bit DLLs and the 64-bit distributions + contain 64-bit DLLs. + 2013-03-07 Jay Berkenbilt * Use ./install-sh (already present) instead of "install -c" to diff --git a/TODO b/TODO index 832e7ab1..497096c3 100644 --- a/TODO +++ b/TODO @@ -22,12 +22,6 @@ - See ../misc/broken-files - * The mingw64 package is broken. It contains a 32-bit version of - libstdc++-6.dll. Fix this and make sure it can never happen - again. Ideally we should test in a sandbox, but failing that, at - least run file on all the dlls to make sure they are of the right - type. - * Add to documentation, and mention this documentation in README.maintainer: diff --git a/copy_dlls b/copy_dlls index e93f1613..c85e44b9 100755 --- a/copy_dlls +++ b/copy_dlls @@ -12,6 +12,7 @@ my ($file, $destdir, $objdump) = @ARGV; my $filedir = dirname($file); my %dlls = (); +my $format = undef; open(O, "$objdump -p $file|") or die "$whoami: can't run objdump\n"; while () { @@ -22,11 +23,21 @@ while () next if $dll =~ m/^(kernel32|user32|msvcrt)\.dll$/; $dlls{$dll} = 1; } + elsif (m/^Magic.*\((PE.+?)\)/) + { + $format = $1; + } } close(O); +if (! defined $format) +{ + die "$whoami: can't determine format of $file\n"; +} -# Search the file's directory, the current directory, and the path for -# dlls since that's what Windows does. +# Search the directories named in the file's manifest (if present), +# the file's directory, the current directory, and the path for dlls +# since that's what Windows does. Be sure to only capture compatible +# DLLs. my $sep = ($^O eq 'MSWin32' ? ';' : ':'); my @path = ($filedir, '.', split($sep, $ENV{'PATH'})); if (-f "$file.manifest") @@ -41,7 +52,7 @@ foreach my $dll (sort keys %dlls) my $found = 0; foreach my $dir (@path) { - if (-f "$dir/$dll") + if ((-f "$dir/$dll") && is_format("$dir/$dll", $format)) { push(@final, "$dir/$dll"); $found = 1; @@ -68,6 +79,31 @@ foreach my $f (@final) die "$whoami: copy $f to $destdir failed\n"; } +sub is_format +{ + my ($file, $format) = @_; + $file =~ s,\\,/,g; + # Special case: msvc*.dll seem to be able to behave both as 32-bit + # and 64-bit DLLs. Either that, or this logic is wrong for those + # DLLs and it doesn't matter because they're already installed on + # my test system (which doesn't have msvc installed on it). + if ($file =~ m,/msvc,i) + { + return 1; + } + my $result = 0; + my $file_format = `file $file`; + print "$file $format $file_format\n"; + if ($? == 0) + { + if ($file_format =~ m/\Q${format}\E executable/) + { + $result = 1; + } + } + $result; +} + sub get_manifest_dirs { # Find all system directories in which to search for DLLs based on