There is an ancient bug in vms/vms.c in the code that does the initial load of the %ENV hash. The sequence necessary to exercise the bug is to first initialize an environment variable to a zero-length string, then do something (such as C<keys %ENV>) that invokes prime_env_iter, and finally do something that depends on the length of the value initialized at the outset. In this last step you get a length of one instead of zero because you are getting the length of a placeholder stored in the native environment's value string (the logical name's equivalence string). The following one-liner illustrates:
$ perl -e "$ENV{X}=q{}; $a=length($ENV{X}); @k=keys %ENV; $b=length($ENV{X}); print qq{$a\t$b\n};"
0 1
The attached patch against blead fixes the bug and causes no new test failures. The bug was causing a failure in lib/I18N/LangTags/t/80_all_env.t in both blead and maint for reasons that had only to do with the %ENV infrastructure described above and nothing at all to do with I18N::LangTags (thanks to Sean Burke for patiently wading through a red herring bug report).
--- vms/vms.c;-0 Tue Jul 6 23:12:33 2004
+++ vms/vms.c Thu Jul 8 09:01:34 2004
@@ -665,7 +665,21 @@ prime_env_iter(void)
continue;
}
PERL_HASH(hash,key,keylen);
- sv = newSVpvn(cp2,cp1 - cp2 + 1);
+
+ if (cp1 == cp2 && *cp2 == '.') {
+ /* A single dot usually means an unprintable character, such as a null
+ * to indicate a zero-length value. Get the actual value to make sure.
+ */
+ char lnm[LNM$C_NAMLENGTH+1];
+ char eqv[LNM$C_NAMLENGTH+1];
+ strncpy(lnm, key, keylen);
+ int trnlen = vmstrnenv(lnm, eqv, 0, fildev, 0);
+ sv = newSVpvn(eqv, strlen(eqv));
+ }
+ else {
+ sv = newSVpvn(cp2,cp1 - cp2 + 1);
+ }
+
SvTAINTED_on(sv);
hv_store(envhv,key,keylen,sv,hash);
hv_store(seenhv,key,keylen,&PL_sv_yes,hash);
