Skip to content

Commit cb648b3

Browse files
committed
Replace assertions with explicit runtime checks.
Numerous 'assert' statements were replaced with explicit runtime checks where warranted. Required some changes to the JUnit tests since different exceptions now resulted.
1 parent 06cfbe7 commit cb648b3

File tree

11 files changed

+173
-77
lines changed

11 files changed

+173
-77
lines changed

src/main/java/org/owasp/esapi/StringUtilities.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ public static int getLevenshteinDistance (String s, String t) {
174174
* assert StringUtils.notNullOrEmpty(cipherXform, true) :
175175
* "Cipher transformation may not be null or empty!";
176176
* </pre>
177+
* or an equivalent runtime check that throws an {@code IllegalArgumentException}.
177178
*
178179
* @param str The {@code String} to be checked.
179180
* @param trim If {@code true}, the string is first trimmed before checking
@@ -196,4 +197,4 @@ public static boolean notNullOrEmpty(String str, boolean trim) {
196197
public static boolean isEmpty(String str) {
197198
return str == null || str.length() == 0;
198199
}
199-
}
200+
}

src/main/java/org/owasp/esapi/crypto/CipherSpec.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ private CipherSpec setCipherTransformation(String cipherXform, boolean fromCiphe
153153
throw new IllegalArgumentException("Cipher transformation may not be null or empty string (after trimming whitespace).");
154154
}
155155
int parts = cipherXform.split("/").length;
156+
157+
// Assertion should be okay here as these conditions are checked
158+
// elsewhere and this method is private.
156159
assert ( !fromCipher ? (parts == 3) : true ) :
157160
"Malformed cipherXform (" + cipherXform + "); must have form: \"alg/mode/paddingscheme\"";
158161
if ( fromCipher && (parts != 3) ) {
@@ -165,8 +168,8 @@ private CipherSpec setCipherTransformation(String cipherXform, boolean fromCiphe
165168
// Only algorithm and mode was given.
166169
cipherXform += "/NoPadding";
167170
} else if ( parts == 3 ) {
168-
// All three parts provided. Do nothing. Could happen if not compiled with
169-
// assertions enabled.
171+
// All three parts provided. Do nothing. Could happen if not compiled with
172+
// assertions enabled, but there are explicit checks elsewhere.
170173
; // Do nothing - shown only for completeness.
171174
} else {
172175
// Should never happen unless Cipher implementation is totally screwed up.
@@ -177,6 +180,8 @@ private CipherSpec setCipherTransformation(String cipherXform, boolean fromCiphe
177180
throw new IllegalArgumentException("Malformed cipherXform (" + cipherXform +
178181
"); must have form: \"alg/mode/paddingscheme\"");
179182
}
183+
// Assertion should also be okay here as these conditions are checked
184+
// elsewhere and this method is private.
180185
assert cipherXform.split("/").length == 3 : "Implementation error setCipherTransformation()";
181186
this.cipher_xform_ = cipherXform;
182187
return this;
@@ -404,6 +409,8 @@ protected boolean canEqual(Object other) {
404409
private String getFromCipherXform(CipherTransformationComponent component) {
405410
int part = component.ordinal();
406411
String[] parts = getCipherTransformation().split("/");
412+
// Assertion should also be okay here as these conditions are checked
413+
// elsewhere and this method is private.
407414
assert parts.length == 3 : "Invalid cipher transformation: " + getCipherTransformation();
408415
return parts[part];
409416
}

src/main/java/org/owasp/esapi/crypto/CryptoHelper.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,23 @@ public static SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySiz
138138
{
139139
// These really should be turned into actual runtime checks and an
140140
// IllegalArgumentException should be thrown if they are violated.
141-
assert keyDerivationKey != null : "Key derivation key cannot be null.";
141+
if ( keyDerivationKey == null ) {
142+
throw new IllegalArgumentException("Key derivation key cannot be null.");
143+
}
142144
// We would choose a larger minimum key size, but we want to be
143145
// able to accept DES for legacy encryption needs.
144-
assert keySize >= 56 : "Key has size of " + keySize + ", which is less than minimum of 56-bits.";
145-
assert (keySize % 8) == 0 : "Key size (" + keySize + ") must be a even multiple of 8-bits.";
146-
assert purpose != null;
147-
assert purpose.equals("encryption") || purpose.equals("authenticity") :
148-
"Purpose must be \"encryption\" or \"authenticity\".";
146+
if ( keySize < 56 ) {
147+
throw new IllegalArgumentException("Key has size of " + keySize + ", which is less than minimum of 56-bits.");
148+
}
149+
if ( (keySize % 8) != 0 ) {
150+
throw new IllegalArgumentException("Key size (" + keySize + ") must be a even multiple of 8-bits.");
151+
}
152+
if ( purpose == null ) {
153+
throw new IllegalArgumentException("'purpose' may not be null.");
154+
}
155+
if ( ! ( purpose.equals("encryption") || purpose.equals("authenticity") ) ) {
156+
throw new IllegalArgumentException("Purpose must be \"encryption\" or \"authenticity\".");
157+
}
149158

150159
// DISCUSS: Should we use HmacSHA1 (what we were using) or the HMAC defined by
151160
// Encryptor.KDF.PRF instead? Either way, this is not compatible with
@@ -169,8 +178,12 @@ public static SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySiz
169178
*/
170179
public static boolean isCombinedCipherMode(String cipherMode)
171180
{
172-
assert cipherMode != null : "Cipher mode may not be null";
173-
assert ! cipherMode.equals("") : "Cipher mode may not be empty string";
181+
if ( cipherMode == null ) {
182+
throw new IllegalArgumentException("Cipher mode may not be null");
183+
}
184+
if ( cipherMode.equals("") ) {
185+
throw new IllegalArgumentException("Cipher mode may not be empty string");
186+
}
174187
List<String> combinedCipherModes =
175188
ESAPI.securityConfiguration().getCombinedCipherModes();
176189
return combinedCipherModes.contains( cipherMode );

src/main/java/org/owasp/esapi/crypto/KeyDerivationFunction.java

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ public enum PRF_ALGORITHMS {
106106
// Check if versions of KeyDerivationFunction, CipherText, and
107107
// CipherTextSerializer are all the same.
108108
{
109-
// Ignore error about comparing identical versions and dead code.
110-
// We expect them to be, but the point is to catch us if they aren't.
111-
assert CipherTextSerializer.cipherTextSerializerVersion == CipherText.cipherTextVersion :
112-
"Versions of CipherTextSerializer and CipherText are not compatible.";
113-
assert CipherTextSerializer.cipherTextSerializerVersion == KeyDerivationFunction.kdfVersion :
114-
"Versions of CipherTextSerializer and KeyDerivationFunction are not compatible.";
109+
// Ignore error about comparing identical versions and dead code.
110+
// We expect them to be, but the point is to catch us if they aren't.
111+
if ( CipherTextSerializer.cipherTextSerializerVersion != CipherText.cipherTextVersion ) {
112+
throw new ExceptionInInitializerError("Versions of CipherTextSerializer and CipherText are not compatible.");
113+
}
114+
if ( CipherTextSerializer.cipherTextSerializerVersion != KeyDerivationFunction.kdfVersion ) {
115+
throw new ExceptionInInitializerError("Versions of CipherTextSerializer and KeyDerivationFunction are not compatible.");
116+
}
115117
}
116118

117119
/**
@@ -295,14 +297,30 @@ public SecretKey computeDerivedKey(SecretKey keyDerivationKey, int keySize, Stri
295297
// to section 5.1 of NIST SP 800-108 based on feedback from
296298
// Jeffrey Walton.
297299
//
298-
// These probably should be turned into actual runtime checks and an
299-
// IllegalArgumentException should be thrown if they are violated.
300-
assert keyDerivationKey != null : "Key derivation key cannot be null.";
301-
// We would choose a larger minimum key size, but we want to be
302-
// able to accept DES for legacy encryption needs.
303-
assert keySize >= 56 : "Key has size of " + keySize + ", which is less than minimum of 56-bits.";
304-
assert (keySize % 8) == 0 : "Key size (" + keySize + ") must be a even multiple of 8-bits.";
305-
assert purpose != null && !purpose.equals("") : "Purpose may not be null or empty.";
300+
301+
// These checks used to be assertions prior to ESAPI 2.1.0.1
302+
if ( keyDerivationKey == null ) {
303+
throw new IllegalArgumentException("Key derivation key cannot be null.");
304+
}
305+
// We would choose a larger minimum key size, but we want to allow
306+
// this KDF to be able to accept DES for legacy encryption needs. (Note that
307+
// elsewhere there are checks that disallow *encryption* for key size
308+
// less than Encryptor.EncryptionKeyLength bits, so if they want
309+
// ESAPI to encrypt stuff for DES, they would have to set that up to
310+
// be 56 bits. But I can't think of any valid symmetric encryption
311+
// algorithm whose key size is less than 56 bits that we would ever
312+
// want to allow.
313+
if ( keySize < 56 ) {
314+
throw new IllegalArgumentException("Key has size of " + keySize +
315+
", which is less than minimum of 56-bits.");
316+
}
317+
if ( (keySize % 8) != 0 ) {
318+
throw new IllegalArgumentException("Key size (" + keySize +
319+
") must be a even multiple of 8-bits.");
320+
}
321+
if ( purpose == null || "".equals(purpose) ) {
322+
throw new IllegalArgumentException("Purpose may not be null or empty.");
323+
}
306324

307325
keySize = calcKeySize( keySize ); // Safely convert to whole # of bytes.
308326
byte[] derivedKey = new byte[ keySize ];
@@ -451,7 +469,9 @@ public static PRF_ALGORITHMS convertIntToPRF(int selection) {
451469
* {@code ks} bits.
452470
*/
453471
private static int calcKeySize(int ks) {
454-
assert ks > 0 : "Key size must be > 0 bits.";
472+
if ( ks <= 0 ) {
473+
throw new IllegalArgumentException("Key size must be > 0 bits.");
474+
}
455475
int numBytes = 0;
456476
int n = ks/8;
457477
int rem = ks % 8;

src/main/java/org/owasp/esapi/crypto/PlainText.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public final class PlainText implements Serializable {
4242
*/
4343
public PlainText(String str) {
4444
try {
45-
assert str != null : "String for plaintext cannot be null.";
4645
if ( str == null ) {
4746
throw new IllegalArgumentException("String for plaintext may not be null!");
4847
}
@@ -61,8 +60,11 @@ public PlainText(String str) {
6160
*/
6261
public PlainText(byte[] b) {
6362
// Must allow 0 length arrays though, to represent empty strings.
64-
assert b != null : "Byte array representing plaintext cannot be null.";
65-
// Make copy so mutable byte array b can't change PlainText.
63+
if ( b == null ) {
64+
throw new IllegalArgumentException("Byte array representing plaintext cannot be null.");
65+
}
66+
67+
// Make copy so mutable byte array b can't change PlainText.
6668
rawBytes = new byte[ b.length ];
6769
System.arraycopy(b, 0, rawBytes, 0, b.length);
6870
}
@@ -156,4 +158,4 @@ public void overwrite() {
156158
protected boolean canEqual(Object other) {
157159
return (other instanceof PlainText);
158160
}
159-
}
161+
}

src/main/java/org/owasp/esapi/crypto/SecurityProviderLoader.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,12 @@ public static int insertProviderAt(String algProvider, int pos)
155155
Class<?> providerClass = null;
156156
String clzName = null;
157157
Provider cryptoProvider = null;
158-
assert (pos == -1 || pos >= 1) : "Position pos must be -1 or integer >= 1";
158+
159+
// Yes; I'm aware of DeMorgan's Law, but this is easier to grok.
160+
if ( ! ( (pos == -1 || pos >= 1) ) ) {
161+
throw new IllegalArgumentException("Position pos must be -1 or integer >= 1");
162+
}
163+
159164
try {
160165
// Does algProvider look like a class name?
161166
if (algProvider.indexOf('.') != -1) {

src/main/java/org/owasp/esapi/reference/DefaultSecurityConfiguration.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ public String getEncryptionAlgorithm() {
788788
* {@inheritDoc}
789789
*/
790790
public String getCipherTransformation() {
791+
// Assertion should be okay here. An NPE is likely at runtime if disabled.
791792
assert cipherXformCurrent != null : "Current cipher transformation is null";
792793
return cipherXformCurrent;
793794
}
@@ -796,16 +797,17 @@ public String getCipherTransformation() {
796797
* {@inheritDoc}
797798
*/
798799
public String setCipherTransformation(String cipherXform) {
799-
String previous = getCipherTransformation();
800-
if ( cipherXform == null ) {
801-
// Special case... means set it to original value from ESAPI.properties
802-
cipherXformCurrent = cipherXformFromESAPIProp;
803-
} else {
804-
assert ! cipherXform.trim().equals("") :
805-
"Cipher transformation cannot be just white space or empty string";
806-
cipherXformCurrent = cipherXform; // Note: No other sanity checks!!!
807-
}
808-
return previous;
800+
String previous = getCipherTransformation();
801+
if ( cipherXform == null ) {
802+
// Special case... means set it to original value from ESAPI.properties
803+
cipherXformCurrent = cipherXformFromESAPIProp;
804+
} else {
805+
if ( cipherXform.trim().equals("") ) {
806+
throw new ConfigurationException("Cipher transformation cannot be just white space or empty string");
807+
}
808+
cipherXformCurrent = cipherXform; // Note: No other sanity checks!!!
809+
}
810+
return previous;
809811
}
810812

811813
/**

src/main/java/org/owasp/esapi/util/ByteConversionUtil.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,19 @@ public static byte[] fromLong(long input) {
7777

7878
/**
7979
* Converts a given byte array to an {@code short}. Bytes are expected in
80-
* network byte
81-
* order.
80+
* network byte order.
8281
*
83-
* @param input A network byte-ordered representation of an {@code short}.
82+
* @param input A network byte-ordered representation of an {@code short},
83+
* so exactly 2 bytes are expected.
8484
* @return The {@code short} value represented by the input array.
8585
*/
8686
public static short toShort(byte[] input) {
87-
assert input.length == 2 : "toShort(): Byte array length must be 2.";
87+
if ( input == null ) {
88+
throw new IllegalArgumentException("input: parameter may not be null.");
89+
}
90+
if ( input.length != 2 ) {
91+
throw new IllegalArgumentException("input: Byte array length must be 2.");
92+
}
8893
short output = 0;
8994
output = (short)(((input[0] & 0xff) << 8) | (input[1] & 0xff));
9095
return output;
@@ -95,10 +100,16 @@ public static short toShort(byte[] input) {
95100
* network byte order.
96101
*
97102
* @param input A network byte-ordered representation of an {@code int}.
103+
* Must be exactly 4 bytes.
98104
* @return The {@code int} value represented by the input array.
99105
*/
100106
public static int toInt(byte[] input) {
101-
assert input.length == 4 : "toInt(): Byte array length must be 4.";
107+
if ( input == null ) {
108+
throw new IllegalArgumentException("input: parameter may not be null.");
109+
}
110+
if ( input.length != 4 ) {
111+
throw new IllegalArgumentException("input: Byte array length must be 4.");
112+
}
102113
int output = 0;
103114
output = ((input[0] & 0xff) << 24) | ((input[1] & 0xff) << 16) |
104115
((input[2] & 0xff) << 8) | (input[3] & 0xff);
@@ -110,10 +121,16 @@ public static int toInt(byte[] input) {
110121
* network byte
111122
*
112123
* @param input A network byte-ordered representation of a {@code long}.
124+
* Must be exactly 8 bytes.
113125
* @return The {@code long} value represented by the input array
114126
*/
115127
public static long toLong(byte[] input) {
116-
assert input.length == 8 : "toLong(): Byte array length must be 8.";
128+
if ( input == null ) {
129+
throw new IllegalArgumentException("input: parameter may not be null.");
130+
}
131+
if ( input.length != 8 ) {
132+
throw new IllegalArgumentException("input: Byte array length must be 8.");
133+
}
117134
long output = 0;
118135
output = ((long)(input[0] & 0xff) << 56);
119136
output |= ((long)(input[1] & 0xff) << 48);
@@ -125,4 +142,4 @@ public static long toLong(byte[] input) {
125142
output |= (input[7] & 0xff);
126143
return output;
127144
}
128-
}
145+
}

src/test/java/org/owasp/esapi/crypto/CryptoTokenTest.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,11 @@ public final void testSetUserAccountName() {
183183
try {
184184
ctok.setUserAccountName(null); // Can't be null
185185
// Should get one of these, depending on whether or not assertions are enabled.
186-
fail("Failed to throw expected AssertionError or NullPointerException");
187-
} catch (ValidationException e) {
188-
fail("Wrong type of exception thrown (ValidationException): " + e);
189-
} catch (NullPointerException e) {
190-
; // Success
191-
} catch (AssertionError e) {
186+
fail("Failed to throw expected IllegalArgumentException");
187+
} catch (IllegalArgumentException e) {
192188
; // Success
189+
} catch (Exception e) {
190+
fail("Wrong type of exception thrown: " + e);
193191
}
194192
try {
195193
ctok.setUserAccountName("1773g4l"); // Can't start w/ numeric

src/test/java/org/owasp/esapi/crypto/PlainTextTest.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,11 @@ public final void testNullCase() {
6565
try {
6666
byte[] bytes = null;
6767
PlainText pt = new PlainText(bytes);
68-
assertTrue( pt != null ); // Should never get to here.
69-
fail("testNullCase(): Expected NullPointerException or AssertionError");
70-
} catch (NullPointerException e) {
71-
// Will get this case if assertions are not enabled for PlainText.
72-
// System.err.println("Caught NullPointerException; exception was: " + e);
73-
// e.printStackTrace(System.err);
74-
counter++;
75-
} catch (AssertionError e) {
76-
// Will get this case if assertions *are* enabled for PlainText.
77-
// System.err.println("Caught AssertionError; exception was: " + e);
78-
// e.printStackTrace(System.err);
79-
counter++;
80-
} finally {
81-
assertTrue( counter > 0 );
68+
fail("testNullCase(): Expected IllegalArgumentException");
69+
} catch (IllegalArgumentException e) {
70+
; // Success
71+
} catch (Exception e) {
72+
fail("testNullCase(): Caught unexpected exception: " + e);
8273
}
8374
}
8475

0 commit comments

Comments
 (0)