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);

Reply via email to