Mon Jan 30 06:18:25 2017: Request 120038 was acted upon.
Transaction: Ticket created by SHAY
       Queue: PAR-Packer
     Subject: [PATCH] Fix build for VS2015 (VC++ 14)
   Broken in: (no value)
    Severity: (no value)
       Owner: Nobody
  Requestors: s...@cpan.org
      Status: new
 Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=120038 >


Using the patch called "perl-5.24.1-vc14.patch" attached to rt.perl.org #125714 
I am able to build perl using the latest Visual Studio 2015 (VC++ 14.0), but 
PAR::Packer fails to build with that perl and compiler.

The attached patch fixes this. I found and fixed three problems:

1. Manifest files are not generated by default (and haven't been for a while 
now, actually) so they should not be embedded if not present. 
ExtUtils::MakeMaker and other similar tools already have similar code.

2. The new VC++ has a massively rewritten CRT and now defines some printf type 
functions inline, so the #define of snprint is no longer required.

3. I found that boot.exe was crashing on exit with the following call stack:

ntdll.dll!RtlpFreeHeap() Unknown
ntdll.dll!RtlFreeHeap() Unknown
ucrtbase.dll!___acrt_add_locale_ref() Unknown
ucrtbase.dll!___dcrt_uninitialize_environments_nolock() Unknown
ucrtbase.dll!___acrt_uninitialize_lowio() Unknown
ucrtbase.dll!___acrt_execute_uninitializers() Unknown
ucrtbase.dll!___acrt_add_locale_ref() Unknown
ucrtbase.dll!___acrt_DllMain@12() Unknown
ucrtbase.dll!___acrt_DllMain@12() Unknown
ntdll.dll!_LdrxCallInitRoutine@16() Unknown
ntdll.dll!LdrpCallInitRoutine() Unknown
ntdll.dll!LdrShutdownProcess() Unknown
ntdll.dll!RtlExitUserProcess() Unknown
kernel32.dll!_ExitProcessImplementation@4() Unknown
ucrtbase.dll!_swprintf() Unknown
ucrtbase.dll!_swprintf() Unknown
ucrtbase.dll!_exit() Unknown
> boot.exe!main(int argc, char * * argv, char * * env) Line 234 C

That suggested a problem freeing memory, and code in env.c's par_setenv() 
function looked like an obvious candidate for causing corruption because of the 
way that it mallocs/reallocs chunks of the environ array, which is really 
managed by the CRT. I don't know why it worked in the past and breaks now, but 
documentation of _putenv() at 
https://msdn.microsoft.com/en-us/library/83zh4e6k.aspx does warn "Do not change 
an environment entry directly: instead, use _putenv or _wputenv to change it. 
In particular, direct freeing elements of the _environ[] global array might 
lead to invalid memory being addressed." Presumably the change is again to do 
with the CRT rewrite. Anyway, changing par_setenv() to simply call _putenv() on 
Windows fixes the crash.

Please consider this patch for your next release of PAR::Packer.

Many thanks for keeping this great tool alive!
diff --binary -ruN PAR-Packer-1.036.orig/myldr/Makefile.PL PAR-Packer-1.036/myldr/Makefile.PL
--- PAR-Packer-1.036.orig/myldr/Makefile.PL	2016-09-17 22:30:46.000000000 +0100
+++ PAR-Packer-1.036/myldr/Makefile.PL	2017-01-30 10:59:44.416670100 +0000
@@ -100,7 +100,7 @@
     # Embed the manifest file for VC 2005 (aka VC8) or higher, but not for the
     # 64-bit Platform SDK compiler.
     if( $Config{ptrsize} == 4 and $Config{ccversion} =~ /^(\d+)/ and $1 >= 14 ) {
-        $mt_cmd = 'mt -nologo -manifest $@.manifest -outputresource:$@;1';
+        $mt_cmd = 'if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1';
     } else {
         $mt_cmd = '-$(NOOP)';
     }
diff --binary -ruN PAR-Packer-1.036.orig/myldr/env.c PAR-Packer-1.036/myldr/env.c
--- PAR-Packer-1.036.orig/myldr/env.c	2016-09-17 22:30:46.000000000 +0100
+++ PAR-Packer-1.036/myldr/env.c	2017-01-30 11:03:16.586930700 +0000
@@ -94,6 +94,14 @@
 	const char *name;
 	register const char *value;
 {
+#ifdef WIN32
+	char* p = (char*)malloc((size_t)(strlen(name) + strlen(value) + 2));
+	if (!p)
+		return (-1);
+	sprintf(p, "%s=%s", name, value);
+	_putenv(p);
+	return (0);
+#else
 	extern char **environ;
 	static int alloced = 0;         /* if allocated space before */
 	register char *c;
@@ -137,6 +145,7 @@
 	for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
 	for (*c++ = '='; (*c++ = *value++););
 	return (0);
+#endif
 }
 
 /*
diff --binary -ruN PAR-Packer-1.036.orig/myldr/mktmpdir.h PAR-Packer-1.036/myldr/mktmpdir.h
--- PAR-Packer-1.036.orig/myldr/mktmpdir.h	2016-09-17 22:30:46.000000000 +0100
+++ PAR-Packer-1.036/myldr/mktmpdir.h	2017-01-30 10:59:08.508541800 +0000
@@ -1,5 +1,7 @@
 #ifdef _MSC_VER
-#  define snprintf _snprintf
+#  if _MSC_VER < 1900
+#    define snprintf _snprintf
+#  endif
 #  if _MSC_VER < 1500
 #    define vsnprintf _vsnprintf
 #  endif

Reply via email to