New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make boolean conversion strict #22200
Changes from 1 commit
b5d642b
e705d96
9fb7ea1
db3fd5e
c1b9df1
cbb3822
c09b301
665554d
1ee2db4
f7337ba
206adfa
fcfce6c
8de2eb4
6144f36
22aabf2
978f047
33af9f1
55b7e2b
0577acc
4c90110
f4a2f64
0f91b13
61f3912
bdc029e
fc8f39a
4523e55
File filter...
Jump to…
Make boolean conversion strict
This PR removes all leniency in the conversion of Strings to booleans: "true" is converted to the boolean value `true`, "false" is converted to the boolean value `false`. Everything else raises an error.
- Loading branch information
@@ -19,34 +19,28 @@ | ||
|
||
package org.elasticsearch.common; | ||
|
||
public class Booleans { | ||
public final class Booleans { | ||
private Booleans() { | ||
throw new AssertionError("No instances intended"); | ||
} | ||
|
||
/** | ||
* Returns <code>false</code> if text is in <tt>false</tt>, <tt>0</tt>, <tt>off</tt>, <tt>no</tt>; else, true | ||
* Parses a char[] representation of a boolean value to <code>boolean</code>. | ||
* | ||
* @return <code>true</code> iff the sequence of chars is "true", <code>false</code> iff the sequence of chars is "false" or the | ||
* provided default value iff either text is <code>null</code> or length == 0. | ||
* @throws IllegalArgumentException if the string cannot be parsed to boolean. | ||
*/ | ||
public static boolean parseBoolean(char[] text, int offset, int length, boolean defaultValue) { | ||
// TODO: the leniency here is very dangerous: a simple typo will be misinterpreted and the user won't know. | ||
// We should remove it and cutover to https://github.com/rmuir/booleanparser | ||
if (text == null || length == 0) { | ||
return defaultValue; | ||
} else { | ||
return parseBoolean(new String(text, offset, length)); | ||
} | ||
if (length == 1) { | ||
return text[offset] != '0'; | ||
} | ||
if (length == 2) { | ||
return !(text[offset] == 'n' && text[offset + 1] == 'o'); | ||
} | ||
if (length == 3) { | ||
return !(text[offset] == 'o' && text[offset + 1] == 'f' && text[offset + 2] == 'f'); | ||
} | ||
if (length == 5) { | ||
return !(text[offset] == 'f' && text[offset + 1] == 'a' && text[offset + 2] == 'l' && text[offset + 3] == 's' && text[offset + 4] == 'e'); | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* returns true if the a sequence of chars is one of "true","false","on","off","yes","no","0","1" | ||
* returns true iff the sequence of chars is one of "true","false". | ||
* | ||
* @param text sequence to check | ||
* @param offset offset to start | ||
@@ -56,77 +50,61 @@ public static boolean isBoolean(char[] text, int offset, int length) { | ||
if (text == null || length == 0) { | ||
return false; | ||
} | ||
if (length == 1) { | ||
return text[offset] == '0' || text[offset] == '1'; | ||
} | ||
if (length == 2) { | ||
return (text[offset] == 'n' && text[offset + 1] == 'o') || (text[offset] == 'o' && text[offset + 1] == 'n'); | ||
} | ||
if (length == 3) { | ||
return (text[offset] == 'o' && text[offset + 1] == 'f' && text[offset + 2] == 'f') || | ||
(text[offset] == 'y' && text[offset + 1] == 'e' && text[offset + 2] == 's'); | ||
} | ||
if (length == 4) { | ||
return (text[offset] == 't' && text[offset + 1] == 'r' && text[offset + 2] == 'u' && text[offset + 3] == 'e'); | ||
} | ||
if (length == 5) { | ||
return (text[offset] == 'f' && text[offset + 1] == 'a' && text[offset + 2] == 'l' && text[offset + 3] == 's' && text[offset + 4] == 'e'); | ||
} | ||
return false; | ||
return isBoolean(new String(text, offset, length)); | ||
} | ||
|
||
public static boolean isBoolean(String value) { | ||
return isExplicitFalse(value) || isExplicitTrue(value); | ||
} | ||
|
||
/*** | ||
/** | ||
* Parses a string representation of a boolean value to <code>boolean</code>. | ||
* | ||
* @return true/false | ||
* throws exception if string cannot be parsed to boolean | ||
* @return <code>true</code> iff the provided value is "true". <code>false</code> iff the provided value is "false". | ||
* @throws IllegalArgumentException if the string cannot be parsed to boolean. | ||
*/ | ||
public static Boolean parseBooleanExact(String value) { | ||
boolean isFalse = isExplicitFalse(value); | ||
if (isFalse) { | ||
public static boolean parseBoolean(String value) { | ||
if (isExplicitFalse(value)) { | ||
return false; | ||
} | ||
boolean isTrue = isExplicitTrue(value); | ||
if (isTrue) { | ||
if (isExplicitTrue(value)) { | ||
return true; | ||
} | ||
|
||
throw new IllegalArgumentException("Failed to parse value [" + value + "] cannot be parsed to boolean [ true/1/on/yes OR false/0/off/no ]"); | ||
throw new IllegalArgumentException("Failed to parse value [" + value + "] as boolean (only 'true' and 'false' are allowed)"); | ||
|
||
} | ||
|
||
public static Boolean parseBoolean(String value, Boolean defaultValue) { | ||
if (value == null) { // only for the null case we do that here! | ||
return defaultValue; | ||
} | ||
return parseBoolean(value, false); | ||
} | ||
/** | ||
* Returns <code>true</code> iff the value is neither of the following: | ||
* <tt>false</tt>, <tt>0</tt>, <tt>off</tt>, <tt>no</tt> | ||
* otherwise <code>false</code> | ||
* | ||
* @param value text to parse. | ||
* @param defaultValue The default value to return if the provided value is <code>null</code>. | ||
* @return see {@link #parseBoolean(String)} | ||
*/ | ||
public static boolean parseBoolean(String value, boolean defaultValue) { | ||
if (value == null) { | ||
if (value == null || value.length() == 0) { | ||
return defaultValue; | ||
} | ||
return parseBoolean(value); | ||
} | ||
|
||
public static Boolean parseBoolean(String value, Boolean defaultValue) { | ||
dakrone
Member
|
||
if (value == null || value.length() == 0) { | ||
dakrone
Member
|
||
return defaultValue; | ||
} | ||
return !(value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no")); | ||
return parseBoolean(value); | ||
} | ||
|
||
/** | ||
* Returns <code>true</code> iff the value is either of the following: | ||
* <tt>false</tt>, <tt>0</tt>, <tt>off</tt>, <tt>no</tt> | ||
* otherwise <code>false</code> | ||
* @return <code>true</code> iff the value is <tt>false</tt>, otherwise <code>false</code>. | ||
*/ | ||
public static boolean isExplicitFalse(String value) { | ||
|
||
return value != null && (value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no")); | ||
return value != null && value.equals("false"); | ||
|
||
} | ||
|
||
/** | ||
* Returns <code>true</code> iff the value is either of the following: | ||
* <tt>true</tt>, <tt>1</tt>, <tt>on</tt>, <tt>yes</tt> | ||
* otherwise <code>false</code> | ||
* @return <code>true</code> iff the value is <tt>true</tt>, otherwise <code>false</code> | ||
*/ | ||
public static boolean isExplicitTrue(String value) { | ||
return value != null && (value.equals("true") || value.equals("1") || value.equals("on") || value.equals("yes")); | ||
return value != null && value.equals("true"); | ||
} | ||
|
||
} |
@@ -196,7 +196,13 @@ public long paramAsLong(String key, long defaultValue) { | ||
|
||
@Override | ||
public boolean paramAsBoolean(String key, boolean defaultValue) { | ||
return Booleans.parseBoolean(param(key), defaultValue); | ||
String rawParam = param(key); | ||
// treat the sheer presence of a parameter as "true" | ||
nik9000
Contributor
|
||
if (rawParam != null && rawParam.length() == 0) { | ||
return true; | ||
} else { | ||
return Booleans.parseBoolean(rawParam, defaultValue); | ||
} | ||
} | ||
|
||
@Override | ||

I think
"Failed to parse value [" + value + "] as only [true] or [false] are allowed."
is a easier to read.