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

NonWriteable system properties are actually writeable

XMLWordPrintable

    • 9
    • b25

        The SystemProperty code used for VM argument parsing was reworked in Java 9 as part of the module system updates. In Java 8 the set_value() method was defined as follows:

        bool set_value(char *value) {
            if (writeable()) {
              if (_value != NULL) {
                FreeHeap(_value);
              }
              _value = AllocateHeap(strlen(value)+1, mtInternal);
              if (_value != NULL) {
                strcpy(_value, value);
              }
              return true;
            }
            return false;
          }

        so we can only update a writeable flag.

        In Java 9 this was refactored so that SystemProperty extends PathString, which contains a simple set_value method that always sets the value:

        bool PathString::set_value(const char *value) {
          if (_value != NULL) {
            FreeHeap(_value);
          }
          _value = AllocateHeap(strlen(value)+1, mtArguments);
          assert(_value != NULL, "Unable to allocate space for new path value");
          if (_value != NULL) {
            strcpy(_value, value);
          } else {
            // not able to allocate
            return false;
          }
          return true;
        }

        and SystemProperty added a new method:

         // A system property should only have its value set
          // via an external interface if it is a writeable property.
          // The internal, non-writeable property jdk.boot.class.path.append
          // is the only exception to this rule. It can be set externally
          // via -Xbootclasspath/a or JVMTI OnLoad phase call to AddToBootstrapClassLoaderSearch.
          // In those cases for jdk.boot.class.path.append, the base class
          // set_value and append_value methods are called directly.
          bool set_writeable_value(const char *value) {
            if (writeable()) {
              return set_value(value);
            }
            return false;
          }

        The intent was obviously that in general set_writeable_value should be used to attempt to set the value, but the general property handling code was not updated:

        // This add maintains unique property key in the list.
        void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v,
                                                PropertyAppendable append, PropertyWriteable writeable,
                                                PropertyInternal internal) {
          if (plist == NULL)
            return;

          // If property key exist then update with new value.
          SystemProperty* prop;
          for (prop = *plist; prop != NULL; prop = prop->next()) {
            if (strcmp(k, prop->key()) == 0) {
              if (append == AppendProperty) {
                prop->append_value(v);
              } else {
                prop->set_value(v);
              }
              return;
            }
          }

          PropertyList_add(plist, k, v, writeable == WriteableProperty, internal == InternalProperty);
        }

        Consequently whether the flag is writeable or not is ignored and it will always be appended or set. As a result the user can override non-writable system properties on the command-line e.g:

        public class JavaProps {
          public static void main(String[] args) {
            System.out.println(System.getProperty(args[0]));
          }
        }

        > java9 JavaProps java.vm.name
        Java HotSpot(TM) 64-Bit Server VM
        > java9 -Djava.vm.name=MyVM JavaProps java.vm.name
        MyVM

        Property was re-defined by the user! Whereas in Java 8:

        > java JavaProps java.vm.name
        OpenJDK 64-Bit Server VM
        > java -Djava.vm.name=MyVM JavaProps java.vm.name
        OpenJDK 64-Bit Server VM

              dholmes David Holmes
              dholmes David Holmes
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: