Revision2: Corrected: RFR 8059557 (XL): Validate JVM Command-Line Flag Arguments

Derek White derek.white at oracle.com
Wed Jun 3 21:29:54 UTC 2015


Hi Gerard,

Thanks for the explanations. Just quoting still-open issues below:

On 6/2/15 4:09 PM, Gerard Ziemski wrote:
> Thank you Derek very much for your feedback. Please see my answers inline:
>
>> Line 2036, 2041:
>>    - Set status to false instead of returning directly?
> I’m sorry, which file do those lines refer to?
In arguments.cpp, in bool Arguments::check_vm_args_consistency(). My 
point is that the pre-existing control flow was to set  "status = false" 
and continue checking flags, not to bail out when the first failure 
occurred.

>> Line 2827 (existing); Change "K" -> "1*K" for consistency.
> Line 2827 in gobals.hpp or is it a different file?

Never mind. I should have been talking about arguments.cpp, but I must 
have miss-typed the line #, and now I can't find it. There are actually 
lots of naked "K"s around, so even though I'm not a fan, I can't 
complain about consistency.

> - Shouldn't the default implementations for 
> CommandLineFlagConstraint::apply_XXX() return failure, not success?
> I looked at it from the point of view of the more likely scenario, which is assume success, unless a fault detected.
>
> If we did do this, though, then instead of:
>
> Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
>    if ((CommandLineFlags::finishedInitializing()) && (*value > MaxHeapFreeRatio)) {
>      if (verbose == true) {
>        jio_fprintf(defaultStream::error_stream(),
>                    "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
>                    "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
>                    *value, MaxHeapFreeRatio);
>      }
>      return Flag::VIOLATES_CONSTRAINT;
>    } else {
>      return Flag::SUCCESS;
>    }
> }
>
> we’d have:
>
> Flag::Error MinHeapFreeRatioConstraintFunc(bool verbose, uintx* value) {
>    Flag::Error error = Flag::VIOLATES_CONSTRAINT;
>    if ((CommandLineFlags::finishedInitializing()) && (*value > MaxHeapFreeRatio)) {
>      if (verbose == true) {
>        jio_fprintf(defaultStream::error_stream(),
>                    "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
>                    "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
>                    *value, MaxHeapFreeRatio);
>      }
>    } else {
>      error = Flag::SUCCESS;
>    }
>    return error;
> }
>
> which is not as nice, in my opinion.
I'm not sure we're talking about the same thing.

Looking at commandLineFlagConstraintList.hpp:

   55   virtual Flag::Error apply_bool(bool* value, bool verbose = true) { return Flag::SUCCESS; };

I had the question "What happens if someone calls a version of the apply 
function (apply_FOO) that doesn't match the type of the constraint?"

For example, look at CommandLineFlagConstraint::apply_bool(). What if 
the flag is really an "int", and it has a constraint? So the constraint 
is of type CommandLineFlagConstraint_intx. If apply_bool() is ever 
called on a CommandLineFlagConstraint_intx it will return Flag::SUCCESS. 
This is wrong - it violates the implicit constraint that the type of the 
value matches the type of the flag.

It looks like the callers ensure that constraint's type matches the 
value's type, so the default apply_bool() is never called. I'm not sure 
why you'd have to re-write MinHeapFreeRatioConstraint() (as describe 
above) no matter what the default value of apply_bool() is.

But if some later code forgets to match the types correctly, I think 
we're better off calling shouldNotReachHere() in the default methods.

I think Kim had a similar question about default check_FOO() methods in 
commandLineFlagRangeList.hpp.

   47   virtual Flag::Error check_intx(intx value, bool verbose = true) { return Flag::SUCCESS; }
   48   virtual Flag::Error check_uintx(uintx value, bool verbose = true) { return Flag::SUCCESS; }
   49   virtual Flag::Error check_uint64_t(uint64_t value, bool verbose = true) { return Flag::SUCCESS; }
   50   virtual Flag::Error check_size_t(size_t value, bool verbose = true) { return Flag::SUCCESS; }
   51   virtual Flag::Error check_double(double value, bool verbose = true) { return Flag::SUCCESS; }

Thanks for reading this far!

  - Derek

Notes:

    apply_bool() is called in two places.

    1) apply_constraint_and_check_range_bool()
         - Do the callers do a type check?
             - Yes. On type mismatch:
                - CommandLineFlags::boolAtPut(const char* name, size_t
    len, bool* value, Flag::Flags origin) returns  Flag::WRONG_FORMAT.
                - CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType
    flag, bool value, Flag::Flags origin) will fail a "guarantee". Not
    sure if that's best idea.

    2) CommandLineFlags::check_all_ranges_and_constraints()
            - Caller basically does a type case, so apply_bool() is
    never called with wrong type flag.

   55   virtual Flag::Error apply_bool(bool* value, bool verbose = true) { return Flag::SUCCESS; };
   56   virtual Flag::Error apply_intx(intx* value, bool verbose = true) { return Flag::SUCCESS; };
   57   virtual Flag::Error apply_uintx(uintx* value, bool verbose = true) { return Flag::SUCCESS; };
   58   virtual Flag::Error apply_uint64_t(uint64_t* value, bool verbose = true) { return Flag::SUCCESS; };
   59   virtual Flag::Error apply_size_t(size_t* value, bool verbose = true) { return Flag::SUCCESS; };
   60   virtual Flag::Error apply_double(double* value, bool verbose = true) { return Flag::SUCCESS;

These are never called (because the callers ensure that constraint's 
type matches the "value" type), so it shouldn't matter if they return 
Flag::SUCCESS or Flag::INVALID_FLAG.




More information about the hotspot-dev mailing list