Revision2: Corrected: RFR 8059557 (XL): Validate JVM Command-Line Flag Arguments
Kim Barrett
kim.barrett at oracle.com
Thu May 28 22:10:15 UTC 2015
On May 27, 2015, at 5:28 PM, Gerard Ziemski <gerard.ziemski at oracle.com> wrote:
>
> Here is a revision 2 of the feature taking into account feedback from Dmitry, David, Kim and Alexander.
>
> […]
> References:
>
> Webrev: http://cr.openjdk.java.net/~gziemski/8059557_rev2
> note: due to "awk" limit of 50 pats the Frames diff is not available for "src/share/vm/runtime/arguments.cpp”
This is only a partial review. I haven't taken a detailed look at
arguments.[ch]pp or globals.cpp, and haven't looked at the new range
and constraint checking or the tests. But I'm running out of steam
for today, and won't be able to get back to this until Monday, so
giving you what I have so far.
------------------------------------------------------------------------------
Many files are being changed to #include globals.hpp just to get
access to Flag values. Perhaps globals.hpp ought to be split up.
This probably ought to be addressed as a separate CR though.
------------------------------------------------------------------------------
src/share/vm/runtime/globals.hpp
362 void print_on(outputStream* st, bool printRanges = false, bool withComments = false );
458 static void printFlags(outputStream* out, bool withComments, bool printRanges = false);
Why are the withComments and printRanges arguments in different
orders?
Just in general, multiple bool arguments tend to be problematic for
understanding the using code. Common alternative is to use enums.
Another common alternative (used often in hotspot) is to use comments
in the calls; that helps the reader, so long as the (not checked by
compiler) order is actually as commented. Calls should at least be
commented, for consistency with other hotspot usage.
------------------------------------------------------------------------------
src/share/vm/runtime/init.cpp
145 if (PrintFlagsFinal) {
146 CommandLineFlags::printFlags(tty, false);
147 }
148 if (PrintFlagsRanges) {
149 CommandLineFlags::printFlags(tty, false, true);
150 }
[145-147 from original, 148-150 added]
Really print the flags twice if both options are provided? I was expecting something like:
if (PrintFlagsFinal || PrintFlagsRanges) {
CommandLineFlags::printFlags(tty, false, PrintFlagsRanges);
}
------------------------------------------------------------------------------
src/share/vm/runtime/os.hpp
167 // A strlcat like API for safe string concatenation of 2 NULL limited C strings
168 // strlcat is not guranteed to exist on all platforms, so we implement our own
169 static void strlcat(char *dst, const char *src, size_t size) {
170 register char *_dst = dst;
171 register char *_src = (char *)src;
172 register int _size = (int)size;
173
174 while ((_size-- != 0) && (*_dst != '\0')) {
175 _dst++;
176 }
177 while ((_size-- != 0) && (*_src != '\0')) {
178 *_dst = *_src;
179 _dst++; _src++;
180 }
181 *_dst = '\0';
182 }
Several problems here:
1. In the description comment: NULL is a pointer. The string
terminator is NUL.
2. Use of "register" storage class specifiers: The "register" storage
class is deprecated in C++11 and slated for removal in C++17.
Compilers have for a long time been parsing it but otherwise ascribing
no special meaning beyond specifying automatic storage allocation.
3. There's no reason for any of the casts.
4. Use of _ prefixed names is generally reserved for member variables
in hotspot. There's no need for these additional variables anyway,
after elimination of the register storage class usage and the
inappropriate casts.
5. This will buffer overrun if strlen(dst) >= size. This differs from
BSD strlcat.
6. Unlike BSD strlcat, this doesn't provide a return value that allows
the caller to detect truncation. I would think most real uses aught
to care about that case, though I haven't audited uses in this change
set yet.
------------------------------------------------------------------------------
src/share/vm/services/classLoadingService.cpp
184 bool succeed = (CommandLineFlags::boolAtPut((char*)"TraceClassLoading", &verbose, Flag::MANAGEMENT) == Flag::SUCCESS);
185 assert(succeed, "Setting TraceClassLoading flag fails");
I'm surprised this doesn't produce an unused variable warning in a
product build.
Rather than converting the boolAtPut result to a bool success and
asserting it to be true, it would be better to capture the resulting
Flag::Error, test for success in the assert, and report the failure
reason in the assert message.
Pre-existing defect: Unnecessary cast.
Possible pre-existing defect: I don't understand exactly how these
service functions are used, but I wonder whether an assertion is
really the appropriate method to check for failure to perform the
operation.
Similarly for line 195.
Similarly for src/share/vm/services/memoryService.cpp:521
------------------------------------------------------------------------------
src/share/vm/services/writeableFlags.cpp
62 if (error != Flag::SUCCESS) {
...
93 }
Rather than if != success and indenting the whole function, I think it
would be more readable if this were
if (error == Flag::SUCCESS) {
return;
}
...
------------------------------------------------------------------------------
src/share/vm/services/writeableFlags.cpp
88 buffer[79] = '\0';
What's this about?
------------------------------------------------------------------------------
src/share/vm/services/writeableFlags.cpp
108 Flag::Error err = CommandLineFlags::boolAtPut((char*)name, &value, origin);
125 Flag::Error err = CommandLineFlags::intxAtPut((char*)name, &value, origin);
142 Flag::Error err = CommandLineFlags::uintxAtPut((char*)name, &value, origin);
... and so on ...
Pre-existing inappropriate casts.
More information about the hotspot-dev
mailing list