[rt.cpan.org #120038] [PATCH] Fix build for VS2015 (VC++ 14)

"Steve Hay via RT" <[email protected]>
Newsgroups gmane.comp.lang.perl.par
Message-ID <[email protected]>
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: [email protected]
      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!
pp-vc14.patch (text/x-diff, 1.8 KB)
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 [email protected] -outputresource:$@;1';
+        $mt_cmd = 'if exist [email protected] mt -nologo -manifest [email protected] -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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.