Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4921267

(process) Win32Process passes incorrect environment block for empty env

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 5.0
    • 5.0
    • core-libs
    • b24
    • generic
    • solaris_2.6

      When the environment block is empty, the Java_java_lang_Win32Process_create() calls CreateProcess() with one zero "\0", but should call with two zeros "\0\0"

      This was caught by running Rational Purify on an instance of the 1.4.2 hotspot VM and Borland's application server.

      Purify generates the following warning:

      [W] UMR: Uninitialized memory read in CreateProcessA {37 occurrences}
             Reading 1 byte from 0x0d45a9b9 (1 byte at 0x0d45a9b9
      uninitialized)
             Address 0x0d45a9b9 is argument #7 of CreateProcessA
             Address 0x0d45a9b9 is 1 byte into a 4 byte block at 0x0d45a9b8
             Address 0x0d45a9b9 points to a malloc'd block in heap 0x003b0000
             Thread ID: 0xc3c
             Error location
                 CreateProcessA [KERNEL32.dll]
                 Java_java_lang_Win32Process_create [java.dll]
                 ??? [ip=0x02aa7fdd]
                 ??? [ip=0x02aa2c54]
                 ??? [ip=0x02aa00ee]
                 ??? [jvm.dll ip=0x6d3ae143]
                 JVM_FindSignal [jvm.dll]
                 ??? [jvm.dll ip=0x6d3ae057]
                 ??? [jvm.dll ip=0x6d3b1d0a]
                 JNU_NewObjectByName [java.dll]
             Allocation location
                 malloc [MSVCRT.dll]
                 JNU_GetStringPlatformChars [java.dll]
                 JNU_GetStringPlatformChars [java.dll]
                 Java_java_lang_Win32Process_create [java.dll]
                 ??? [ip=0x02aa7fdd]
                 ??? [ip=0x02aa2c54]
                 ??? [ip=0x02aa00ee]
                 ??? [jvm.dll ip=0x6d3ae143]
                 JVM_FindSignal [jvm.dll]
                 ??? [jvm.dll ip=0x6d3ae057]

      This shows that the second byte in argument #7 is read by CreateProcess but never initialized.

      A logical hypothesis is that an empty envcmd '\0' is passed to CreateProcess:

      Win32Process.java:

      .....

             String envstr = null;
             if (env != null) {
                 StringBuffer envbuf = new StringBuffer(256);
                 for (int i = 0; i < env.length; i++) {
                     envbuf.append(env[i]).append('\0');
                 }
                 envstr = envbuf.toString();
             }

      This code doesn't append '\0' if env.length == 0

      Needs to be smth like:

             String envstr = null;
             if (env != null) {
                 StringBuffer envbuf = new StringBuffer(256);
                 for (int i = 0; i < env.length; i++) {
                     envbuf.append(env[i]).append('\0');
                 }
                 if (env.length == 0) envbuf.append(env[i]).append('\0');
                 envstr = envbuf.toString();
             }

      In the current version of Win32Process.java, an empty envstr is generated.

      Later, empty envstr is appended with one '\0' in JNU_GetStringPlatformChars()

      As a result Java_java_lang_Win32Process_create() passes "\0" instead of "\0\0"
      to CreateProcess

      Due, to this CreateProcess tries to read beyond the *envcmd argument and if there's not a '\0' there by chance, it results in reading and processing wrong memory

      In fact this situation might be real when CreateProcess is called multiple times and memory contains non-zeros left after previous operations.

      Borland is observing a crash inside CreateProcess exactly in the scenario when CreateProcess is called frequently. This bug might be the cause of problems that Borland is seeing. Unfortunately, Borland's Enterprise Server is huge and it's too much work to try to create a small test case.
      This bug needs to be fixed regardless.

      To support the argument that two '\0' are needed for an empty environment, here's Win32 API documentation:

      BOOL CreateProcess(...)

      lpEnvironment
      [in] Pointer to an environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.
      An environment block consists of a null-terminated block of null-terminated strings. Each string is in the form:

      name=value
      ......
      Note that an ANSI environment block is terminated by two zero bytes: one for the last string, one more to terminate the block.

            martin Martin Buchholz
            ksoshals Kirill Soshalskiy (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: